blob: fd1719c7e7fe2249e32887653eebd14fcbb292eb [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
764#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
765/*
766 * FUNCTION: wlan_hdd_send_avoid_freq_event
767 * This is called when wlan driver needs to send vendor specific
768 * avoid frequency range event to userspace
769 */
770int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
771 tHddAvoidFreqList *pAvoidFreqList)
772{
773 struct sk_buff *vendor_event;
774
775 ENTER();
776
777 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700778 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800779 return -EINVAL;
780 }
781
782 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700783 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784 return -EINVAL;
785 }
786
787 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
788 NULL,
789 sizeof(tHddAvoidFreqList),
790 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
791 GFP_KERNEL);
792 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700793 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800794 return -EINVAL;
795 }
796
797 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
798 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
799
800 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
801
802 EXIT();
803 return 0;
804}
805#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
806
807/* vendor specific events */
808static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
809#ifdef FEATURE_WLAN_CH_AVOID
810 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
811 .vendor_id =
812 QCA_NL80211_VENDOR_ID,
813 .subcmd =
814 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
815 },
816#endif /* FEATURE_WLAN_CH_AVOID */
817
818#ifdef WLAN_FEATURE_NAN
819 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
820 .vendor_id =
821 QCA_NL80211_VENDOR_ID,
822 .subcmd =
823 QCA_NL80211_VENDOR_SUBCMD_NAN
824 },
825#endif
826
827#ifdef WLAN_FEATURE_STATS_EXT
828 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
829 .vendor_id =
830 QCA_NL80211_VENDOR_ID,
831 .subcmd =
832 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
833 },
834#endif /* WLAN_FEATURE_STATS_EXT */
835#ifdef FEATURE_WLAN_EXTSCAN
836 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
837 .vendor_id =
838 QCA_NL80211_VENDOR_ID,
839 .subcmd =
840 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
841 },
842 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
843 .vendor_id =
844 QCA_NL80211_VENDOR_ID,
845 .subcmd =
846 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
847 },
848 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
849 .
850 vendor_id
851 =
852 QCA_NL80211_VENDOR_ID,
853 .subcmd =
854 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
855 },
856 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
857 .
858 vendor_id
859 =
860 QCA_NL80211_VENDOR_ID,
861 .
862 subcmd =
863 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
864 },
865 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
866 .
867 vendor_id
868 =
869 QCA_NL80211_VENDOR_ID,
870 .
871 subcmd
872 =
873 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
874 },
875 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
876 .
877 vendor_id
878 =
879 QCA_NL80211_VENDOR_ID,
880 .subcmd =
881 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
882 },
883 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
884 .vendor_id =
885 QCA_NL80211_VENDOR_ID,
886 .subcmd =
887 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
888 },
889 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
890 .
891 vendor_id
892 =
893 QCA_NL80211_VENDOR_ID,
894 .subcmd =
895 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
896 },
897 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
898 .
899 vendor_id
900 =
901 QCA_NL80211_VENDOR_ID,
902 .subcmd =
903 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
904 },
905 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
906 .
907 vendor_id
908 =
909 QCA_NL80211_VENDOR_ID,
910 .
911 subcmd
912 =
913 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
914 },
915 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
916 .
917 vendor_id
918 =
919 QCA_NL80211_VENDOR_ID,
920 .
921 subcmd =
922 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
923 },
924 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
925 .
926 vendor_id
927 =
928 QCA_NL80211_VENDOR_ID,
929 .
930 subcmd
931 =
932 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
933 },
934 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
935 .
936 vendor_id
937 =
938 QCA_NL80211_VENDOR_ID,
939 .
940 subcmd
941 =
942 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
943 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800944#endif /* FEATURE_WLAN_EXTSCAN */
945
946#ifdef WLAN_FEATURE_LINK_LAYER_STATS
947 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
948 .vendor_id =
949 QCA_NL80211_VENDOR_ID,
950 .subcmd =
951 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
952 },
953 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
954 .vendor_id =
955 QCA_NL80211_VENDOR_ID,
956 .subcmd =
957 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
958 },
959 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
960 .vendor_id =
961 QCA_NL80211_VENDOR_ID,
962 .subcmd =
963 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
964 },
965 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
966 .vendor_id =
967 QCA_NL80211_VENDOR_ID,
968 .subcmd =
969 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
970 },
971 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
972 .vendor_id =
973 QCA_NL80211_VENDOR_ID,
974 .subcmd =
975 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
976 },
977 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
978 .vendor_id =
979 QCA_NL80211_VENDOR_ID,
980 .subcmd =
981 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
982 },
Zhang Qianca38fb12016-12-23 11:10:48 +0800983 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
984 .vendor_id =
985 QCA_NL80211_VENDOR_ID,
986 .subcmd =
987 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
988 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
990 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
991 .vendor_id =
992 QCA_NL80211_VENDOR_ID,
993 .subcmd =
994 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
995 },
996 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
997 .vendor_id = QCA_NL80211_VENDOR_ID,
998 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
999 },
1000#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1001 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1002 .vendor_id =
1003 QCA_NL80211_VENDOR_ID,
1004 .subcmd =
1005 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1006 },
1007#endif
1008 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1009 .vendor_id =
1010 QCA_NL80211_VENDOR_ID,
1011 .subcmd =
1012 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1013 },
1014 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1015 .vendor_id =
1016 QCA_NL80211_VENDOR_ID,
1017 .subcmd =
1018 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1019 },
1020 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1021 .vendor_id =
1022 QCA_NL80211_VENDOR_ID,
1023 .subcmd =
1024 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1025 },
1026 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1027 .vendor_id =
1028 QCA_NL80211_VENDOR_ID,
1029 .subcmd =
1030 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1031 },
1032 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1033 .vendor_id =
1034 QCA_NL80211_VENDOR_ID,
1035 .subcmd =
1036 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1037 },
1038#ifdef FEATURE_WLAN_EXTSCAN
1039 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1040 .vendor_id = QCA_NL80211_VENDOR_ID,
1041 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1042 },
1043 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1044 .vendor_id = QCA_NL80211_VENDOR_ID,
1045 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1046 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001047 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1048 .vendor_id = QCA_NL80211_VENDOR_ID,
1049 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1050 },
1051#endif /* FEATURE_WLAN_EXTSCAN */
1052 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1053 .vendor_id = QCA_NL80211_VENDOR_ID,
1054 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1055 },
1056#ifdef WLAN_FEATURE_MEMDUMP
1057 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1058 .vendor_id = QCA_NL80211_VENDOR_ID,
1059 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1060 },
1061#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001062#ifdef WLAN_FEATURE_TSF
1063 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1064 .vendor_id = QCA_NL80211_VENDOR_ID,
1065 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1066 },
1067#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001068 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1069 .vendor_id = QCA_NL80211_VENDOR_ID,
1070 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1071 },
1072 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1073 .vendor_id = QCA_NL80211_VENDOR_ID,
1074 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1075 },
1076 /* OCB events */
1077 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1078 .vendor_id = QCA_NL80211_VENDOR_ID,
1079 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1080 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001081#ifdef FEATURE_LFR_SUBNET_DETECTION
1082 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1083 .vendor_id = QCA_NL80211_VENDOR_ID,
1084 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1085 },
1086#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001087
1088#ifdef WLAN_FEATURE_NAN_DATAPATH
1089 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1090 .vendor_id = QCA_NL80211_VENDOR_ID,
1091 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1092 },
1093#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001094
1095 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1096 .vendor_id = QCA_NL80211_VENDOR_ID,
1097 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1098 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301099 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1100 .vendor_id = QCA_NL80211_VENDOR_ID,
1101 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1102 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301103 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1104 .vendor_id = QCA_NL80211_VENDOR_ID,
1105 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1106 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001107#ifdef WLAN_UMAC_CONVERGENCE
1108 COMMON_VENDOR_EVENTS
1109#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001110};
1111
1112/**
1113 * __is_driver_dfs_capable() - get driver DFS capability
1114 * @wiphy: pointer to wireless wiphy structure.
1115 * @wdev: pointer to wireless_dev structure.
1116 * @data: Pointer to the data to be passed via vendor interface
1117 * @data_len:Length of the data to be passed
1118 *
1119 * This function is called by userspace to indicate whether or not
1120 * the driver supports DFS offload.
1121 *
1122 * Return: 0 on success, negative errno on failure
1123 */
1124static int __is_driver_dfs_capable(struct wiphy *wiphy,
1125 struct wireless_dev *wdev,
1126 const void *data,
1127 int data_len)
1128{
1129 u32 dfs_capability = 0;
1130 struct sk_buff *temp_skbuff;
1131 int ret_val;
1132 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1133
Jeff Johnson1f61b612016-02-12 16:28:33 -08001134 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001135
1136 ret_val = wlan_hdd_validate_context(hdd_ctx);
1137 if (ret_val)
1138 return ret_val;
1139
Anurag Chouhan6d760662016-02-20 16:05:43 +05301140 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001141 hdd_err("Command not allowed in FTM mode");
1142 return -EPERM;
1143 }
1144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001145 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146
1147 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1148 NLMSG_HDRLEN);
1149
1150 if (temp_skbuff != NULL) {
1151 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1152 dfs_capability);
1153 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001154 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001155 kfree_skb(temp_skbuff);
1156
1157 return ret_val;
1158 }
1159
1160 return cfg80211_vendor_cmd_reply(temp_skbuff);
1161 }
1162
Jeff Johnson020db452016-06-29 14:37:26 -07001163 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001164 return -ENOMEM;
1165}
1166
1167/**
1168 * is_driver_dfs_capable() - get driver DFS capability
1169 * @wiphy: pointer to wireless wiphy structure.
1170 * @wdev: pointer to wireless_dev structure.
1171 * @data: Pointer to the data to be passed via vendor interface
1172 * @data_len:Length of the data to be passed
1173 *
1174 * This function is called by userspace to indicate whether or not
1175 * the driver supports DFS offload. This is an SSR-protected
1176 * wrapper function.
1177 *
1178 * Return: 0 on success, negative errno on failure
1179 */
1180static int is_driver_dfs_capable(struct wiphy *wiphy,
1181 struct wireless_dev *wdev,
1182 const void *data,
1183 int data_len)
1184{
1185 int ret;
1186
1187 cds_ssr_protect(__func__);
1188 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1189 cds_ssr_unprotect(__func__);
1190
1191 return ret;
1192}
1193
1194/**
1195 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1196 *
1197 * @adapter: SAP adapter pointer
1198 *
1199 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1200 * radio. So in case of DFS MCC scenario override current SAP given config
1201 * to follow concurrent SAP DFS config
1202 *
1203 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1204 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001205int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1206{
1207 hdd_adapter_t *con_sap_adapter;
1208 tsap_Config_t *sap_config, *con_sap_config;
1209 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001210 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001211
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001212 if (!hdd_ctx) {
1213 hdd_err("hdd context is NULL");
1214 return 0;
1215 }
1216
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001217 /*
1218 * Check if AP+AP case, once primary AP chooses a DFS
1219 * channel secondary AP should always follow primary APs channel
1220 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001221 if (!policy_mgr_concurrent_beaconing_sessions_running(
1222 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223 return 0;
1224
1225 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1226 if (!con_sap_adapter)
1227 return 0;
1228
1229 sap_config = &adapter->sessionCtx.ap.sapConfig;
1230 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1231 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1232
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001233 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001234 return 0;
1235
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001236 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001237 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001238 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239 sap_config->channel = con_ch;
1240
1241 if (con_sap_config->acs_cfg.acs_mode == true) {
1242 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1243 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001244 hdd_err("Primary AP channel config error");
1245 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246 con_ch, con_sap_config->acs_cfg.pri_ch,
1247 con_sap_config->acs_cfg.ht_sec_ch);
1248 return -EINVAL;
1249 }
1250 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1251 * MCC restriction. So free ch list allocated in do_acs
1252 * func for Sec AP and realloc for Pri AP ch list size
1253 */
1254 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301255 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001256
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301257 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258 &con_sap_config->acs_cfg,
1259 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301260 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261 sizeof(uint8_t) *
1262 con_sap_config->acs_cfg.ch_list_count);
1263 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001264 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001265 return -ENOMEM;
1266 }
1267
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301268 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001269 con_sap_config->acs_cfg.ch_list,
1270 con_sap_config->acs_cfg.ch_list_count);
1271
1272 } else {
1273 sap_config->acs_cfg.pri_ch = con_ch;
1274 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1275 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1276 }
1277
1278 return con_ch;
1279}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001280
1281/**
1282 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1283 * @sap_cfg: pointer to SAP config struct
1284 *
1285 * This function sets the default ACS start and end channel for the given band
1286 * and also parses the given ACS channel list.
1287 *
1288 * Return: None
1289 */
1290
1291static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1292 bool vht_enabled)
1293{
1294 int i;
1295 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1296 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001297 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1298 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001299 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1300 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001301 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1302 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1304 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001305 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1306 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001307 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1308 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001309 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1310 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001311 }
1312
1313 if (ht_enabled)
1314 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1315
1316 if (vht_enabled)
1317 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1318
1319
1320 /* Parse ACS Chan list from hostapd */
1321 if (!sap_cfg->acs_cfg.ch_list)
1322 return;
1323
1324 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1325 sap_cfg->acs_cfg.end_ch =
1326 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1327 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301328 /* avoid channel as start channel */
1329 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1330 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001331 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1332 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1333 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1334 }
1335}
1336
1337
1338static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1339
1340/**
1341 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1342 * @adapter: pointer to SAP adapter struct
1343 *
1344 * This function starts the ACS procedure if there are no
1345 * constraints like MBSSID DFS restrictions.
1346 *
1347 * Return: Status of ACS Start procedure
1348 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301349int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001350{
1351
1352 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1353 tsap_Config_t *sap_config;
1354 tpWLAN_SAPEventCB acs_event_callback;
1355 int status;
1356
1357 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301358 if (hdd_ctx->acs_policy.acs_channel)
1359 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1360 else
1361 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362
1363 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001364 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001366
1367 if (status > 0) {
1368 /*notify hostapd about channel override */
1369 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1370 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1371 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 }
Jeff Johnson68755312017-02-10 11:46:55 -08001373
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1375 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001376 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 return -EINVAL;
1378 }
1379
1380 acs_event_callback = hdd_hostapd_sap_event_cb;
1381
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301382 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301383 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301384 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387 acs_event_callback, sap_config, adapter->dev);
1388
1389
1390 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001391 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 return -EINVAL;
1393 }
bings394afdd2017-01-09 11:22:38 +08001394 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1395 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001396 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1397
1398 return 0;
1399}
1400
1401/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301402 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1403 * @ap_adapter: AP adapter
1404 * @nol: Non-occupancy list
1405 * @nol_len: Length of NOL
1406 *
1407 * Get the NOL for SAP
1408 *
1409 * Return: Zero on success, non-zero on failure
1410 */
1411static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1412 uint32_t *nol_len)
1413{
1414 QDF_STATUS ret;
1415
1416 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1417 nol, nol_len);
1418 if (QDF_IS_STATUS_ERROR(ret))
1419 return -EINVAL;
1420
1421 return 0;
1422}
1423
1424/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301425 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1426 * @hdd_ctx: hdd context
1427 * @acs_chan_params: external acs channel params
1428 * @sap_config: SAP config
1429 *
1430 * This API provides unsorted pcl list.
1431 * this list is a subset of the valid channel list given by hostapd.
1432 * if channel is not present in pcl, weightage will be given as zero
1433 *
1434 * Return: Zero on success, non-zero on failure
1435 */
1436static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1437 struct hdd_vendor_acs_chan_params *acs_chan_params,
1438 tsap_Config_t *sap_config)
1439{
1440 int i, j;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301441 bool found;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301442
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301443 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1444 hdd_ctx->config->external_acs_policy) {
1445 /*
1446 * In preferred channels mandatory case, PCL shall
1447 * contain only the preferred channels from the
1448 * application. If those channels are not present
1449 * in the driver PCL, then set the weight to zero
1450 */
1451 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1452 acs_chan_params->vendor_pcl_list[i] =
1453 sap_config->acs_cfg.ch_list[i];
1454 acs_chan_params->vendor_weight_list[i] = 0;
1455 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1456 if (sap_config->acs_cfg.ch_list[i] ==
Kapil Gupta8878ad92017-02-13 11:56:04 +05301457 sap_config->acs_cfg.pcl_channels[j]) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301458 acs_chan_params->vendor_weight_list[i] =
1459 sap_config->
1460 acs_cfg.pcl_channels_weight_list[j];
1461 break;
1462 }
1463 }
1464 }
1465 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
1466 } else {
1467 /*
1468 * In preferred channels not mandatory case update the
1469 * PCL weight to zero for those channels which are not
1470 * present in the application's preferred channel list for
1471 * ACS
1472 */
1473 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++) {
1474 found = false;
1475 for (j = 0; j < sap_config->acs_cfg.ch_list_count;
1476 j++) {
1477 if (sap_config->acs_cfg.pcl_channels[i] ==
1478 sap_config->acs_cfg.ch_list[j]) {
1479 acs_chan_params->vendor_pcl_list[i] =
1480 sap_config->
1481 acs_cfg.pcl_channels[i];
1482 acs_chan_params->
1483 vendor_weight_list[i] =
1484 sap_config->acs_cfg.
1485 pcl_channels_weight_list[i];
1486 found = true;
1487 break;
1488 }
1489 }
1490 if (!found) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05301491 acs_chan_params->vendor_pcl_list[i] =
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301492 sap_config->acs_cfg.pcl_channels[i];
Kapil Gupta8878ad92017-02-13 11:56:04 +05301493 acs_chan_params->vendor_weight_list[i] = 0;
1494 }
1495 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301496
1497 acs_chan_params->pcl_count = sap_config->acs_cfg.pcl_ch_count;
1498
1499 if (hdd_ctx->unsafe_channel_count == 0)
1500 return;
1501 /* Update unsafe channel weight as zero */
1502 for (i = 0; i < acs_chan_params->pcl_count; i++) {
1503 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1504 if (acs_chan_params->vendor_pcl_list[i] ==
Kapil Gupta8878ad92017-02-13 11:56:04 +05301505 hdd_ctx->unsafe_channel_list[j]) {
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301506 acs_chan_params->
1507 vendor_weight_list[i] = 0;
1508 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301509 }
1510 }
1511 }
1512}
1513
1514/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301515 * hdd_update_reg_chan_info : This API contructs channel info
1516 * for all the given channel
1517 * @adapter: pointer to SAP adapter struct
1518 * @channel_count: channel count
1519 * @channel_list: channel list
1520 *
1521 * Return: Status of of channel information updation
1522 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301523static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301524 uint32_t channel_count,
1525 uint8_t *channel_list)
1526{
1527 int i;
1528 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001529 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301530 uint8_t bw_offset = 0, chan = 0;
1531 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1532 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1533
1534 /* memory allocation */
1535 sap_config->channel_info = qdf_mem_malloc(
1536 sizeof(struct hdd_channel_info) *
1537 channel_count);
1538 if (!sap_config->channel_info) {
1539 hdd_err("memory allocation failed");
1540 return -ENOMEM;
1541
1542 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301543 sap_config->channel_info_count = channel_count;
Kapil Gupta086c6202016-12-11 18:17:06 +05301544 for (i = 0; i < channel_count; i++) {
1545 icv = &sap_config->channel_info[i];
1546 chan = channel_list[i];
1547
1548 if (chan == 0)
1549 continue;
1550
1551 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1552 bw_offset = 1 << BW_40_OFFSET_BIT;
1553 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1554 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001555 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301556 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001557 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1558 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301559
1560 /* filling demo values */
1561 icv->max_radio_power = HDD_MAX_TX_POWER;
1562 icv->min_radio_power = HDD_MIN_TX_POWER;
1563 /* not supported in current driver */
1564 icv->max_antenna_gain = 0;
1565
1566 icv->reg_class_id = wlan_hdd_find_opclass(
1567 WLAN_HDD_GET_HAL_CTX(adapter),
1568 chan, bw_offset);
1569
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001570 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301571 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001572 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1573 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301574 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1575 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1576 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001577
Kapil Gupta086c6202016-12-11 18:17:06 +05301578 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001579 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301580 sap_config->acs_cfg.ch_width,
1581 sap_config->acs_cfg.is_ht_enabled,
1582 sap_config->acs_cfg.is_vht_enabled,
1583 hdd_ctx->config->enable_sub_20_channel_width);
1584
1585 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1586 icv->freq, icv->flags,
1587 icv->flagext, icv->ieee_chan_number,
1588 icv->max_reg_power, icv->max_radio_power,
1589 icv->min_radio_power, icv->reg_class_id,
1590 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1591 icv->vht_center_freq_seg1);
1592 }
1593 return 0;
1594}
1595
1596/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1597#define CHAN_INFO_ATTR_FLAGS \
1598 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1599#define CHAN_INFO_ATTR_FLAG_EXT \
1600 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1601#define CHAN_INFO_ATTR_FREQ \
1602 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1603#define CHAN_INFO_ATTR_MAX_REG_POWER \
1604 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1605#define CHAN_INFO_ATTR_MAX_POWER \
1606 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1607#define CHAN_INFO_ATTR_MIN_POWER \
1608 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1609#define CHAN_INFO_ATTR_REG_CLASS_ID \
1610 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1611#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1612 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1613#define CHAN_INFO_ATTR_VHT_SEG_0 \
1614 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1615#define CHAN_INFO_ATTR_VHT_SEG_1 \
1616 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1617
1618/**
1619 * hdd_cfg80211_update_channel_info() - add channel info attributes
1620 * @skb: pointer to sk buff
1621 * @hdd_ctx: pointer to hdd station context
1622 * @idx: attribute index
1623 *
1624 * Return: Success(0) or reason code for failure
1625 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301626static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301627hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1628 tsap_Config_t *sap_config, int idx)
1629{
1630 struct nlattr *nla_attr, *channel;
1631 struct hdd_channel_info *icv;
1632 int i;
1633
1634 nla_attr = nla_nest_start(skb, idx);
1635 if (!nla_attr)
1636 goto fail;
1637
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301638 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301639 channel = nla_nest_start(skb, i);
1640 if (!channel)
1641 goto fail;
1642
1643 icv = &sap_config->channel_info[i];
1644 if (!icv) {
1645 hdd_err("channel info not found");
1646 goto fail;
1647 }
1648 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1649 icv->freq) ||
1650 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1651 icv->flags) ||
1652 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1653 icv->flagext) ||
1654 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1655 icv->max_reg_power) ||
1656 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1657 icv->max_radio_power) ||
1658 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1659 icv->min_radio_power) ||
1660 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1661 icv->reg_class_id) ||
1662 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1663 icv->max_antenna_gain) ||
1664 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1665 icv->vht_center_freq_seg0) ||
1666 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1667 icv->vht_center_freq_seg1)) {
1668 hdd_err("put fail");
1669 goto fail;
1670 }
1671 nla_nest_end(skb, channel);
1672 }
1673 nla_nest_end(skb, nla_attr);
1674 return 0;
1675fail:
1676 hdd_err("nl channel update failed");
1677 return -EINVAL;
1678}
1679#undef CHAN_INFO_ATTR_FLAGS
1680#undef CHAN_INFO_ATTR_FLAG_EXT
1681#undef CHAN_INFO_ATTR_FREQ
1682#undef CHAN_INFO_ATTR_MAX_REG_POWER
1683#undef CHAN_INFO_ATTR_MAX_POWER
1684#undef CHAN_INFO_ATTR_MIN_POWER
1685#undef CHAN_INFO_ATTR_REG_CLASS_ID
1686#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1687#undef CHAN_INFO_ATTR_VHT_SEG_0
1688#undef CHAN_INFO_ATTR_VHT_SEG_1
1689
1690/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301691 * hdd_cfg80211_update_pcl() - add pcl info attributes
1692 * @skb: pointer to sk buff
1693 * @hdd_ctx: pointer to hdd station context
1694 * @idx: attribute index
1695 * @vendor_pcl_list: PCL list
1696 * @vendor_weight_list: PCL weights
1697 *
1698 * Return: Success(0) or reason code for failure
1699 */
1700static int32_t
1701hdd_cfg80211_update_pcl(struct sk_buff *skb,
1702 uint8_t ch_list_count, int idx,
1703 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1704{
1705 struct nlattr *nla_attr, *channel;
1706 int i;
1707
1708 nla_attr = nla_nest_start(skb, idx);
1709
1710 if (!nla_attr)
1711 goto fail;
1712
1713 for (i = 0; i < ch_list_count; i++) {
1714 channel = nla_nest_start(skb, i);
1715 if (!channel)
1716 goto fail;
1717 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1718 vendor_pcl_list[i]) ||
1719 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1720 vendor_weight_list[i])) {
1721 hdd_err("put fail");
1722 goto fail;
1723 }
1724 nla_nest_end(skb, channel);
1725 }
1726 nla_nest_end(skb, nla_attr);
1727
1728 return 0;
1729fail:
1730 hdd_err("updating pcl list failed");
1731 return -EINVAL;
1732}
1733
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301734static void hdd_get_scan_band(hdd_context_t *hdd_ctx,
1735 tsap_Config_t *sap_config,
1736 eCsrBand *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301737{
1738 /* Get scan band */
1739 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1740 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1741 *band = eCSR_BAND_24;
1742 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1743 *band = eCSR_BAND_5G;
1744 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1745 *band = eCSR_BAND_ALL;
1746 }
1747 /* Auto is not supported currently */
1748 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1749 hdd_err("invalid band");
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301750 if (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ ==
1751 hdd_ctx->config->external_acs_freq_band)
1752 *band = eCSR_BAND_24;
1753 else
1754 *band = eCSR_BAND_5G;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301755 }
1756}
1757
1758void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1759 uint8_t reason)
1760{
1761 struct sk_buff *skb;
1762 tsap_Config_t *sap_config;
1763 uint32_t channel_count = 0, status;
1764 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1765 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1766 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1767 struct hdd_vendor_acs_chan_params acs_chan_params;
1768 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1769 eCsrBand band = eCSR_BAND_24;
1770 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301771 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
1772 uint32_t i;
1773
Kapil Gupta8878ad92017-02-13 11:56:04 +05301774
1775 if (!hdd_ctx) {
1776 hdd_err("HDD context is NULL");
1777 return;
1778 }
1779
1780 ENTER();
1781 sap_config = &adapter->sessionCtx.ap.sapConfig;
1782
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301783 hdd_get_scan_band(hdd_ctx, &adapter->sessionCtx.ap.sapConfig, &band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301784 /* Get valid channels for SAP */
1785 wlan_hdd_sap_get_valid_channellist(adapter,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301786 &channel_count,
1787 channel_list,
1788 band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301789
1790 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301791 /* Get phymode */
1792 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1793
1794 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1795 &(adapter->wdev),
1796 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1797 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1798 GFP_KERNEL);
1799
1800 if (!skb) {
1801 hdd_err("cfg80211_vendor_event_alloc failed");
1802 return;
1803 }
1804 /*
1805 * Application expects pcl to be a subset of channel list
1806 * Remove all channels which are not in channel list from pcl
1807 * and add weight as zero
1808 */
1809 acs_chan_params.channel_count = channel_count;
1810 acs_chan_params.channel_list = channel_list;
1811 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1812 acs_chan_params.vendor_weight_list = vendor_weight_list;
1813
1814 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1815 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301816
1817 if (acs_chan_params.channel_count) {
1818 hdd_debug("ACS channel list: len: %d",
1819 acs_chan_params.channel_count);
1820 for (i = 0; i < acs_chan_params.channel_count; i++)
1821 hdd_debug("%d ", acs_chan_params.channel_list[i]);
1822 }
1823
1824 if (acs_chan_params.pcl_count) {
1825 hdd_debug("ACS PCL list: len: %d",
1826 acs_chan_params.pcl_count);
1827 for (i = 0; i < acs_chan_params.pcl_count; i++)
1828 hdd_debug("channel:%d, weight:%d ",
1829 acs_chan_params.
1830 vendor_pcl_list[i],
1831 acs_chan_params.
1832 vendor_weight_list[i]);
1833 }
1834
1835 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1836 hdd_ctx->config->external_acs_policy) {
1837 acs_policy =
1838 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
1839 } else {
1840 acs_policy =
1841 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
1842 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301843 /* Update values in NL buffer */
1844 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1845 reason) ||
1846 nla_put_u8(skb,
1847 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1848 false) ||
1849 nla_put_u8(skb,
1850 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1851 true) ||
1852 nla_put_u8(skb,
1853 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1854 true) ||
1855 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1856 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05301857 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1858 band) ||
1859 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1860 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05301861 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301862 channel_count, channel_list)) {
1863 hdd_err("nla put fail");
1864 goto fail;
1865 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301866 status =
1867 hdd_cfg80211_update_pcl(skb,
1868 acs_chan_params.
1869 pcl_count,
1870 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1871 vendor_pcl_list,
1872 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301873
1874 if (status != 0)
1875 goto fail;
1876
1877 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1878 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1879
1880 if (status != 0)
1881 goto fail;
1882
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301883 status = nla_put_u32(skb,
1884 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
1885 acs_policy);
1886
1887 if (status != 0)
1888 goto fail;
1889
Kapil Gupta8878ad92017-02-13 11:56:04 +05301890 cfg80211_vendor_event(skb, GFP_KERNEL);
1891 return;
1892fail:
1893 if (skb)
1894 kfree_skb(skb);
1895}
1896
1897static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1898{
1899 struct hdd_external_acs_timer_context *timer_context;
1900
1901 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1902 return 0;
1903
1904 hdd_notice("Starting vendor app based ACS");
1905 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1906 timer_context->adapter = adapter;
1907
1908 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1909 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1910 QDF_TIMER_TYPE_SW,
1911 hdd_acs_response_timeout_handler, timer_context);
1912 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1913 return 0;
1914}
1915
1916/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001917 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1918 * @wiphy: Linux wiphy struct pointer
1919 * @wdev: Linux wireless device struct pointer
1920 * @data: ACS information from hostapd
1921 * @data_len: ACS information length
1922 *
1923 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1924 * and starts ACS procedure.
1925 *
1926 * Return: ACS procedure start status
1927 */
1928
1929static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1930 struct wireless_dev *wdev,
1931 const void *data, int data_len)
1932{
1933 struct net_device *ndev = wdev->netdev;
1934 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1935 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1936 tsap_Config_t *sap_config;
1937 struct sk_buff *temp_skbuff;
1938 int status = -EINVAL, i = 0;
1939 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1940 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301941 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001942
1943 /* ***Note*** Donot set SME config related to ACS operation here because
1944 * ACS operation is not synchronouse and ACS for Second AP may come when
1945 * ACS operation for first AP is going on. So only do_acs is split to
1946 * seperate start_acs routine. Also SME-PMAC struct that is used to
1947 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1948 * config shall be set only from start_acs.
1949 */
1950
1951 /* nla_policy Policy template. Policy not applied as some attributes are
1952 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1953 *
1954 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1955 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1956 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1957 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1958 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1959 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1960 */
1961
Jeff Johnson1f61b612016-02-12 16:28:33 -08001962 ENTER_DEV(ndev);
1963
Anurag Chouhan6d760662016-02-20 16:05:43 +05301964 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 hdd_err("Command not allowed in FTM mode");
1966 return -EPERM;
1967 }
1968
Kapil Gupta8878ad92017-02-13 11:56:04 +05301969 if (hdd_ctx->config->force_sap_acs &&
1970 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001971 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 return -EPERM;
1973 }
1974
1975 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301976 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001977 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301978
Naveen Rawat64e477e2016-05-20 10:34:56 -07001979 if (cds_is_sub_20_mhz_enabled()) {
1980 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1981 status = -EINVAL;
1982 goto out;
1983 }
1984
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301986 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987
1988 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1989 NULL);
1990 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001991 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992 goto out;
1993 }
1994
1995 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001996 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997 goto out;
1998 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301999 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
2000 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002001
2002 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
2003 ht_enabled =
2004 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2005 else
2006 ht_enabled = 0;
2007
2008 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2009 ht40_enabled =
2010 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2011 else
2012 ht40_enabled = 0;
2013
2014 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2015 vht_enabled =
2016 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2017 else
2018 vht_enabled = 0;
2019
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302020 if (hdd_ctx->config->sap_force_11n_for_11ac) {
2021 vht_enabled = 0;
2022 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
2023 }
2024
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2026 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2027 } else {
2028 if (ht_enabled && ht40_enabled)
2029 ch_width = 40;
2030 else
2031 ch_width = 20;
2032 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302033
2034 /* this may be possible, when sap_force_11n_for_11ac is set */
2035 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2036 if (ht_enabled && ht40_enabled)
2037 ch_width = 40;
2038 else
2039 ch_width = 20;
2040 }
2041
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002042 if (ch_width == 80)
2043 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2044 else if (ch_width == 40)
2045 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2046 else
2047 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2048
2049 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2050 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2051 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2052 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2053 * since it contains the frequency values of the channels in
2054 * the channel list.
2055 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2056 * is present
2057 */
2058 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2059 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2060 sap_config->acs_cfg.ch_list_count = nla_len(
2061 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2062 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302063 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002064 sizeof(uint8_t) *
2065 sap_config->acs_cfg.ch_list_count);
2066 if (sap_config->acs_cfg.ch_list == NULL)
2067 goto out;
2068
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302069 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002070 sap_config->acs_cfg.ch_list_count);
2071 }
2072 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2073 uint32_t *freq =
2074 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2075 sap_config->acs_cfg.ch_list_count = nla_len(
2076 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2077 sizeof(uint32_t);
2078 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302079 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002080 sap_config->acs_cfg.ch_list_count);
2081 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07002082 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002083 status = -ENOMEM;
2084 goto out;
2085 }
2086
2087 /* convert frequency to channel */
2088 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2089 sap_config->acs_cfg.ch_list[i] =
2090 ieee80211_frequency_to_channel(freq[i]);
2091 }
2092 }
2093
2094 hdd_debug("get pcl for DO_ACS vendor command");
2095
2096 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002097 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302098 sap_config->acs_cfg.pcl_channels,
2099 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302100 sap_config->acs_cfg.pcl_channels_weight_list,
2101 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302102 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002103 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002104
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302105 if (sap_config->acs_cfg.pcl_ch_count) {
2106 hdd_debug("ACS config PCL: len: %d",
2107 sap_config->acs_cfg.pcl_ch_count);
2108 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2109 hdd_debug("channel:%d, weight:%d ",
2110 sap_config->acs_cfg.
2111 pcl_channels[i],
2112 sap_config->acs_cfg.
2113 pcl_channels_weight_list[i]);
2114 }
2115
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002116 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302117 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2118 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002119 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002120 vht_enabled = 1;
2121 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2122 sap_config->acs_cfg.ch_width =
2123 hdd_ctx->config->vhtChannelWidth;
2124 /* No VHT80 in 2.4G so perform ACS accordingly */
2125 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302126 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302128 ch_width = 40;
2129 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002130 }
2131
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302132 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2133
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002134 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 -08002135 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2136 ch_width, ht_enabled, vht_enabled,
2137 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2138
Kapil Gupta8878ad92017-02-13 11:56:04 +05302139 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2140 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2141
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002142 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002143 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002144 sap_config->acs_cfg.ch_list_count);
2145 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002146 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002147 }
2148 sap_config->acs_cfg.acs_mode = true;
2149 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002150 /* ***Note*** Completion variable usage is not allowed
2151 * here since ACS scan operation may take max 2.2 sec
2152 * for 5G band:
2153 * 9 Active channel X 40 ms active scan time +
2154 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002155 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2156 * for this long. So we split up the scanning part.
2157 */
2158 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002159 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002160 status = 0;
2161 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302162 /* Check if vendor specific acs is enabled */
2163 if (hdd_ctx->config->vendor_acs_support) {
2164 sap_config->acs_cfg.hw_mode = hw_mode;
2165 hdd_create_acs_timer(adapter);
2166 hdd_update_acs_timer_reason(adapter,
2167 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2168 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2169 wlan_sap_set_vendor_acs(
2170 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2171 true);
2172 else
2173 wlan_sap_set_vendor_acs(
2174 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2175 false);
2176
2177 } else
2178 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002179 }
2180
2181out:
2182 if (0 == status) {
2183 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2184 NLMSG_HDRLEN);
2185 if (temp_skbuff != NULL)
2186 return cfg80211_vendor_cmd_reply(temp_skbuff);
2187 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002188 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002189 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2190
2191 return status;
2192}
2193
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002194/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002195 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2196 * @wiphy: Linux wiphy struct pointer
2197 * @wdev: Linux wireless device struct pointer
2198 * @data: ACS information from hostapd
2199 * @data_len: ACS information len
2200 *
2201 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2202 * and starts ACS procedure.
2203 *
2204 * Return: ACS procedure start status
2205 */
2206
2207static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2208 struct wireless_dev *wdev,
2209 const void *data, int data_len)
2210{
2211 int ret;
2212
2213 cds_ssr_protect(__func__);
2214 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2215 cds_ssr_unprotect(__func__);
2216
2217 return ret;
2218}
2219
2220/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002221 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2222 * @adapter: Pointer to adapter struct
2223 *
2224 * This function handle cleanup of what was done in DO_ACS, including free
2225 * memory.
2226 *
2227 * Return: void
2228 */
2229
2230void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2231{
2232 if (adapter == NULL)
2233 return;
2234 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2235 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2236 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2237 }
2238}
2239
2240/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002241 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2242 * @work: Linux workqueue struct pointer for ACS work
2243 *
2244 * This function starts the ACS procedure which was marked pending when an ACS
2245 * procedure was in progress for a concurrent SAP interface.
2246 *
2247 * Return: None
2248 */
2249
2250static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2251{
2252 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2253 acs_pending_work.work);
2254 wlan_hdd_cfg80211_start_acs(adapter);
2255}
2256
2257/**
2258 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2259 * @adapter: Pointer to SAP adapter struct
2260 * @pri_channel: SAP ACS procedure selected Primary channel
2261 * @sec_channel: SAP ACS procedure selected secondary channel
2262 *
2263 * This is a callback function from SAP module on ACS procedure is completed.
2264 * This function send the ACS selected channel information to hostapd
2265 *
2266 * Return: None
2267 */
2268
2269void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2270{
2271 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2272 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2273 struct sk_buff *vendor_event;
2274 int ret_val;
2275 hdd_adapter_t *con_sap_adapter;
2276 uint16_t ch_width;
2277
2278 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002279 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002280 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2281 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2282 GFP_KERNEL);
2283
2284 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002285 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002286 return;
2287 }
2288
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002289 ret_val = nla_put_u8(vendor_event,
2290 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2291 sap_cfg->acs_cfg.pri_ch);
2292 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002293 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002294 kfree_skb(vendor_event);
2295 return;
2296 }
2297
2298 ret_val = nla_put_u8(vendor_event,
2299 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2300 sap_cfg->acs_cfg.ht_sec_ch);
2301 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002302 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303 kfree_skb(vendor_event);
2304 return;
2305 }
2306
2307 ret_val = nla_put_u8(vendor_event,
2308 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2309 sap_cfg->acs_cfg.vht_seg0_center_ch);
2310 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002311 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002312 kfree_skb(vendor_event);
2313 return;
2314 }
2315
2316 ret_val = nla_put_u8(vendor_event,
2317 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2318 sap_cfg->acs_cfg.vht_seg1_center_ch);
2319 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002320 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002321 kfree_skb(vendor_event);
2322 return;
2323 }
2324
2325 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2326 ch_width = 80;
2327 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2328 ch_width = 40;
2329 else
2330 ch_width = 20;
2331
2332 ret_val = nla_put_u16(vendor_event,
2333 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2334 ch_width);
2335 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002336 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002337 kfree_skb(vendor_event);
2338 return;
2339 }
2340 if (sap_cfg->acs_cfg.pri_ch > 14)
2341 ret_val = nla_put_u8(vendor_event,
2342 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2343 QCA_ACS_MODE_IEEE80211A);
2344 else
2345 ret_val = nla_put_u8(vendor_event,
2346 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2347 QCA_ACS_MODE_IEEE80211G);
2348
2349 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002350 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 kfree_skb(vendor_event);
2352 return;
2353 }
2354
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002355 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 -08002356 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2357 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2358 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2359
2360 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2361 /* ***Note*** As already mentioned Completion variable usage is not
2362 * allowed here since ACS scan operation may take max 2.2 sec.
2363 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2364 * operation.
2365 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2366 * when Primary AP ACS is complete and secondary AP ACS is started here
2367 * immediately, Primary AP start_bss may come inbetween ACS operation
2368 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2369 * delay. This path and below constraint will be removed on sessionizing
2370 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2371 * As per design constraint user space control application must take
2372 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2373 * this code path. Sec AP hostapd should be started after Primary AP
2374 * start beaconing which can be confirmed by getchannel iwpriv command
2375 */
2376
2377 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2378 if (con_sap_adapter &&
2379 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002380 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2381 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382 /* Lets give 500ms for OBSS + START_BSS to complete */
2383 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2384 msecs_to_jiffies(500));
2385 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2386 }
2387
2388 return;
2389}
2390
2391static int
2392__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2393 struct wireless_dev *wdev,
2394 const void *data,
2395 int data_len)
2396{
2397 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2398 struct sk_buff *skb = NULL;
2399 uint32_t fset = 0;
2400 int ret;
2401
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002402 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302403
Anurag Chouhan6d760662016-02-20 16:05:43 +05302404 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002405 hdd_err("Command not allowed in FTM mode");
2406 return -EPERM;
2407 }
2408
2409 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302410 if (ret)
2411 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002412
2413 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002414 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002415 fset |= WIFI_FEATURE_INFRA;
2416 }
2417 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002418 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002419 fset |= WIFI_FEATURE_INFRA_5G;
2420 }
2421#ifdef WLAN_FEATURE_P2P
2422 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2423 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002424 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002425 fset |= WIFI_FEATURE_P2P;
2426 }
2427#endif
2428 fset |= WIFI_FEATURE_SOFT_AP;
2429
2430 /* HOTSPOT is a supplicant feature, enable it by default */
2431 fset |= WIFI_FEATURE_HOTSPOT;
2432
2433#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302434 if (pHddCtx->config->extscan_enabled &&
2435 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002436 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2438 }
2439#endif
2440 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002441 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 fset |= WIFI_FEATURE_NAN;
2443 }
2444 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002445 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446 fset |= WIFI_FEATURE_D2D_RTT;
2447 fset |= WIFI_FEATURE_D2AP_RTT;
2448 }
2449#ifdef FEATURE_WLAN_SCAN_PNO
2450 if (pHddCtx->config->configPNOScanSupport &&
2451 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002452 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453 fset |= WIFI_FEATURE_PNO;
2454 }
2455#endif
2456 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2457#ifdef FEATURE_WLAN_TDLS
2458 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2459 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002460 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002461 fset |= WIFI_FEATURE_TDLS;
2462 }
2463 if (sme_is_feature_supported_by_fw(TDLS) &&
2464 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2465 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002466 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002467 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2468 }
2469#endif
2470#ifdef WLAN_AP_STA_CONCURRENCY
2471 fset |= WIFI_FEATURE_AP_STA;
2472#endif
2473 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002474 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002475
2476 if (hdd_link_layer_stats_supported())
2477 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2478
2479 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2480 NLMSG_HDRLEN);
2481 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002482 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002483 return -EINVAL;
2484 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002485 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002486 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002487 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002488 goto nla_put_failure;
2489 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302490 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302491 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002492nla_put_failure:
2493 kfree_skb(skb);
2494 return -EINVAL;
2495}
2496
2497/**
2498 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2499 * @wiphy: pointer to wireless wiphy structure.
2500 * @wdev: pointer to wireless_dev structure.
2501 * @data: Pointer to the data to be passed via vendor interface
2502 * @data_len:Length of the data to be passed
2503 *
2504 * Return: Return the Success or Failure code.
2505 */
2506static int
2507wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2508 struct wireless_dev *wdev,
2509 const void *data, int data_len)
2510{
2511 int ret = 0;
2512
2513 cds_ssr_protect(__func__);
2514 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2515 data, data_len);
2516 cds_ssr_unprotect(__func__);
2517
2518 return ret;
2519}
2520
2521/**
2522 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2523 * @wiphy: pointer to wireless wiphy structure.
2524 * @wdev: pointer to wireless_dev structure.
2525 * @data: Pointer to the data to be passed via vendor interface
2526 * @data_len:Length of the data to be passed
2527 *
2528 * Set the MAC address that is to be used for scanning.
2529 *
2530 * Return: Return the Success or Failure code.
2531 */
2532static int
2533__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2534 struct wireless_dev *wdev,
2535 const void *data,
2536 int data_len)
2537{
2538 tpSirScanMacOui pReqMsg = NULL;
2539 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2540 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302541 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 int ret;
2543
Jeff Johnson1f61b612016-02-12 16:28:33 -08002544 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545
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)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554
2555 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002556 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 return -ENOTSUPP;
2558 }
2559
2560 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2561 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002562 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002563 return -EINVAL;
2564 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302565 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002566 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002567 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002568 return -ENOMEM;
2569 }
2570 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002571 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002572 goto fail;
2573 }
2574 nla_memcpy(&pReqMsg->oui[0],
2575 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2576 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002577 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002578 pReqMsg->oui[1], pReqMsg->oui[2]);
2579 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302580 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002581 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582 goto fail;
2583 }
2584 return 0;
2585fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302586 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002587 return -EINVAL;
2588}
2589
2590/**
2591 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2592 * @wiphy: pointer to wireless wiphy structure.
2593 * @wdev: pointer to wireless_dev structure.
2594 * @data: Pointer to the data to be passed via vendor interface
2595 * @data_len:Length of the data to be passed
2596 *
2597 * Set the MAC address that is to be used for scanning. This is an
2598 * SSR-protecting wrapper function.
2599 *
2600 * Return: Return the Success or Failure code.
2601 */
2602static int
2603wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2604 struct wireless_dev *wdev,
2605 const void *data,
2606 int data_len)
2607{
2608 int ret;
2609
2610 cds_ssr_protect(__func__);
2611 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2612 data, data_len);
2613 cds_ssr_unprotect(__func__);
2614
2615 return ret;
2616}
2617
2618/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302619 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2620 * @wiphy: pointer phy adapter
2621 * @wdev: pointer to wireless device structure
2622 * @data: pointer to data buffer
2623 * @data_len: length of data
2624 *
2625 * This routine will give concurrency matrix
2626 *
2627 * Return: int status code
2628 */
2629static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2630 struct wireless_dev *wdev,
2631 const void *data,
2632 int data_len)
2633{
2634 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2635 uint8_t i, feature_sets, max_feature_sets;
2636 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2637 struct sk_buff *reply_skb;
2638 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2639 int ret;
2640
2641 ENTER_DEV(wdev->netdev);
2642
2643 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2644 hdd_err("Command not allowed in FTM mode");
2645 return -EPERM;
2646 }
2647
2648 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302649 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302650 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302651
2652 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2653 data, data_len, NULL)) {
2654 hdd_err("Invalid ATTR");
2655 return -EINVAL;
2656 }
2657
2658 /* Parse and fetch max feature set */
2659 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2660 hdd_err("Attr max feature set size failed");
2661 return -EINVAL;
2662 }
2663 max_feature_sets = nla_get_u32(tb[
2664 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002665 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302666
2667 /* Fill feature combination matrix */
2668 feature_sets = 0;
2669 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002670 WIFI_FEATURE_P2P;
2671 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2672 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302673 /* Add more feature combinations here */
2674
2675 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002676 hdd_debug("Number of feature sets: %d", feature_sets);
2677 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302678 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002679 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302680
2681 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2682 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2683 if (!reply_skb) {
2684 hdd_err("Feature set matrix: buffer alloc fail");
2685 return -ENOMEM;
2686 }
2687
2688 if (nla_put_u32(reply_skb,
2689 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2690 feature_sets) ||
2691 nla_put(reply_skb,
2692 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2693 sizeof(u32) * feature_sets,
2694 feature_set_matrix)) {
2695 hdd_err("nla put fail");
2696 kfree_skb(reply_skb);
2697 return -EINVAL;
2698 }
2699 return cfg80211_vendor_cmd_reply(reply_skb);
2700}
2701
2702/**
2703 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2704 * @wiphy: pointer to wireless wiphy structure.
2705 * @wdev: pointer to wireless_dev structure.
2706 * @data: Pointer to the data to be passed via vendor interface
2707 * @data_len:Length of the data to be passed
2708 *
2709 * Retrieves the concurrency feature set matrix
2710 *
2711 * Return: 0 on success, negative errno on failure
2712 */
2713static int
2714wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2715 struct wireless_dev *wdev,
2716 const void *data,
2717 int data_len)
2718{
2719 int ret;
2720
2721 cds_ssr_protect(__func__);
2722 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2723 data, data_len);
2724 cds_ssr_unprotect(__func__);
2725
2726 return ret;
2727}
2728
2729/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002730 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2731 * @feature_flags: pointer to the byte array of features.
2732 * @feature: Feature to be turned ON in the byte array.
2733 *
2734 * Return: None
2735 *
2736 * This is called to turn ON or SET the feature flag for the requested feature.
2737 **/
2738#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002739static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2740 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002741{
2742 uint32_t index;
2743 uint8_t bit_mask;
2744
2745 index = feature / NUM_BITS_IN_BYTE;
2746 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2747 feature_flags[index] |= bit_mask;
2748}
2749
2750/**
2751 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2752 * @wiphy: pointer to wireless wiphy structure.
2753 * @wdev: pointer to wireless_dev structure.
2754 * @data: Pointer to the data to be passed via vendor interface
2755 * @data_len:Length of the data to be passed
2756 *
2757 * This is called when wlan driver needs to send supported feature set to
2758 * supplicant upon a request/query from the supplicant.
2759 *
2760 * Return: Return the Success or Failure code.
2761 **/
2762#define MAX_CONCURRENT_CHAN_ON_24G 2
2763#define MAX_CONCURRENT_CHAN_ON_5G 2
2764static int
2765__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2766 struct wireless_dev *wdev,
2767 const void *data, int data_len)
2768{
2769 struct sk_buff *skb = NULL;
2770 uint32_t dbs_capability = 0;
2771 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302772 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002773 int ret_val;
2774
2775 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2776 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2777
Jeff Johnson1f61b612016-02-12 16:28:33 -08002778 ENTER_DEV(wdev->netdev);
2779
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002780 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2781 if (ret_val)
2782 return ret_val;
2783
Anurag Chouhan6d760662016-02-20 16:05:43 +05302784 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002785 hdd_err("Command not allowed in FTM mode");
2786 return -EPERM;
2787 }
2788
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002789 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002790 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791 wlan_hdd_cfg80211_set_feature(feature_flags,
2792 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2793 }
2794
2795 wlan_hdd_cfg80211_set_feature(feature_flags,
2796 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002797 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002798 wlan_hdd_cfg80211_set_feature(feature_flags,
2799 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002800
2801 if (wma_is_p2p_lo_capable())
2802 wlan_hdd_cfg80211_set_feature(feature_flags,
2803 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2804
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002805 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2806 NLMSG_HDRLEN);
2807
2808 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002809 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002810 return -ENOMEM;
2811 }
2812
2813 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2814 sizeof(feature_flags), feature_flags))
2815 goto nla_put_failure;
2816
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002817 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2818 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302819 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820 if (one_by_one_dbs)
2821 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2822
2823 if (two_by_two_dbs)
2824 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2825
2826 if (!one_by_one_dbs && !two_by_two_dbs)
2827 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2828 } else {
2829 hdd_err("wma_get_dbs_hw_mode failed");
2830 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2831 }
2832
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002833 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834
2835 if (nla_put_u32(skb,
2836 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2837 MAX_CONCURRENT_CHAN_ON_24G))
2838 goto nla_put_failure;
2839
2840 if (nla_put_u32(skb,
2841 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2842 MAX_CONCURRENT_CHAN_ON_5G))
2843 goto nla_put_failure;
2844
2845 return cfg80211_vendor_cmd_reply(skb);
2846
2847nla_put_failure:
2848 kfree_skb(skb);
2849 return -EINVAL;
2850}
2851
2852/**
2853 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2854 * @wiphy: pointer to wireless wiphy structure.
2855 * @wdev: pointer to wireless_dev structure.
2856 * @data: Pointer to the data to be passed via vendor interface
2857 * @data_len:Length of the data to be passed
2858 *
2859 * This is called when wlan driver needs to send supported feature set to
2860 * supplicant upon a request/query from the supplicant.
2861 *
2862 * Return: Return the Success or Failure code.
2863 */
2864static int
2865wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2866 struct wireless_dev *wdev,
2867 const void *data, int data_len)
2868{
2869 int ret;
2870
2871 cds_ssr_protect(__func__);
2872 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2873 data, data_len);
2874 cds_ssr_unprotect(__func__);
2875
2876 return ret;
2877}
2878
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302879#define PARAM_NUM_NW \
2880 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2881#define PARAM_SET_BSSID \
2882 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2883#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2884#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002885
2886/**
2887 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2888 * @wiphy: The wiphy structure
2889 * @wdev: The wireless device
2890 * @data: Data passed by framework
2891 * @data_len: Parameters to be configured passed as data
2892 *
2893 * The roaming related parameters are configured by the framework
2894 * using this interface.
2895 *
2896 * Return: Return either success or failure code.
2897 */
2898static int
2899__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2900 struct wireless_dev *wdev, const void *data, int data_len)
2901{
2902 struct net_device *dev = wdev->netdev;
2903 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2904 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2905 uint8_t session_id;
2906 struct roam_ext_params roam_params;
2907 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302908 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002909 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2910 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2911 int rem, i;
2912 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002913 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002914 int ret;
2915
Jeff Johnson1f61b612016-02-12 16:28:33 -08002916 ENTER_DEV(dev);
2917
Anurag Chouhan6d760662016-02-20 16:05:43 +05302918 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919 hdd_err("Command not allowed in FTM mode");
2920 return -EPERM;
2921 }
2922
2923 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302924 if (ret)
2925 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002926
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05302927 if (pHddCtx->driver_status == DRIVER_MODULES_CLOSED) {
2928 hdd_err("Driver Modules are closed");
2929 return -EINVAL;
2930 }
2931
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002932 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2933 data, data_len,
2934 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002935 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936 return -EINVAL;
2937 }
2938 /* Parse and fetch Command Type*/
2939 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002940 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002941 goto fail;
2942 }
2943 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302944 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002945 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2946 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002947 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002948 goto fail;
2949 }
2950 req_id = nla_get_u32(
2951 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002952 hdd_debug("Req Id (%d)", req_id);
2953 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002954 switch (cmd_type) {
2955 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2956 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302957 if (tb[PARAM_NUM_NW]) {
2958 count = nla_get_u32(
2959 tb[PARAM_NUM_NW]);
2960 } else {
2961 hdd_err("Number of networks is not provided");
2962 goto fail;
2963 }
2964
2965 if (count &&
2966 tb[PRAM_SSID_LIST]) {
2967 nla_for_each_nested(curr_attr,
2968 tb[PRAM_SSID_LIST], rem) {
2969 if (nla_parse(tb2,
2970 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2971 nla_data(curr_attr), nla_len(curr_attr),
2972 NULL)) {
2973 hdd_err("nla_parse failed");
2974 goto fail;
2975 }
2976 /* Parse and Fetch allowed SSID list*/
2977 if (!tb2[PARAM_LIST_SSID]) {
2978 hdd_err("attr allowed ssid failed");
2979 goto fail;
2980 }
2981 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2982 /*
2983 * Upper Layers include a null termination
2984 * character. Check for the actual permissible
2985 * length of SSID and also ensure not to copy
2986 * the NULL termination character to the driver
2987 * buffer.
2988 */
2989 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2990 ((buf_len - 1) <=
2991 SIR_MAC_MAX_SSID_LENGTH)) {
2992 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002993 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302994 tb2[PARAM_LIST_SSID], buf_len - 1);
2995 roam_params.ssid_allowed_list[i].length
2996 = buf_len - 1;
2997 hdd_debug("SSID[%d]: %.*s,length = %d",
2998 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002999 roam_params.ssid_allowed_list[i].length,
3000 roam_params.ssid_allowed_list[i].ssId,
3001 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303002 i++;
3003 } else {
3004 hdd_err("Invalid buffer length");
3005 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003006 }
3007 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303008 if (i != count) {
3009 hdd_err("Invalid number of SSIDs i = %d, count = %d",
3010 i, count);
3011 goto fail;
3012 }
3013
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003014 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07003015 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003016 roam_params.num_ssid_allowed_list);
3017 sme_update_roam_params(pHddCtx->hHal, session_id,
3018 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3019 break;
3020 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
3021 /* Parse and fetch 5G Boost Threshold */
3022 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003023 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003024 goto fail;
3025 }
3026 roam_params.raise_rssi_thresh_5g = nla_get_s32(
3027 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003028 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003029 roam_params.raise_rssi_thresh_5g);
3030 /* Parse and fetch 5G Penalty Threshold */
3031 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003032 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003033 goto fail;
3034 }
3035 roam_params.drop_rssi_thresh_5g = nla_get_s32(
3036 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003037 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 roam_params.drop_rssi_thresh_5g);
3039 /* Parse and fetch 5G Boost Factor */
3040 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003041 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042 goto fail;
3043 }
3044 roam_params.raise_factor_5g = nla_get_u32(
3045 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003046 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003047 roam_params.raise_factor_5g);
3048 /* Parse and fetch 5G Penalty factor */
3049 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003050 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003051 goto fail;
3052 }
3053 roam_params.drop_factor_5g = nla_get_u32(
3054 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003055 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 roam_params.drop_factor_5g);
3057 /* Parse and fetch 5G Max Boost */
3058 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003059 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003060 goto fail;
3061 }
3062 roam_params.max_raise_rssi_5g = nla_get_u32(
3063 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07003064 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003065 roam_params.max_raise_rssi_5g);
3066 /* Parse and fetch Rssi Diff */
3067 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003068 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003069 goto fail;
3070 }
3071 roam_params.rssi_diff = nla_get_s32(
3072 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07003073 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003074 roam_params.rssi_diff);
3075 /* Parse and fetch Alert Rssi Threshold */
3076 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003077 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003078 goto fail;
3079 }
3080 roam_params.alert_rssi_threshold = nla_get_u32(
3081 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003082 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003083 roam_params.alert_rssi_threshold);
3084 sme_update_roam_params(pHddCtx->hHal, session_id,
3085 roam_params,
3086 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
3087 break;
3088 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
3089 /* Parse and fetch Activate Good Rssi Roam */
3090 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003091 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003092 goto fail;
3093 }
3094 roam_params.good_rssi_roam = nla_get_s32(
3095 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07003096 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003097 roam_params.good_rssi_roam);
3098 sme_update_roam_params(pHddCtx->hHal, session_id,
3099 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
3100 break;
3101 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
3102 /* Parse and fetch number of preferred BSSID */
3103 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003104 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 goto fail;
3106 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003107 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003108 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003109 if (count > MAX_BSSID_FAVORED) {
3110 hdd_err("Preferred BSSID count %u exceeds max %u",
3111 count, MAX_BSSID_FAVORED);
3112 goto fail;
3113 }
3114 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115 i = 0;
3116 nla_for_each_nested(curr_attr,
3117 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3118 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003119
3120 if (i == count) {
3121 hdd_warn("Ignoring excess Preferred BSSID");
3122 break;
3123 }
3124
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003125 if (nla_parse(tb2,
3126 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3127 nla_data(curr_attr), nla_len(curr_attr),
3128 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003129 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003130 goto fail;
3131 }
3132 /* Parse and fetch MAC address */
3133 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003134 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003135 goto fail;
3136 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003137 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003138 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303139 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003140 hdd_debug(MAC_ADDRESS_STR,
3141 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003142 /* Parse and fetch preference factor*/
3143 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003144 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003145 goto fail;
3146 }
3147 roam_params.bssid_favored_factor[i] = nla_get_u32(
3148 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003149 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003150 roam_params.bssid_favored_factor[i]);
3151 i++;
3152 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003153 if (i < count)
3154 hdd_warn("Num Preferred BSSID %u less than expected %u",
3155 i, count);
3156 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003157 sme_update_roam_params(pHddCtx->hHal, session_id,
3158 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3159 break;
3160 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3161 /* Parse and fetch number of blacklist BSSID */
3162 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003163 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164 goto fail;
3165 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003166 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003168 if (count > MAX_BSSID_AVOID_LIST) {
3169 hdd_err("Blacklist BSSID count %u exceeds max %u",
3170 count, MAX_BSSID_AVOID_LIST);
3171 goto fail;
3172 }
3173 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303175
3176 if (count &&
3177 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3178 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003179 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3180 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003181
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303182 if (i == count) {
3183 hdd_warn("Ignoring excess Blacklist BSSID");
3184 break;
3185 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003186
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303187 if (nla_parse(tb2,
3188 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3189 nla_data(curr_attr), nla_len(curr_attr),
3190 NULL)) {
3191 hdd_err("nla_parse failed");
3192 goto fail;
3193 }
3194 /* Parse and fetch MAC address */
3195 if (!tb2[PARAM_SET_BSSID]) {
3196 hdd_err("attr blacklist addr failed");
3197 goto fail;
3198 }
3199 nla_memcpy(
3200 roam_params.bssid_avoid_list[i].bytes,
3201 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3202 hdd_debug(MAC_ADDRESS_STR,
3203 MAC_ADDR_ARRAY(
3204 roam_params.bssid_avoid_list[i].bytes));
3205 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003207 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003208 if (i < count)
3209 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3210 i, count);
3211 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003212 sme_update_roam_params(pHddCtx->hHal, session_id,
3213 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3214 break;
3215 }
3216 return 0;
3217fail:
3218 return -EINVAL;
3219}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303220#undef PARAM_NUM_NW
3221#undef PARAM_SET_BSSID
3222#undef PRAM_SSID_LIST
3223#undef PARAM_LIST_SSID
3224
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225
3226/**
3227 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3228 * @wiphy: pointer to wireless wiphy structure.
3229 * @wdev: pointer to wireless_dev structure.
3230 * @data: Pointer to the data to be passed via vendor interface
3231 * @data_len:Length of the data to be passed
3232 *
3233 * Return: Return the Success or Failure code.
3234 */
3235static int
3236wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3237 struct wireless_dev *wdev,
3238 const void *data,
3239 int data_len)
3240{
3241 int ret;
3242
3243 cds_ssr_protect(__func__);
3244 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3245 data, data_len);
3246 cds_ssr_unprotect(__func__);
3247
3248 return ret;
3249}
3250
3251static const struct nla_policy
3252wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3253 +1] = {
3254 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3255};
3256
3257/**
3258 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3259 * @hdd_ctx: HDD context
3260 * @device_mode: device mode
3261 * Return: bool
3262 */
3263static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003264 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003265{
3266 hdd_adapter_t *adapter;
3267 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3268 hdd_ap_ctx_t *ap_ctx;
3269 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303270 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003271
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303272 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003273 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303275 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 adapter = adapter_node->pAdapter;
3277
3278 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003279 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280 ap_ctx =
3281 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3282
3283 /*
3284 * if there is SAP already running on DFS channel,
3285 * do not disable scan on dfs channels. Note that
3286 * with SAP on DFS, there cannot be conurrency on
3287 * single radio. But then we can have multiple
3288 * radios !!
3289 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003290 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3291 hdd_ctx->hdd_pdev,
3292 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003293 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003294 return true;
3295 }
3296 }
3297
3298 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003299 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003300 sta_ctx =
3301 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3302
3303 /*
3304 * if STA is already connected on DFS channel,
3305 * do not disable scan on dfs channels
3306 */
3307 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003308 (CHANNEL_STATE_DFS ==
3309 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3310 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003311 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003312 return true;
3313 }
3314 }
3315
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303316 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003317 adapter_node,
3318 &next);
3319 adapter_node = next;
3320 }
3321
3322 return false;
3323}
3324
3325/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003326 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003327 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003328 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003329 *
3330 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003331 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003332 * Fails the disable request if any device is active on a DFS channel.
3333 *
3334 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003335 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003336
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003337int wlan_hdd_enable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3338 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003339{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303340 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003341 bool err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003342
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003343 if (enable_dfs_channels == hdd_ctx->config->enableDFSChnlScan) {
3344 hdd_info("DFS channels are already %s",
3345 enable_dfs_channels ? "enabled" : "disabled");
3346 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003347 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003348
3349 if (!enable_dfs_channels) {
3350 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3351 QDF_STA_MODE);
3352 if (err)
3353 return -EOPNOTSUPP;
3354
3355 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3356 QDF_SAP_MODE);
3357 if (err)
3358 return -EOPNOTSUPP;
3359 }
3360
3361 hdd_ctx->config->enableDFSChnlScan = enable_dfs_channels;
3362
3363 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3364
3365 /* pass dfs channel status to regulatory component */
3366 status = ucfg_reg_enable_dfs_channels(hdd_ctx->hdd_pdev,
3367 enable_dfs_channels);
3368
3369 if (QDF_IS_STATUS_ERROR(status))
3370 hdd_err("Failed to %s DFS channels",
3371 enable_dfs_channels ? "enable" : "disable");
3372
3373 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003374}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003375
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003376/**
3377 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3378 * @wiphy: corestack handler
3379 * @wdev: wireless device
3380 * @data: data
3381 * @data_len: data length
3382 * Return: success(0) or reason code for failure
3383 */
3384static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3385 struct wireless_dev *wdev,
3386 const void *data,
3387 int data_len)
3388{
3389 struct net_device *dev = wdev->netdev;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003390 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3391 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3392 int ret_val;
3393 uint32_t no_dfs_flag = 0;
3394
Jeff Johnson1f61b612016-02-12 16:28:33 -08003395 ENTER_DEV(dev);
3396
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003397 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303398 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003399 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003400
3401 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3402 data, data_len,
3403 wlan_hdd_set_no_dfs_flag_config_policy)) {
3404 hdd_err("invalid attr");
3405 return -EINVAL;
3406 }
3407
3408 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3409 hdd_err("attr dfs flag failed");
3410 return -EINVAL;
3411 }
3412
3413 no_dfs_flag = nla_get_u32(
3414 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3415
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003416 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003417
3418 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003419 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003420 return -EINVAL;
3421 }
3422
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003423 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003424 return ret_val;
3425}
3426
3427/**
3428 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3429 *
3430 * @wiphy: wiphy device pointer
3431 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003432 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003433 * @data_len: Buffer length
3434 *
3435 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3436 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3437 *
3438 * Return: EOK or other error codes.
3439 */
3440
3441static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3442 struct wireless_dev *wdev,
3443 const void *data,
3444 int data_len)
3445{
3446 int ret;
3447
3448 cds_ssr_protect(__func__);
3449 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3450 data, data_len);
3451 cds_ssr_unprotect(__func__);
3452
3453 return ret;
3454}
3455
Manikandan Mohan80dea792016-04-28 16:36:48 -07003456static const struct nla_policy
3457wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3458 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3459};
3460
3461/**
3462 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3463 * @wiphy: wiphy device pointer
3464 * @wdev: wireless device pointer
3465 * @data: Vendor command data buffer
3466 * @data_len: Buffer length
3467 *
3468 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3469 * setup WISA Mode features.
3470 *
3471 * Return: Success(0) or reason code for failure
3472 */
3473static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3474 struct wireless_dev *wdev, const void *data, int data_len)
3475{
3476 struct net_device *dev = wdev->netdev;
3477 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3478 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3479 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3480 struct sir_wisa_params wisa;
3481 int ret_val;
3482 QDF_STATUS status;
3483 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003484 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3485 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003486
3487 ENTER_DEV(dev);
3488 ret_val = wlan_hdd_validate_context(hdd_ctx);
3489 if (ret_val)
3490 goto err;
3491
3492 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3493 hdd_err("Command not allowed in FTM mode");
3494 return -EPERM;
3495 }
3496
3497 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3498 wlan_hdd_wisa_cmd_policy)) {
3499 hdd_err("Invalid WISA cmd attributes");
3500 ret_val = -EINVAL;
3501 goto err;
3502 }
3503 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3504 hdd_err("Invalid WISA mode");
3505 ret_val = -EINVAL;
3506 goto err;
3507 }
3508
3509 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003510 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003511 wisa.mode = wisa_mode;
3512 wisa.vdev_id = adapter->sessionId;
3513 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003514 if (!QDF_IS_STATUS_SUCCESS(status)) {
3515 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003516 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003517 }
3518 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003519 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003520 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3521 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003522 adapter->sessionId),
3523 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003524err:
3525 EXIT();
3526 return ret_val;
3527}
3528
3529/**
3530 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3531 * @wiphy: corestack handler
3532 * @wdev: wireless device
3533 * @data: data
3534 * @data_len: data length
3535 *
3536 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3537 * setup WISA mode features.
3538 *
3539 * Return: Success(0) or reason code for failure
3540 */
3541static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3542 struct wireless_dev *wdev,
3543 const void *data,
3544 int data_len)
3545{
3546 int ret;
3547
3548 cds_ssr_protect(__func__);
3549 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3550 cds_ssr_unprotect(__func__);
3551
3552 return ret;
3553}
3554
Anurag Chouhan96919482016-07-13 16:36:57 +05303555/*
3556 * define short names for the global vendor params
3557 * used by __wlan_hdd_cfg80211_get_station_cmd()
3558 */
3559#define STATION_INVALID \
3560 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3561#define STATION_INFO \
3562 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3563#define STATION_ASSOC_FAIL_REASON \
3564 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3565#define STATION_MAX \
3566 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3567
3568static const struct nla_policy
3569hdd_get_station_policy[STATION_MAX + 1] = {
3570 [STATION_INFO] = {.type = NLA_FLAG},
3571 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3572};
3573
3574/**
3575 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3576 * @hdd_ctx: HDD context within host driver
3577 * @wdev: wireless device
3578 *
3579 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3580 * Validate cmd attributes and send the station info to upper layers.
3581 *
3582 * Return: Success(0) or reason code for failure
3583 */
3584static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3585 hdd_adapter_t *adapter)
3586{
3587 struct sk_buff *skb = NULL;
3588 uint32_t nl_buf_len;
3589 hdd_station_ctx_t *hdd_sta_ctx;
3590
3591 nl_buf_len = NLMSG_HDRLEN;
3592 nl_buf_len += sizeof(uint32_t);
3593 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3594
3595 if (!skb) {
3596 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3597 return -ENOMEM;
3598 }
3599
3600 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3601
3602 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3603 hdd_sta_ctx->conn_info.assoc_status_code)) {
3604 hdd_err("put fail");
3605 goto fail;
3606 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303607
3608 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
3609 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
3610 hdd_sta_ctx->conn_info.cca)) {
3611 hdd_err("put fail");
3612 goto fail;
3613 }
3614
Anurag Chouhan96919482016-07-13 16:36:57 +05303615 return cfg80211_vendor_cmd_reply(skb);
3616fail:
3617 if (skb)
3618 kfree_skb(skb);
3619 return -EINVAL;
3620}
3621
3622/**
3623 * hdd_map_auth_type() - transform auth type specific to
3624 * vendor command
3625 * @auth_type: csr auth type
3626 *
3627 * Return: Success(0) or reason code for failure
3628 */
3629static int hdd_convert_auth_type(uint32_t auth_type)
3630{
3631 uint32_t ret_val;
3632
3633 switch (auth_type) {
3634 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3635 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3636 break;
3637 case eCSR_AUTH_TYPE_SHARED_KEY:
3638 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3639 break;
3640 case eCSR_AUTH_TYPE_WPA:
3641 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3642 break;
3643 case eCSR_AUTH_TYPE_WPA_PSK:
3644 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3645 break;
3646 case eCSR_AUTH_TYPE_AUTOSWITCH:
3647 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3648 break;
3649 case eCSR_AUTH_TYPE_WPA_NONE:
3650 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3651 break;
3652 case eCSR_AUTH_TYPE_RSN:
3653 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3654 break;
3655 case eCSR_AUTH_TYPE_RSN_PSK:
3656 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3657 break;
3658 case eCSR_AUTH_TYPE_FT_RSN:
3659 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3660 break;
3661 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3662 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3663 break;
3664 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3665 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3666 break;
3667 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3668 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3669 break;
3670 case eCSR_AUTH_TYPE_CCKM_WPA:
3671 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3672 break;
3673 case eCSR_AUTH_TYPE_CCKM_RSN:
3674 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3675 break;
3676 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3677 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3678 break;
3679 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3680 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3681 break;
3682 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3683 case eCSR_AUTH_TYPE_FAILED:
3684 case eCSR_AUTH_TYPE_NONE:
3685 default:
3686 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3687 break;
3688 }
3689 return ret_val;
3690}
3691
3692/**
3693 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3694 * vendor command
3695 * @dot11mode: dot11mode
3696 *
3697 * Return: Success(0) or reason code for failure
3698 */
3699static int hdd_convert_dot11mode(uint32_t dot11mode)
3700{
3701 uint32_t ret_val;
3702
3703 switch (dot11mode) {
3704 case eCSR_CFG_DOT11_MODE_11A:
3705 ret_val = QCA_WLAN_802_11_MODE_11A;
3706 break;
3707 case eCSR_CFG_DOT11_MODE_11B:
3708 ret_val = QCA_WLAN_802_11_MODE_11B;
3709 break;
3710 case eCSR_CFG_DOT11_MODE_11G:
3711 ret_val = QCA_WLAN_802_11_MODE_11G;
3712 break;
3713 case eCSR_CFG_DOT11_MODE_11N:
3714 ret_val = QCA_WLAN_802_11_MODE_11N;
3715 break;
3716 case eCSR_CFG_DOT11_MODE_11AC:
3717 ret_val = QCA_WLAN_802_11_MODE_11AC;
3718 break;
3719 case eCSR_CFG_DOT11_MODE_AUTO:
3720 case eCSR_CFG_DOT11_MODE_ABG:
3721 default:
3722 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3723 }
3724 return ret_val;
3725}
3726
3727/**
3728 * hdd_add_tx_bitrate() - add tx bitrate attribute
3729 * @skb: pointer to sk buff
3730 * @hdd_sta_ctx: pointer to hdd station context
3731 * @idx: attribute index
3732 *
3733 * Return: Success(0) or reason code for failure
3734 */
3735static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3736 hdd_station_ctx_t *hdd_sta_ctx,
3737 int idx)
3738{
3739 struct nlattr *nla_attr;
3740 uint32_t bitrate, bitrate_compat;
3741
3742 nla_attr = nla_nest_start(skb, idx);
3743 if (!nla_attr)
3744 goto fail;
3745 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3746 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3747
3748 /* report 16-bit bitrate only if we can */
3749 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3750 if (bitrate > 0 &&
3751 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3752 hdd_err("put fail");
3753 goto fail;
3754 }
3755 if (bitrate_compat > 0 &&
3756 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3757 hdd_err("put fail");
3758 goto fail;
3759 }
3760 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3761 hdd_sta_ctx->conn_info.txrate.nss)) {
3762 hdd_err("put fail");
3763 goto fail;
3764 }
3765 nla_nest_end(skb, nla_attr);
3766 return 0;
3767fail:
3768 return -EINVAL;
3769}
3770
3771/**
3772 * hdd_add_sta_info() - add station info attribute
3773 * @skb: pointer to sk buff
3774 * @hdd_sta_ctx: pointer to hdd station context
3775 * @idx: attribute index
3776 *
3777 * Return: Success(0) or reason code for failure
3778 */
3779static int32_t hdd_add_sta_info(struct sk_buff *skb,
3780 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3781{
3782 struct nlattr *nla_attr;
3783
3784 nla_attr = nla_nest_start(skb, idx);
3785 if (!nla_attr)
3786 goto fail;
3787 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3788 (hdd_sta_ctx->conn_info.signal + 100))) {
3789 hdd_err("put fail");
3790 goto fail;
3791 }
3792 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3793 goto fail;
3794 nla_nest_end(skb, nla_attr);
3795 return 0;
3796fail:
3797 return -EINVAL;
3798}
3799
3800/**
3801 * hdd_add_survey_info() - add survey info attribute
3802 * @skb: pointer to sk buff
3803 * @hdd_sta_ctx: pointer to hdd station context
3804 * @idx: attribute index
3805 *
3806 * Return: Success(0) or reason code for failure
3807 */
3808static int32_t hdd_add_survey_info(struct sk_buff *skb,
3809 hdd_station_ctx_t *hdd_sta_ctx,
3810 int idx)
3811{
3812 struct nlattr *nla_attr;
3813
3814 nla_attr = nla_nest_start(skb, idx);
3815 if (!nla_attr)
3816 goto fail;
3817 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3818 hdd_sta_ctx->conn_info.freq) ||
3819 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3820 (hdd_sta_ctx->conn_info.noise + 100))) {
3821 hdd_err("put fail");
3822 goto fail;
3823 }
3824 nla_nest_end(skb, nla_attr);
3825 return 0;
3826fail:
3827 return -EINVAL;
3828}
3829
3830/**
3831 * hdd_add_link_standard_info() - add link info attribute
3832 * @skb: pointer to sk buff
3833 * @hdd_sta_ctx: pointer to hdd station context
3834 * @idx: attribute index
3835 *
3836 * Return: Success(0) or reason code for failure
3837 */
3838static int32_t
3839hdd_add_link_standard_info(struct sk_buff *skb,
3840 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3841{
3842 struct nlattr *nla_attr;
3843
3844 nla_attr = nla_nest_start(skb, idx);
3845 if (!nla_attr)
3846 goto fail;
3847 if (nla_put(skb,
3848 NL80211_ATTR_SSID,
3849 hdd_sta_ctx->conn_info.SSID.SSID.length,
3850 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3851 hdd_err("put fail");
3852 goto fail;
3853 }
3854 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3855 goto fail;
3856 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3857 goto fail;
3858 nla_nest_end(skb, nla_attr);
3859 return 0;
3860fail:
3861 return -EINVAL;
3862}
3863
3864/**
3865 * hdd_add_ap_standard_info() - add ap info attribute
3866 * @skb: pointer to sk buff
3867 * @hdd_sta_ctx: pointer to hdd station context
3868 * @idx: attribute index
3869 *
3870 * Return: Success(0) or reason code for failure
3871 */
3872static int32_t
3873hdd_add_ap_standard_info(struct sk_buff *skb,
3874 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3875{
3876 struct nlattr *nla_attr;
3877
3878 nla_attr = nla_nest_start(skb, idx);
3879 if (!nla_attr)
3880 goto fail;
3881 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3882 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3883 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3884 &hdd_sta_ctx->conn_info.vht_caps)) {
3885 hdd_err("put fail");
3886 goto fail;
3887 }
3888 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3889 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3890 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3891 &hdd_sta_ctx->conn_info.ht_caps)) {
3892 hdd_err("put fail");
3893 goto fail;
3894 }
3895 nla_nest_end(skb, nla_attr);
3896 return 0;
3897fail:
3898 return -EINVAL;
3899}
3900
3901/**
3902 * hdd_get_station_info() - send BSS information to supplicant
3903 * @hdd_ctx: pointer to hdd context
3904 * @adapter: pointer to adapter
3905 *
3906 * Return: 0 if success else error status
3907 */
3908static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3909 hdd_adapter_t *adapter)
3910{
3911 struct sk_buff *skb = NULL;
3912 uint8_t *tmp_hs20 = NULL;
3913 uint32_t nl_buf_len;
3914 hdd_station_ctx_t *hdd_sta_ctx;
3915
3916 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3917
3918 nl_buf_len = NLMSG_HDRLEN;
3919 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3920 sizeof(hdd_sta_ctx->conn_info.freq) +
3921 sizeof(hdd_sta_ctx->conn_info.noise) +
3922 sizeof(hdd_sta_ctx->conn_info.signal) +
3923 (sizeof(uint32_t) * 2) +
3924 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3925 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3926 sizeof(hdd_sta_ctx->conn_info.authType) +
3927 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3928 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3929 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3930 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3931 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3932 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3933 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3934 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3935 1);
3936 }
3937 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3938 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3939 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3940 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3941
3942
3943 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3944 if (!skb) {
3945 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3946 return -ENOMEM;
3947 }
3948
3949 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3950 LINK_INFO_STANDARD_NL80211_ATTR)) {
3951 hdd_err("put fail");
3952 goto fail;
3953 }
3954 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3955 AP_INFO_STANDARD_NL80211_ATTR)) {
3956 hdd_err("put fail");
3957 goto fail;
3958 }
3959 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3960 hdd_sta_ctx->conn_info.roam_count) ||
3961 nla_put_u32(skb, INFO_AKM,
3962 hdd_convert_auth_type(
3963 hdd_sta_ctx->conn_info.authType)) ||
3964 nla_put_u32(skb, WLAN802_11_MODE,
3965 hdd_convert_dot11mode(
3966 hdd_sta_ctx->conn_info.dot11Mode))) {
3967 hdd_err("put fail");
3968 goto fail;
3969 }
3970 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3971 if (nla_put(skb, HT_OPERATION,
3972 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3973 &hdd_sta_ctx->conn_info.ht_operation)) {
3974 hdd_err("put fail");
3975 goto fail;
3976 }
3977 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3978 if (nla_put(skb, VHT_OPERATION,
3979 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3980 &hdd_sta_ctx->conn_info.vht_operation)) {
3981 hdd_err("put fail");
3982 goto fail;
3983 }
3984 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3985 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3986 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3987 tmp_hs20 + 1)) {
3988 hdd_err("put fail");
3989 goto fail;
3990 }
3991
3992 return cfg80211_vendor_cmd_reply(skb);
3993fail:
3994 if (skb)
3995 kfree_skb(skb);
3996 return -EINVAL;
3997}
3998
3999/**
4000 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4001 * @wiphy: corestack handler
4002 * @wdev: wireless device
4003 * @data: data
4004 * @data_len: data length
4005 *
4006 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4007 * Validate cmd attributes and send the station info to upper layers.
4008 *
4009 * Return: Success(0) or reason code for failure
4010 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05304011static int
Anurag Chouhan96919482016-07-13 16:36:57 +05304012__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4013 struct wireless_dev *wdev,
4014 const void *data,
4015 int data_len)
4016{
4017 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4018 struct net_device *dev = wdev->netdev;
4019 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4020 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
4021 int32_t status;
4022
4023 ENTER_DEV(dev);
4024 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4025 hdd_err("Command not allowed in FTM mode");
4026 status = -EPERM;
4027 goto out;
4028 }
4029
4030 status = wlan_hdd_validate_context(hdd_ctx);
4031 if (0 != status)
4032 goto out;
4033
4034
4035 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
4036 data, data_len, NULL);
4037 if (status) {
4038 hdd_err("Invalid ATTR");
4039 goto out;
4040 }
4041
4042 /* Parse and fetch Command Type*/
4043 if (tb[STATION_INFO]) {
4044 status = hdd_get_station_info(hdd_ctx, adapter);
4045 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
4046 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
4047 } else {
4048 hdd_err("get station info cmd type failed");
4049 status = -EINVAL;
4050 goto out;
4051 }
4052 EXIT();
4053out:
4054 return status;
4055}
4056
4057/**
4058 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4059 * @wiphy: corestack handler
4060 * @wdev: wireless device
4061 * @data: data
4062 * @data_len: data length
4063 *
4064 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4065 * Validate cmd attributes and send the station info to upper layers.
4066 *
4067 * Return: Success(0) or reason code for failure
4068 */
4069static int32_t
4070hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4071 struct wireless_dev *wdev,
4072 const void *data,
4073 int data_len)
4074{
4075 int ret;
4076
4077 cds_ssr_protect(__func__);
4078 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
4079 cds_ssr_unprotect(__func__);
4080
4081 return ret;
4082}
4083
4084/*
4085 * undef short names defined for get station command
4086 * used by __wlan_hdd_cfg80211_get_station_cmd()
4087 */
4088#undef STATION_INVALID
4089#undef STATION_INFO
4090#undef STATION_ASSOC_FAIL_REASON
4091#undef STATION_MAX
4092
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004093#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4094/**
4095 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4096 * @wiphy: pointer to wireless wiphy structure.
4097 * @wdev: pointer to wireless_dev structure.
4098 * @data: Pointer to the Key data
4099 * @data_len:Length of the data passed
4100 *
4101 * This is called when wlan driver needs to save the keys received via
4102 * vendor specific command.
4103 *
4104 * Return: Return the Success or Failure code.
4105 */
4106static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4107 struct wireless_dev *wdev,
4108 const void *data, int data_len)
4109{
4110 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4111 struct net_device *dev = wdev->netdev;
4112 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4113 hdd_context_t *hdd_ctx_ptr;
4114 int status;
4115
Jeff Johnson1f61b612016-02-12 16:28:33 -08004116 ENTER_DEV(dev);
4117
Anurag Chouhan6d760662016-02-20 16:05:43 +05304118 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004119 hdd_err("Command not allowed in FTM mode");
4120 return -EPERM;
4121 }
4122
4123 if ((data == NULL) || (data_len == 0) ||
4124 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004125 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004126 return -EINVAL;
4127 }
4128
4129 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4130 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004131 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004132 return -EINVAL;
4133 }
4134
4135 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304136 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004137 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004138 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4139 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004140 true,
4141 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304142 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4143 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004144 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4145 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4146 return 0;
4147}
4148
4149/**
4150 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4151 * @wiphy: pointer to wireless wiphy structure.
4152 * @wdev: pointer to wireless_dev structure.
4153 * @data: Pointer to the Key data
4154 * @data_len:Length of the data passed
4155 *
4156 * This is called when wlan driver needs to save the keys received via
4157 * vendor specific command.
4158 *
4159 * Return: Return the Success or Failure code.
4160 */
4161static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4162 struct wireless_dev *wdev,
4163 const void *data, int data_len)
4164{
4165 int ret;
4166
4167 cds_ssr_protect(__func__);
4168 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4169 cds_ssr_unprotect(__func__);
4170
4171 return ret;
4172}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004173#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004174
4175static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4176 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4177 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4178 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004179 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180};
4181
4182/**
4183 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4184 * @wiphy: pointer to wireless wiphy structure.
4185 * @wdev: pointer to wireless_dev structure.
4186 * @data: Pointer to the data to be passed via vendor interface
4187 * @data_len:Length of the data to be passed
4188 *
4189 * This is called when wlan driver needs to send wifi driver related info
4190 * (driver/fw version) to the user space application upon request.
4191 *
4192 * Return: Return the Success or Failure code.
4193 */
4194static int
4195__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4196 struct wireless_dev *wdev,
4197 const void *data, int data_len)
4198{
4199 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4200 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004201 tSirVersionString driver_version;
4202 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004203 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004204 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004205 struct sk_buff *reply_skb;
4206 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207
Jeff Johnson1f61b612016-02-12 16:28:33 -08004208 ENTER_DEV(wdev->netdev);
4209
Anurag Chouhan6d760662016-02-20 16:05:43 +05304210 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004211 hdd_err("Command not allowed in FTM mode");
4212 return -EPERM;
4213 }
4214
4215 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304216 if (status)
4217 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004218
4219 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4220 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004221 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004222 return -EINVAL;
4223 }
4224
4225 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004226 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004227 strlcpy(driver_version, QWLAN_VERSIONSTR,
4228 sizeof(driver_version));
4229 skb_len += strlen(driver_version) + 1;
4230 count++;
4231 }
4232
4233 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004234 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004235 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4236 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004237 snprintf(firmware_version, sizeof(firmware_version),
4238 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4239 skb_len += strlen(firmware_version) + 1;
4240 count++;
4241 }
4242
4243 if (count == 0) {
4244 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004245 return -EINVAL;
4246 }
4247
Ryan Hsu7ac88852016-04-28 10:20:34 -07004248 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4249 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4250
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004251 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004252 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004253 return -ENOMEM;
4254 }
4255
Ryan Hsu7ac88852016-04-28 10:20:34 -07004256 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4257 if (nla_put_string(reply_skb,
4258 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4259 driver_version))
4260 goto error_nla_fail;
4261 }
4262
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304263 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004264 if (nla_put_string(reply_skb,
4265 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4266 firmware_version))
4267 goto error_nla_fail;
4268 }
4269
4270 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4271 if (nla_put_u32(reply_skb,
4272 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4273 hdd_ctx->radio_index))
4274 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004275 }
4276
4277 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004278
4279error_nla_fail:
4280 hdd_err("nla put fail");
4281 kfree_skb(reply_skb);
4282 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004283}
4284
4285/**
4286 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4287 * @wiphy: pointer to wireless wiphy structure.
4288 * @wdev: pointer to wireless_dev structure.
4289 * @data: Pointer to the data to be passed via vendor interface
4290 * @data_len:Length of the data to be passed
4291 *
4292 * This is called when wlan driver needs to send wifi driver related info
4293 * (driver/fw version) to the user space application upon request.
4294 *
4295 * Return: Return the Success or Failure code.
4296 */
4297static int
4298wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4299 struct wireless_dev *wdev,
4300 const void *data, int data_len)
4301{
4302 int ret;
4303
4304 cds_ssr_protect(__func__);
4305 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4306 cds_ssr_unprotect(__func__);
4307
4308 return ret;
4309}
4310
4311/**
4312 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4313 * @wiphy: pointer to wireless wiphy structure.
4314 * @wdev: pointer to wireless_dev structure.
4315 * @data: Pointer to the data to be passed via vendor interface
4316 * @data_len:Length of the data to be passed
4317 *
4318 * This is called by userspace to know the supported logger features
4319 *
4320 * Return: Return the Success or Failure code.
4321 */
4322static int
4323__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4324 struct wireless_dev *wdev,
4325 const void *data, int data_len)
4326{
4327 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4328 int status;
4329 uint32_t features;
4330 struct sk_buff *reply_skb = NULL;
4331
Jeff Johnson1f61b612016-02-12 16:28:33 -08004332 ENTER_DEV(wdev->netdev);
4333
Anurag Chouhan6d760662016-02-20 16:05:43 +05304334 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335 hdd_err("Command not allowed in FTM mode");
4336 return -EPERM;
4337 }
4338
4339 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304340 if (status)
4341 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004342
4343 features = 0;
4344
4345 if (hdd_is_memdump_supported())
4346 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4347 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4348 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4349 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4350
4351 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4352 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4353 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004354 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 return -ENOMEM;
4356 }
4357
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004358 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004359 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4360 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004361 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 kfree_skb(reply_skb);
4363 return -EINVAL;
4364 }
4365
4366 return cfg80211_vendor_cmd_reply(reply_skb);
4367}
4368
4369/**
4370 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4371 * @wiphy: pointer to wireless wiphy structure.
4372 * @wdev: pointer to wireless_dev structure.
4373 * @data: Pointer to the data to be passed via vendor interface
4374 * @data_len:Length of the data to be passed
4375 *
4376 * This is called by userspace to know the supported logger features
4377 *
4378 * Return: Return the Success or Failure code.
4379 */
4380static int
4381wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4382 struct wireless_dev *wdev,
4383 const void *data, int data_len)
4384{
4385 int ret;
4386
4387 cds_ssr_protect(__func__);
4388 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4389 data, data_len);
4390 cds_ssr_unprotect(__func__);
4391
4392 return ret;
4393}
4394
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004395#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004396/**
4397 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304398 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004399 * @bssid: pointer to bssid of roamed AP.
4400 * @req_rsn_ie: Pointer to request RSN IE
4401 * @req_rsn_len: Length of the request RSN IE
4402 * @rsp_rsn_ie: Pointer to response RSN IE
4403 * @rsp_rsn_len: Length of the response RSN IE
4404 * @roam_info_ptr: Pointer to the roaming related information
4405 *
4406 * This is called when wlan driver needs to send the roaming and
4407 * authorization information after roaming.
4408 *
4409 * The information that would be sent is the request RSN IE, response
4410 * RSN IE and BSSID of the newly roamed AP.
4411 *
4412 * If the Authorized status is authenticated, then additional parameters
4413 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4414 * supplicant.
4415 *
4416 * The supplicant upon receiving this event would ignore the legacy
4417 * cfg80211_roamed call and use the entire information from this event.
4418 * The cfg80211_roamed should still co-exist since the kernel will
4419 * make use of the parameters even if the supplicant ignores it.
4420 *
4421 * Return: Return the Success or Failure code.
4422 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304423int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004424 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4425 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4426{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304427 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004429 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430 ENTER();
4431
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304432 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004433 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004434
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004435 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004436 !roam_info_ptr->roamSynchInProgress)
4437 return 0;
4438
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004439 /*
4440 * The user space has issued a disconnect when roaming is in
4441 * progress. The disconnect should be honored gracefully.
4442 * If the roaming is complete and the roam event is sent
4443 * back to the user space, it will get confused as it is
4444 * expecting a disconnect event. So, do not send the event
4445 * and handle the disconnect later.
4446 */
4447 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004448 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004449 return 0;
4450 }
4451
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004452 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304453 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004454 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4455 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4456 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004457 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004458 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4459 GFP_KERNEL);
4460
4461 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004462 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463 return -EINVAL;
4464 }
4465
4466 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4467 ETH_ALEN, bssid) ||
4468 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4469 req_rsn_len, req_rsn_ie) ||
4470 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4471 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004472 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004473 goto nla_put_failure;
4474 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004475 if (roam_info_ptr->synchAuthStatus ==
4476 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004477 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004478 if (nla_put_u8(skb,
4479 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4480 hdd_err("nla put fail");
4481 goto nla_put_failure;
4482 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004483 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4484 /* if FT or CCKM connection: dont send replay counter */
4485 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4486 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4487 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4488 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4489 nla_put(skb,
4490 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4491 SIR_REPLAY_CTR_LEN,
4492 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004493 hdd_err("non FT/non CCKM connection");
4494 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004495 goto nla_put_failure;
4496 }
4497 if (nla_put(skb,
4498 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4499 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4500 nla_put(skb,
4501 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4502 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4503 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004504 goto nla_put_failure;
4505 }
4506 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004507 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004508 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4509 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004510 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004511 goto nla_put_failure;
4512 }
4513 }
4514
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304515 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4516 roam_info_ptr->synchAuthStatus,
4517 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004518
4519 /*
4520 * Add subnet change status if subnet has changed
4521 * 0 = unchanged
4522 * 1 = changed
4523 * 2 = unknown
4524 */
4525 if (roam_info_ptr->subnet_change_status) {
4526 if (nla_put_u8(skb,
4527 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4528 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004529 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004530 goto nla_put_failure;
4531 }
4532 }
4533
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004534 cfg80211_vendor_event(skb, GFP_KERNEL);
4535 return 0;
4536
4537nla_put_failure:
4538 kfree_skb(skb);
4539 return -EINVAL;
4540}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004541#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004542
4543static const struct nla_policy
4544wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4545
4546 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4547 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4548 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304549 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304550 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4551 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004552 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4553 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4554 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4555 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4556 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304557 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004558};
4559
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004560/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304561 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4562 *
4563 * @adapter: Pointer to HDD adapter
4564 * @ie_data: Pointer to Scan IEs buffer
4565 * @ie_len: Length of Scan IEs
4566 *
4567 * Return: 0 on success; error number otherwise
4568 */
4569static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4570 uint8_t *ie_data, uint8_t ie_len)
4571{
4572 hdd_scaninfo_t *scan_info = NULL;
4573 scan_info = &adapter->scan_info;
4574
4575 if (scan_info->default_scan_ies) {
4576 qdf_mem_free(scan_info->default_scan_ies);
4577 scan_info->default_scan_ies = NULL;
4578 }
4579
4580 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4581 if (!scan_info->default_scan_ies)
4582 return -ENOMEM;
4583
4584 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4585 scan_info->default_scan_ies_len = ie_len;
4586 return 0;
4587}
4588
4589/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004590 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4591 * vendor command
4592 *
4593 * @wiphy: wiphy device pointer
4594 * @wdev: wireless device pointer
4595 * @data: Vendor command data buffer
4596 * @data_len: Buffer length
4597 *
4598 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4599 *
4600 * Return: Error code.
4601 */
4602static int
4603__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4604 struct wireless_dev *wdev,
4605 const void *data,
4606 int data_len)
4607{
4608 struct net_device *dev = wdev->netdev;
4609 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4610 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4611 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4612 int ret_val = 0;
4613 u32 modulated_dtim;
4614 u16 stats_avg_factor;
4615 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304616 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004617 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004618 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304619 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304620 int attr_len;
4621 int access_policy = 0;
4622 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4623 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304624 uint16_t scan_ie_len = 0;
4625 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304626 struct sir_set_tx_rx_aggregation_size request;
4627 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004628 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004629 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004630 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304631 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304632
Jeff Johnson1f61b612016-02-12 16:28:33 -08004633 ENTER_DEV(dev);
4634
Anurag Chouhan6d760662016-02-20 16:05:43 +05304635 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004636 hdd_err("Command not allowed in FTM mode");
4637 return -EPERM;
4638 }
4639
4640 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304641 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004642 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004643
4644 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4645 data, data_len,
4646 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004647 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004648 return -EINVAL;
4649 }
4650
Krunal Sonie3531942016-04-12 17:43:53 -07004651 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4652 ftm_capab = nla_get_u32(tb[
4653 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4654 hdd_ctx->config->fine_time_meas_cap =
4655 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4656 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304657 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004658 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004659 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4660 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004661 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004662 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4663 hdd_ctx->config->fine_time_meas_cap);
4664 }
4665
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004666 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4667 modulated_dtim = nla_get_u32(
4668 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4669
4670 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4671 adapter->sessionId,
4672 modulated_dtim);
4673
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304674 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004675 ret_val = -EPERM;
4676 }
4677
Kapil Gupta6213c012016-09-02 19:39:09 +05304678 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4679 qpower = nla_get_u8(
4680 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4681 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4682 ret_val = -EINVAL;
4683 }
4684
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004685 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4686 stats_avg_factor = nla_get_u16(
4687 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4688 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4689 adapter->sessionId,
4690 stats_avg_factor);
4691
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304692 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004693 ret_val = -EPERM;
4694 }
4695
4696
4697 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4698 guard_time = nla_get_u32(
4699 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4700 status = sme_configure_guard_time(hdd_ctx->hHal,
4701 adapter->sessionId,
4702 guard_time);
4703
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304704 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004705 ret_val = -EPERM;
4706 }
4707
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304708 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4709 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4710 attr_len = nla_len(
4711 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4712 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004713 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304714 attr_len);
4715 return -EINVAL;
4716 }
4717
4718 nla_memcpy(&vendor_ie,
4719 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4720 attr_len);
4721 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004722 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304723 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304724 }
4725
4726 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4727 access_policy = (int) nla_get_u32(
4728 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4729 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4730 (access_policy >
4731 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004732 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304733 access_policy);
4734 return -EINVAL;
4735 }
4736 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004737 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304738 access_policy);
4739 }
4740
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004741 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4742 retry = nla_get_u8(tb[
4743 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4744 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4745 CFG_NON_AGG_RETRY_MAX : retry;
4746 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4747 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4748 retry, PDEV_CMD);
4749 }
4750
4751 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4752 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4753 retry = retry > CFG_AGG_RETRY_MAX ?
4754 CFG_AGG_RETRY_MAX : retry;
4755
4756 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4757 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4758 CFG_AGG_RETRY_MIN : retry;
4759 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4760 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4761 retry, PDEV_CMD);
4762 }
4763
4764 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4765 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4766 retry = retry > CFG_MGMT_RETRY_MAX ?
4767 CFG_MGMT_RETRY_MAX : retry;
4768 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4769 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4770 retry, PDEV_CMD);
4771 }
4772
4773 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4774 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4775 retry = retry > CFG_CTRL_RETRY_MAX ?
4776 CFG_CTRL_RETRY_MAX : retry;
4777 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4778 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4779 retry, PDEV_CMD);
4780 }
4781
4782 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4783 delay = nla_get_u8(tb[
4784 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4785 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4786 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004787 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004788 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4789 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004790 abs_delay, PDEV_CMD);
4791 }
4792
4793 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
4794 abs_delay = nla_get_u8(tb[
4795 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
4796 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4797 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4798 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004799 }
4800
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304801 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4802 tx_fail_count = nla_get_u32(
4803 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4804 if (tx_fail_count) {
4805 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4806 adapter->sessionId, tx_fail_count);
4807 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004808 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304809 status);
4810 return -EINVAL;
4811 }
4812 }
4813 }
4814
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304815 if (vendor_ie_present && access_policy_present) {
4816 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4817 access_policy =
4818 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304819 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304820 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304821 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304822
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004823 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304824 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4825 adapter->sessionId, &vendor_ie[0],
4826 access_policy);
4827 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004828 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304829 return -EINVAL;
4830 }
4831 }
4832
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304833 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4834 set_value = nla_get_u8(
4835 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004836 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304837 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4838 }
4839
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304840 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4841 scan_ie_len = nla_len(
4842 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004843 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304844 scan_ie_len, adapter->sessionId,
4845 adapter->device_mode);
4846 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4847 scan_ie = (uint8_t *) nla_data(tb
4848 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304849
4850 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4851 scan_ie_len))
4852 hdd_err("Failed to save default scan IEs");
4853
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304854 if (adapter->device_mode == QDF_STA_MODE) {
4855 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4856 adapter->sessionId, scan_ie,
4857 scan_ie_len);
4858 if (QDF_STATUS_SUCCESS != status)
4859 ret_val = -EPERM;
4860 }
4861 } else
4862 ret_val = -EPERM;
4863 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304864
4865 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4866 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4867 /* if one is specified, both must be specified */
4868 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4869 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4870 hdd_err("Both TX and RX MPDU Aggregation required");
4871 return -EINVAL;
4872 }
4873
4874 request.tx_aggregation_size = nla_get_u8(
4875 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4876 request.rx_aggregation_size = nla_get_u8(
4877 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4878 request.vdev_id = adapter->sessionId;
4879
4880 if (request.tx_aggregation_size >=
4881 CFG_TX_AGGREGATION_SIZE_MIN &&
4882 request.tx_aggregation_size <=
4883 CFG_TX_AGGREGATION_SIZE_MAX &&
4884 request.rx_aggregation_size >=
4885 CFG_RX_AGGREGATION_SIZE_MIN &&
4886 request.rx_aggregation_size <=
4887 CFG_RX_AGGREGATION_SIZE_MAX) {
4888 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4889 if (qdf_status != QDF_STATUS_SUCCESS) {
4890 hdd_err("failed to set aggr sizes err %d",
4891 qdf_status);
4892 ret_val = -EPERM;
4893 }
4894 } else {
4895 hdd_err("TX %d RX %d MPDU aggr size not in range",
4896 request.tx_aggregation_size,
4897 request.rx_aggregation_size);
4898 ret_val = -EINVAL;
4899 }
4900 }
4901
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304902 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4903 uint8_t ignore_assoc_disallowed;
4904
4905 ignore_assoc_disallowed
4906 = nla_get_u8(tb[
4907 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004908 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304909 ignore_assoc_disallowed);
4910 if ((ignore_assoc_disallowed <
4911 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4912 (ignore_assoc_disallowed >
4913 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4914 return -EPERM;
4915
4916 sme_update_session_param(hdd_ctx->hHal,
4917 adapter->sessionId,
4918 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4919 ignore_assoc_disallowed);
4920 }
4921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004922 return ret_val;
4923}
4924
4925/**
4926 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4927 * vendor command
4928 *
4929 * @wiphy: wiphy device pointer
4930 * @wdev: wireless device pointer
4931 * @data: Vendor command data buffer
4932 * @data_len: Buffer length
4933 *
4934 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4935 *
4936 * Return: EOK or other error codes.
4937 */
4938static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4939 struct wireless_dev *wdev,
4940 const void *data,
4941 int data_len)
4942{
4943 int ret;
4944
4945 cds_ssr_protect(__func__);
4946 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4947 data, data_len);
4948 cds_ssr_unprotect(__func__);
4949
4950 return ret;
4951}
4952
4953static const struct
4954nla_policy
4955qca_wlan_vendor_wifi_logger_start_policy
4956[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4957 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4958 = {.type = NLA_U32 },
4959 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4960 = {.type = NLA_U32 },
4961 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4962 = {.type = NLA_U32 },
4963};
4964
4965/**
4966 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4967 * or disable the collection of packet statistics from the firmware
4968 * @wiphy: WIPHY structure pointer
4969 * @wdev: Wireless device structure pointer
4970 * @data: Pointer to the data received
4971 * @data_len: Length of the data received
4972 *
4973 * This function enables or disables the collection of packet statistics from
4974 * the firmware
4975 *
4976 * Return: 0 on success and errno on failure
4977 */
4978static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4979 struct wireless_dev *wdev,
4980 const void *data,
4981 int data_len)
4982{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304983 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004984 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4985 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4986 struct sir_wifi_start_log start_log;
4987
Jeff Johnson1f61b612016-02-12 16:28:33 -08004988 ENTER_DEV(wdev->netdev);
4989
Anurag Chouhan6d760662016-02-20 16:05:43 +05304990 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004991 hdd_err("Command not allowed in FTM mode");
4992 return -EPERM;
4993 }
4994
4995 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304996 if (status)
4997 return status;
4998
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304999 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
5000 hdd_err("Driver Modules are closed, can not start logger");
5001 return -EINVAL;
5002 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005003
5004 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
5005 data, data_len,
5006 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005007 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005008 return -EINVAL;
5009 }
5010
5011 /* Parse and fetch ring id */
5012 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005013 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005014 return -EINVAL;
5015 }
5016 start_log.ring_id = nla_get_u32(
5017 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005018 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005019
5020 /* Parse and fetch verbose level */
5021 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005022 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005023 return -EINVAL;
5024 }
5025 start_log.verbose_level = nla_get_u32(
5026 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005027 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005028
5029 /* Parse and fetch flag */
5030 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005031 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005032 return -EINVAL;
5033 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05305034 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005035 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005036 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005037
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305038 /* size is buff size which can be set using iwpriv command*/
5039 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05305040 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305041
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005042 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
5043
5044 if (start_log.ring_id == RING_ID_WAKELOCK) {
5045 /* Start/stop wakelock events */
5046 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
5047 cds_set_wakelock_logging(true);
5048 else
5049 cds_set_wakelock_logging(false);
5050 return 0;
5051 }
5052
5053 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305054 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005055 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005056 status);
5057 return -EINVAL;
5058 }
5059 return 0;
5060}
5061
5062/**
5063 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
5064 * or disable the collection of packet statistics from the firmware
5065 * @wiphy: WIPHY structure pointer
5066 * @wdev: Wireless device structure pointer
5067 * @data: Pointer to the data received
5068 * @data_len: Length of the data received
5069 *
5070 * This function is used to enable or disable the collection of packet
5071 * statistics from the firmware
5072 *
5073 * Return: 0 on success and errno on failure
5074 */
5075static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5076 struct wireless_dev *wdev,
5077 const void *data,
5078 int data_len)
5079{
5080 int ret = 0;
5081
5082 cds_ssr_protect(__func__);
5083 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
5084 wdev, data, data_len);
5085 cds_ssr_unprotect(__func__);
5086
5087 return ret;
5088}
5089
5090static const struct
5091nla_policy
5092qca_wlan_vendor_wifi_logger_get_ring_data_policy
5093[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
5094 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
5095 = {.type = NLA_U32 },
5096};
5097
5098/**
5099 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5100 * @wiphy: WIPHY structure pointer
5101 * @wdev: Wireless device structure pointer
5102 * @data: Pointer to the data received
5103 * @data_len: Length of the data received
5104 *
5105 * This function is used to flush or retrieve the per packet statistics from
5106 * the driver
5107 *
5108 * Return: 0 on success and errno on failure
5109 */
5110static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5111 struct wireless_dev *wdev,
5112 const void *data,
5113 int data_len)
5114{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305115 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005116 uint32_t ring_id;
5117 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5118 struct nlattr *tb
5119 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5120
Jeff Johnson1f61b612016-02-12 16:28:33 -08005121 ENTER_DEV(wdev->netdev);
5122
Anurag Chouhan6d760662016-02-20 16:05:43 +05305123 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005124 hdd_err("Command not allowed in FTM mode");
5125 return -EPERM;
5126 }
5127
5128 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305129 if (status)
5130 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005131
5132 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5133 data, data_len,
5134 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005135 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005136 return -EINVAL;
5137 }
5138
5139 /* Parse and fetch ring id */
5140 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005141 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005142 return -EINVAL;
5143 }
5144
5145 ring_id = nla_get_u32(
5146 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5147
5148 if (ring_id == RING_ID_PER_PACKET_STATS) {
5149 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005150 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305151 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5152 /*
5153 * As part of DRIVER ring ID, flush both driver and fw logs.
5154 * For other Ring ID's driver doesn't have any rings to flush
5155 */
5156 hdd_notice("Bug report triggered by framework");
5157
5158 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5159 WLAN_LOG_INDICATOR_FRAMEWORK,
5160 WLAN_LOG_REASON_CODE_UNUSED,
5161 true, false);
5162 if (QDF_STATUS_SUCCESS != status) {
5163 hdd_err("Failed to trigger bug report");
5164 return -EINVAL;
5165 }
5166 } else {
5167 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5168 WLAN_LOG_INDICATOR_FRAMEWORK,
5169 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005170 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005171 return 0;
5172}
5173
5174/**
5175 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5176 * @wiphy: WIPHY structure pointer
5177 * @wdev: Wireless device structure pointer
5178 * @data: Pointer to the data received
5179 * @data_len: Length of the data received
5180 *
5181 * This function is used to flush or retrieve the per packet statistics from
5182 * the driver
5183 *
5184 * Return: 0 on success and errno on failure
5185 */
5186static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5187 struct wireless_dev *wdev,
5188 const void *data,
5189 int data_len)
5190{
5191 int ret = 0;
5192
5193 cds_ssr_protect(__func__);
5194 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5195 wdev, data, data_len);
5196 cds_ssr_unprotect(__func__);
5197
5198 return ret;
5199}
5200
5201#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5202/**
5203 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5204 * @hdd_ctx: HDD context
5205 * @request_id: [input] request id
5206 * @pattern_id: [output] pattern id
5207 *
5208 * This function loops through request id to pattern id array
5209 * if the slot is available, store the request id and return pattern id
5210 * if entry exists, return the pattern id
5211 *
5212 * Return: 0 on success and errno on failure
5213 */
5214static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5215 uint32_t request_id,
5216 uint8_t *pattern_id)
5217{
5218 uint32_t i;
5219
5220 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5221 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5222 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5223 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5224 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5225 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5226 return 0;
5227 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5228 request_id) {
5229 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5230 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5231 return 0;
5232 }
5233 }
5234 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5235 return -EINVAL;
5236}
5237
5238/**
5239 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5240 * @hdd_ctx: HDD context
5241 * @request_id: [input] request id
5242 * @pattern_id: [output] pattern id
5243 *
5244 * This function loops through request id to pattern id array
5245 * reset request id to 0 (slot available again) and
5246 * return pattern id
5247 *
5248 * Return: 0 on success and errno on failure
5249 */
5250static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5251 uint32_t request_id,
5252 uint8_t *pattern_id)
5253{
5254 uint32_t i;
5255
5256 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5257 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5258 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5259 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5260 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5261 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5262 return 0;
5263 }
5264 }
5265 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5266 return -EINVAL;
5267}
5268
5269
5270/*
5271 * define short names for the global vendor params
5272 * used by __wlan_hdd_cfg80211_offloaded_packets()
5273 */
5274#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5275#define PARAM_REQUEST_ID \
5276 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5277#define PARAM_CONTROL \
5278 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5279#define PARAM_IP_PACKET \
5280 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5281#define PARAM_SRC_MAC_ADDR \
5282 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5283#define PARAM_DST_MAC_ADDR \
5284 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5285#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5286
5287/**
5288 * wlan_hdd_add_tx_ptrn() - add tx pattern
5289 * @adapter: adapter pointer
5290 * @hdd_ctx: hdd context
5291 * @tb: nl attributes
5292 *
5293 * This function reads the NL attributes and forms a AddTxPtrn message
5294 * posts it to SME.
5295 *
5296 */
5297static int
5298wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5299 struct nlattr **tb)
5300{
5301 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305302 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005303 uint32_t request_id, ret, len;
5304 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305305 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005306 uint16_t eth_type = htons(ETH_P_IP);
5307
5308 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005309 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005310 return -ENOTSUPP;
5311 }
5312
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305313 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005314 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005315 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005316 return -ENOMEM;
5317 }
5318
5319 /* Parse and fetch request Id */
5320 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005321 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005322 goto fail;
5323 }
5324
5325 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5326 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005327 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328 return -EINVAL;
5329 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005330 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005331
5332 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005333 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005334 goto fail;
5335 }
5336 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005337 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005338 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005339 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005340 goto fail;
5341 }
5342
5343 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005344 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005345 goto fail;
5346 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005347 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305348 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005349 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005350 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005351
Anurag Chouhanc5548422016-02-24 18:33:27 +05305352 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005353 &adapter->macAddressCurrent)) {
5354 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005355 goto fail;
5356 }
5357
5358 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005359 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005360 goto fail;
5361 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305362 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005363 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364 MAC_ADDR_ARRAY(dst_addr.bytes));
5365
5366 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005367 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005368 goto fail;
5369 }
5370 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005371 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372
5373 if (add_req->ucPtrnSize < 0 ||
5374 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5375 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005376 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377 add_req->ucPtrnSize);
5378 goto fail;
5379 }
5380
5381 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305382 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305383 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305384 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305385 QDF_MAC_ADDR_SIZE);
5386 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305387 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005388 len += 2;
5389
5390 /*
5391 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5392 * ------------------------------------------------------------
5393 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5394 * ------------------------------------------------------------
5395 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305396 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005397 nla_data(tb[PARAM_IP_PACKET]),
5398 add_req->ucPtrnSize);
5399 add_req->ucPtrnSize += len;
5400
5401 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5402 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005403 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005404 goto fail;
5405 }
5406 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005407 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005408
5409 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305410 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005411 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005412 goto fail;
5413 }
5414
5415 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305416 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417 return 0;
5418
5419fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305420 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421 return -EINVAL;
5422}
5423
5424/**
5425 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5426 * @adapter: adapter pointer
5427 * @hdd_ctx: hdd context
5428 * @tb: nl attributes
5429 *
5430 * This function reads the NL attributes and forms a DelTxPtrn message
5431 * posts it to SME.
5432 *
5433 */
5434static int
5435wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5436 struct nlattr **tb)
5437{
5438 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305439 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005440 uint32_t request_id, ret;
5441 uint8_t pattern_id = 0;
5442
5443 /* Parse and fetch request Id */
5444 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005445 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446 return -EINVAL;
5447 }
5448 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5449 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005450 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005451 return -EINVAL;
5452 }
5453
5454 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5455 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005456 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005457 return -EINVAL;
5458 }
5459
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305460 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005461 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005462 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005463 return -ENOMEM;
5464 }
5465
Anurag Chouhanc5548422016-02-24 18:33:27 +05305466 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005467 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005468 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005469 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005470 request_id, del_req->ucPtrnId);
5471
5472 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305473 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005474 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005475 goto fail;
5476 }
5477
5478 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305479 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005480 return 0;
5481
5482fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305483 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005484 return -EINVAL;
5485}
5486
5487
5488/**
5489 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5490 * @wiphy: Pointer to wireless phy
5491 * @wdev: Pointer to wireless device
5492 * @data: Pointer to data
5493 * @data_len: Data length
5494 *
5495 * Return: 0 on success, negative errno on failure
5496 */
5497static int
5498__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5499 struct wireless_dev *wdev,
5500 const void *data,
5501 int data_len)
5502{
5503 struct net_device *dev = wdev->netdev;
5504 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5505 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5506 struct nlattr *tb[PARAM_MAX + 1];
5507 uint8_t control;
5508 int ret;
5509 static const struct nla_policy policy[PARAM_MAX + 1] = {
5510 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5511 [PARAM_CONTROL] = { .type = NLA_U32 },
5512 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305513 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005514 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305515 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005516 [PARAM_PERIOD] = { .type = NLA_U32 },
5517 };
5518
Jeff Johnson1f61b612016-02-12 16:28:33 -08005519 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005520
Anurag Chouhan6d760662016-02-20 16:05:43 +05305521 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005522 hdd_err("Command not allowed in FTM mode");
5523 return -EPERM;
5524 }
5525
5526 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305527 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005528 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005529
5530 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005531 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005532 return -ENOTSUPP;
5533 }
5534
5535 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005536 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005537 return -EINVAL;
5538 }
5539
5540 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005541 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005542 return -EINVAL;
5543 }
5544 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005545 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005546
5547 if (control == WLAN_START_OFFLOADED_PACKETS)
5548 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005549 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005550 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005551
5552 hdd_err("Invalid control: %d", control);
5553
5554 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005555}
5556
5557/*
5558 * done with short names for the global vendor params
5559 * used by __wlan_hdd_cfg80211_offloaded_packets()
5560 */
5561#undef PARAM_MAX
5562#undef PARAM_REQUEST_ID
5563#undef PARAM_CONTROL
5564#undef PARAM_IP_PACKET
5565#undef PARAM_SRC_MAC_ADDR
5566#undef PARAM_DST_MAC_ADDR
5567#undef PARAM_PERIOD
5568
5569/**
5570 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5571 * @wiphy: wiphy structure pointer
5572 * @wdev: Wireless device structure pointer
5573 * @data: Pointer to the data received
5574 * @data_len: Length of @data
5575 *
5576 * Return: 0 on success; errno on failure
5577 */
5578static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5579 struct wireless_dev *wdev,
5580 const void *data,
5581 int data_len)
5582{
5583 int ret = 0;
5584
5585 cds_ssr_protect(__func__);
5586 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5587 wdev, data, data_len);
5588 cds_ssr_unprotect(__func__);
5589
5590 return ret;
5591}
5592#endif
5593
5594/*
5595 * define short names for the global vendor params
5596 * used by __wlan_hdd_cfg80211_monitor_rssi()
5597 */
5598#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5599#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5600#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5601#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5602#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5603
5604/**
5605 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5606 * @wiphy: Pointer to wireless phy
5607 * @wdev: Pointer to wireless device
5608 * @data: Pointer to data
5609 * @data_len: Data length
5610 *
5611 * Return: 0 on success, negative errno on failure
5612 */
5613static int
5614__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5615 struct wireless_dev *wdev,
5616 const void *data,
5617 int data_len)
5618{
5619 struct net_device *dev = wdev->netdev;
5620 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5621 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5622 struct nlattr *tb[PARAM_MAX + 1];
5623 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305624 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005625 int ret;
5626 uint32_t control;
5627 static const struct nla_policy policy[PARAM_MAX + 1] = {
5628 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5629 [PARAM_CONTROL] = { .type = NLA_U32 },
5630 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5631 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5632 };
5633
Jeff Johnson1f61b612016-02-12 16:28:33 -08005634 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005635
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305636 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5637 hdd_err("invalid session id: %d", adapter->sessionId);
5638 return -EINVAL;
5639 }
5640
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005641 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305642 if (ret)
5643 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005644
5645 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005646 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005647 return -ENOTSUPP;
5648 }
5649
5650 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005651 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005652 return -EINVAL;
5653 }
5654
5655 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005656 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005657 return -EINVAL;
5658 }
5659
5660 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005661 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005662 return -EINVAL;
5663 }
5664
5665 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5666 req.session_id = adapter->sessionId;
5667 control = nla_get_u32(tb[PARAM_CONTROL]);
5668
5669 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5670 req.control = true;
5671 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005672 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005673 return -EINVAL;
5674 }
5675
5676 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005677 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005678 return -EINVAL;
5679 }
5680
5681 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5682 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5683
5684 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005685 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005686 req.min_rssi, req.max_rssi);
5687 return -EINVAL;
5688 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005689 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005690 req.min_rssi, req.max_rssi);
5691
5692 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5693 req.control = false;
5694 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005695 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005696 return -EINVAL;
5697 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005698 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005699 req.request_id, req.session_id, req.control);
5700
5701 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305702 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005703 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005704 return -EINVAL;
5705 }
5706
5707 return 0;
5708}
5709
5710/*
5711 * done with short names for the global vendor params
5712 * used by __wlan_hdd_cfg80211_monitor_rssi()
5713 */
5714#undef PARAM_MAX
5715#undef PARAM_CONTROL
5716#undef PARAM_REQUEST_ID
5717#undef PARAM_MAX_RSSI
5718#undef PARAM_MIN_RSSI
5719
5720/**
5721 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5722 * @wiphy: wiphy structure pointer
5723 * @wdev: Wireless device structure pointer
5724 * @data: Pointer to the data received
5725 * @data_len: Length of @data
5726 *
5727 * Return: 0 on success; errno on failure
5728 */
5729static int
5730wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5731 const void *data, int data_len)
5732{
5733 int ret;
5734
5735 cds_ssr_protect(__func__);
5736 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5737 cds_ssr_unprotect(__func__);
5738
5739 return ret;
5740}
5741
5742/**
5743 * hdd_rssi_threshold_breached() - rssi breached NL event
5744 * @hddctx: HDD context
5745 * @data: rssi breached event data
5746 *
5747 * This function reads the rssi breached event %data and fill in the skb with
5748 * NL attributes and send up the NL event.
5749 *
5750 * Return: none
5751 */
5752void hdd_rssi_threshold_breached(void *hddctx,
5753 struct rssi_breach_event *data)
5754{
5755 hdd_context_t *hdd_ctx = hddctx;
5756 struct sk_buff *skb;
5757
5758 ENTER();
5759
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305760 if (wlan_hdd_validate_context(hdd_ctx))
5761 return;
5762 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005763 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005764 return;
5765 }
5766
5767 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5768 NULL,
5769 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5770 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5771 GFP_KERNEL);
5772
5773 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005774 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005775 return;
5776 }
5777
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005778 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005779 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005780 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005781 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5782
5783 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5784 data->request_id) ||
5785 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5786 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5787 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5788 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005789 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005790 goto fail;
5791 }
5792
5793 cfg80211_vendor_event(skb, GFP_KERNEL);
5794 return;
5795
5796fail:
5797 kfree_skb(skb);
5798 return;
5799}
5800
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305801static const struct nla_policy
5802ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5803 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5804};
5805
5806/**
5807 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5808 * @wiphy: Pointer to wireless phy
5809 * @wdev: Pointer to wireless device
5810 * @data: Pointer to data
5811 * @data_len: Length of @data
5812 *
5813 * Return: 0 on success, negative errno on failure
5814 */
5815static int
5816__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5817 struct wireless_dev *wdev,
5818 const void *data, int data_len)
5819{
5820 int status;
5821 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5822 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005823 struct net_device *dev = wdev->netdev;
5824 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305825
5826 ENTER_DEV(wdev->netdev);
5827
5828 status = wlan_hdd_validate_context(pHddCtx);
5829 if (0 != status)
5830 return status;
5831 if (!pHddCtx->config->fhostNSOffload) {
5832 hdd_err("ND Offload not supported");
5833 return -EINVAL;
5834 }
5835
5836 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5837 (struct nlattr *)data,
5838 data_len, ns_offload_set_policy)) {
5839 hdd_err("nla_parse failed");
5840 return -EINVAL;
5841 }
5842
5843 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5844 hdd_err("ND Offload flag attribute not present");
5845 return -EINVAL;
5846 }
5847
5848 pHddCtx->ns_offload_enable =
5849 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5850
Dustin Brownd8279d22016-09-07 14:52:57 -07005851 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305852 if (pHddCtx->ns_offload_enable)
5853 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5854 else
5855 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005856
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305857 return 0;
5858}
5859
5860/**
5861 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5862 * @wiphy: pointer to wireless wiphy structure.
5863 * @wdev: pointer to wireless_dev structure.
5864 * @data: Pointer to the data to be passed via vendor interface
5865 * @data_len:Length of the data to be passed
5866 *
5867 * Return: Return the Success or Failure code.
5868 */
5869static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5870 struct wireless_dev *wdev,
5871 const void *data, int data_len)
5872{
5873 int ret;
5874
5875 cds_ssr_protect(__func__);
5876 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5877 cds_ssr_unprotect(__func__);
5878
5879 return ret;
5880}
5881
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005882/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5883 * @wiphy: Pointer to wireless phy
5884 * @wdev: Pointer to wireless device
5885 * @data: Pointer to data
5886 * @data_len: Data length
5887 *
5888 * This function return the preferred frequency list generated by the policy
5889 * manager.
5890 *
5891 * Return: success or failure code
5892 */
5893static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5894 struct wireless_dev
5895 *wdev, const void *data,
5896 int data_len)
5897{
5898 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5899 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305900 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305901 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005902 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305903 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005904 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005905 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5906 struct sk_buff *reply_skb;
5907
Jeff Johnson1f61b612016-02-12 16:28:33 -08005908 ENTER_DEV(wdev->netdev);
5909
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005910 ret = wlan_hdd_validate_context(hdd_ctx);
5911 if (ret)
5912 return -EINVAL;
5913
5914 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5915 data, data_len, NULL)) {
5916 hdd_err("Invalid ATTR");
5917 return -EINVAL;
5918 }
5919
5920 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5921 hdd_err("attr interface type failed");
5922 return -EINVAL;
5923 }
5924
5925 intf_mode = nla_get_u32(tb
5926 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5927
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005928 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005929 hdd_err("Invalid interface type");
5930 return -EINVAL;
5931 }
5932
5933 hdd_debug("Userspace requested pref freq list");
5934
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005935 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
5936 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305937 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305938 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005939 hdd_err("Get pcl failed");
5940 return -EINVAL;
5941 }
5942
5943 /* convert channel number to frequency */
5944 for (i = 0; i < pcl_len; i++) {
5945 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5946 freq_list[i] =
5947 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005948 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005949 else
5950 freq_list[i] =
5951 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005952 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005953 }
5954
5955 /* send the freq_list back to supplicant */
5956 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5957 sizeof(u32) *
5958 pcl_len +
5959 NLMSG_HDRLEN);
5960
5961 if (!reply_skb) {
5962 hdd_err("Allocate reply_skb failed");
5963 return -EINVAL;
5964 }
5965
5966 if (nla_put_u32(reply_skb,
5967 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5968 intf_mode) ||
5969 nla_put(reply_skb,
5970 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5971 sizeof(uint32_t) * pcl_len,
5972 freq_list)) {
5973 hdd_err("nla put fail");
5974 kfree_skb(reply_skb);
5975 return -EINVAL;
5976 }
5977
5978 return cfg80211_vendor_cmd_reply(reply_skb);
5979}
5980
5981/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5982 * @wiphy: Pointer to wireless phy
5983 * @wdev: Pointer to wireless device
5984 * @data: Pointer to data
5985 * @data_len: Data length
5986 *
5987 * This function return the preferred frequency list generated by the policy
5988 * manager.
5989 *
5990 * Return: success or failure code
5991 */
5992static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5993 struct wireless_dev
5994 *wdev, const void *data,
5995 int data_len)
5996{
5997 int ret = 0;
5998
5999 cds_ssr_protect(__func__);
6000 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
6001 data, data_len);
6002 cds_ssr_unprotect(__func__);
6003
6004 return ret;
6005}
6006
6007/**
6008 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6009 * @wiphy: Pointer to wireless phy
6010 * @wdev: Pointer to wireless device
6011 * @data: Pointer to data
6012 * @data_len: Data length
6013 *
6014 * Return: 0 on success, negative errno on failure
6015 */
6016static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6017 struct wireless_dev *wdev,
6018 const void *data,
6019 int data_len)
6020{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05306021 struct net_device *ndev = wdev->netdev;
6022 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006023 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6024 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006025 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006026 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6027 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006028
Jeff Johnson1f61b612016-02-12 16:28:33 -08006029 ENTER_DEV(ndev);
6030
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006031 ret = wlan_hdd_validate_context(hdd_ctx);
6032 if (ret)
6033 return ret;
6034
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006035 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
6036 data, data_len, NULL)) {
6037 hdd_err("Invalid ATTR");
6038 return -EINVAL;
6039 }
6040
6041 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
6042 hdd_err("attr interface type failed");
6043 return -EINVAL;
6044 }
6045
6046 intf_mode = nla_get_u32(tb
6047 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
6048
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006049 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006050 hdd_err("Invalid interface type");
6051 return -EINVAL;
6052 }
6053
6054 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
6055 hdd_err("attr probable freq failed");
6056 return -EINVAL;
6057 }
6058
6059 channel_hint = cds_freq_to_chan(nla_get_u32(tb
6060 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
6061
6062 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006063 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006064 channel_hint, HW_MODE_20_MHZ)) {
6065 hdd_err("Set channel hint failed due to concurrency check");
6066 return -EINVAL;
6067 }
6068
Krunal Soni09e55032016-06-07 10:06:55 -07006069 if (0 != wlan_hdd_check_remain_on_channel(adapter))
6070 hdd_warn("Remain On Channel Pending");
6071
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006072 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006073 if (!QDF_IS_STATUS_SUCCESS(ret))
6074 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006075
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006076 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
6077 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07006078 SIR_UPDATE_REASON_SET_OPER_CHAN);
6079 if (QDF_STATUS_E_FAILURE == ret) {
6080 /* return in the failure case */
6081 hdd_err("ERROR: connections update failed!!");
6082 return -EINVAL;
6083 }
6084
6085 if (QDF_STATUS_SUCCESS == ret) {
6086 /*
6087 * Success is the only case for which we expect hw mode
6088 * change to take place, hence we need to wait.
6089 * For any other return value it should be a pass
6090 * through
6091 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006092 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006093 if (!QDF_IS_STATUS_SUCCESS(ret)) {
6094 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006095 return -EINVAL;
6096 }
6097
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006098 }
6099
6100 return 0;
6101}
6102
6103/**
6104 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6105 * @wiphy: Pointer to wireless phy
6106 * @wdev: Pointer to wireless device
6107 * @data: Pointer to data
6108 * @data_len: Data length
6109 *
6110 * Return: 0 on success, negative errno on failure
6111 */
6112static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6113 struct wireless_dev *wdev,
6114 const void *data,
6115 int data_len)
6116{
6117 int ret = 0;
6118
6119 cds_ssr_protect(__func__);
6120 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6121 data, data_len);
6122 cds_ssr_unprotect(__func__);
6123
6124 return ret;
6125}
6126
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306127static const struct
6128nla_policy
6129qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6130 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6131};
6132
6133/**
6134 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6135 * @wiphy: WIPHY structure pointer
6136 * @wdev: Wireless device structure pointer
6137 * @data: Pointer to the data received
6138 * @data_len: Length of the data received
6139 *
6140 * This function is used to get link properties like nss, rate flags and
6141 * operating frequency for the active connection with the given peer.
6142 *
6143 * Return: 0 on success and errno on failure
6144 */
6145static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6146 struct wireless_dev *wdev,
6147 const void *data,
6148 int data_len)
6149{
6150 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6151 struct net_device *dev = wdev->netdev;
6152 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6153 hdd_station_ctx_t *hdd_sta_ctx;
6154 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306155 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306156 uint32_t sta_id;
6157 struct sk_buff *reply_skb;
6158 uint32_t rate_flags = 0;
6159 uint8_t nss;
6160 uint8_t final_rate_flags = 0;
6161 uint32_t freq;
6162
Jeff Johnson1f61b612016-02-12 16:28:33 -08006163 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306164
Anurag Chouhan6d760662016-02-20 16:05:43 +05306165 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306166 hdd_err("Command not allowed in FTM mode");
6167 return -EPERM;
6168 }
6169
6170 if (0 != wlan_hdd_validate_context(hdd_ctx))
6171 return -EINVAL;
6172
6173 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6174 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006175 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306176 return -EINVAL;
6177 }
6178
6179 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006180 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306181 adapter->device_mode);
6182 return -EINVAL;
6183 }
6184
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306185 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306186 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006187 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306188 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6189
Krunal Sonib4326f22016-03-10 13:05:51 -08006190 if (adapter->device_mode == QDF_STA_MODE ||
6191 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306192 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6193 if ((hdd_sta_ctx->conn_info.connState !=
6194 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306195 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306196 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006197 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306198 MAC_ADDR_ARRAY(peer_mac));
6199 return -EINVAL;
6200 }
6201
6202 nss = hdd_sta_ctx->conn_info.nss;
6203 freq = cds_chan_to_freq(
6204 hdd_sta_ctx->conn_info.operationChannel);
6205 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006206 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6207 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306208
6209 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6210 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306211 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306212 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306213 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306214 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306215 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306216 break;
6217 }
6218
6219 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006220 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306221 MAC_ADDR_ARRAY(peer_mac));
6222 return -EINVAL;
6223 }
6224
6225 nss = adapter->aStaInfo[sta_id].nss;
6226 freq = cds_chan_to_freq(
6227 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6228 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6229 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006230 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306231 MAC_ADDR_ARRAY(peer_mac));
6232 return -EINVAL;
6233 }
6234
6235 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6236 if (rate_flags & eHAL_TX_RATE_VHT80) {
6237 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006238#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306239 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006240#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306241 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6242 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006243#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306244 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006245#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306246 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6247 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6248 } else if (rate_flags &
6249 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6250 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006251#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306252 if (rate_flags & eHAL_TX_RATE_HT40)
6253 final_rate_flags |=
6254 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006255#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306256 }
6257
6258 if (rate_flags & eHAL_TX_RATE_SGI) {
6259 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6260 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6261 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6262 }
6263 }
6264
6265 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6266 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6267
6268 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006269 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306270 return -EINVAL;
6271 }
6272
6273 if (nla_put_u8(reply_skb,
6274 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6275 nss) ||
6276 nla_put_u8(reply_skb,
6277 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6278 final_rate_flags) ||
6279 nla_put_u32(reply_skb,
6280 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6281 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006282 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306283 kfree_skb(reply_skb);
6284 return -EINVAL;
6285 }
6286
6287 return cfg80211_vendor_cmd_reply(reply_skb);
6288}
6289
6290/**
6291 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6292 * properties.
6293 * @wiphy: WIPHY structure pointer
6294 * @wdev: Wireless device structure pointer
6295 * @data: Pointer to the data received
6296 * @data_len: Length of the data received
6297 *
6298 * This function is used to get link properties like nss, rate flags and
6299 * operating frequency for the active connection with the given peer.
6300 *
6301 * Return: 0 on success and errno on failure
6302 */
6303static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6304 struct wireless_dev *wdev,
6305 const void *data,
6306 int data_len)
6307{
6308 int ret = 0;
6309
6310 cds_ssr_protect(__func__);
6311 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6312 wdev, data, data_len);
6313 cds_ssr_unprotect(__func__);
6314
6315 return ret;
6316}
6317
Peng Xu278d0122015-09-24 16:34:17 -07006318static const struct
6319nla_policy
6320qca_wlan_vendor_ota_test_policy
6321[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6322 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6323};
6324
6325/**
6326 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6327 * @wiphy: Pointer to wireless phy
6328 * @wdev: Pointer to wireless device
6329 * @data: Pointer to data
6330 * @data_len: Data length
6331 *
6332 * Return: 0 on success, negative errno on failure
6333 */
6334static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6335 struct wireless_dev *wdev,
6336 const void *data,
6337 int data_len)
6338{
6339 struct net_device *dev = wdev->netdev;
6340 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6341 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6342 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6343 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6344 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306345 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006346 uint32_t current_roam_state;
6347
Jeff Johnson1f61b612016-02-12 16:28:33 -08006348 ENTER_DEV(dev);
6349
Anurag Chouhan6d760662016-02-20 16:05:43 +05306350 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006351 hdd_err("Command not allowed in FTM mode");
6352 return -EPERM;
6353 }
6354
6355 if (0 != wlan_hdd_validate_context(hdd_ctx))
6356 return -EINVAL;
6357
6358 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6359 data, data_len,
6360 qca_wlan_vendor_ota_test_policy)) {
6361 hdd_err("invalid attr");
6362 return -EINVAL;
6363 }
6364
6365 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6366 hdd_err("attr ota test failed");
6367 return -EINVAL;
6368 }
6369
6370 ota_enable = nla_get_u8(
6371 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6372
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006373 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006374 if (ota_enable != 1) {
6375 hdd_err("Invalid value, only enable test mode is supported!");
6376 return -EINVAL;
6377 }
6378
6379 current_roam_state =
6380 sme_get_current_roam_state(hal, adapter->sessionId);
6381 status = sme_stop_roaming(hal, adapter->sessionId,
6382 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306383 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006384 hdd_err("Enable/Disable roaming failed");
6385 return -EINVAL;
6386 }
6387
6388 status = sme_ps_enable_disable(hal, adapter->sessionId,
6389 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306390 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006391 hdd_err("Enable/Disable power save failed");
6392 /* restore previous roaming setting */
6393 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6394 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6395 status = sme_start_roaming(hal, adapter->sessionId,
6396 eCsrHddIssued);
6397 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6398 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6399 status = sme_stop_roaming(hal, adapter->sessionId,
6400 eCsrHddIssued);
6401
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306402 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006403 hdd_err("Restoring roaming state failed");
6404
6405 return -EINVAL;
6406 }
6407
6408
6409 return 0;
6410}
6411
6412/**
6413 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6414 * @wiphy: Pointer to wireless phy
6415 * @wdev: Pointer to wireless device
6416 * @data: Pointer to data
6417 * @data_len: Data length
6418 *
6419 * Return: 0 on success, negative errno on failure
6420 */
6421static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6422 struct wireless_dev *wdev,
6423 const void *data,
6424 int data_len)
6425{
6426 int ret = 0;
6427
6428 cds_ssr_protect(__func__);
6429 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6430 cds_ssr_unprotect(__func__);
6431
6432 return ret;
6433}
6434
Peng Xu4d67c8f2015-10-16 16:02:26 -07006435/**
6436 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6437 * @wiphy: Pointer to wireless phy
6438 * @wdev: Pointer to wireless device
6439 * @data: Pointer to data
6440 * @data_len: Data length
6441 *
6442 * Return: 0 on success, negative errno on failure
6443 */
6444static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6445 struct wireless_dev *wdev,
6446 const void *data,
6447 int data_len)
6448{
6449 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6450 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006451 hdd_adapter_t *adapter;
6452 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006453 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6454 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006455 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006456
Jeff Johnson1f61b612016-02-12 16:28:33 -08006457 ENTER_DEV(dev);
6458
Peng Xu4d67c8f2015-10-16 16:02:26 -07006459 ret = wlan_hdd_validate_context(hdd_ctx);
6460 if (ret)
6461 return ret;
6462
6463 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6464
6465 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6466 data, data_len, NULL)) {
6467 hdd_err("Invalid ATTR");
6468 return -EINVAL;
6469 }
6470
6471 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6472 hdd_err("attr tx power scale failed");
6473 return -EINVAL;
6474 }
6475
6476 scale_value = nla_get_u8(tb
6477 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6478
6479 if (scale_value > MAX_TXPOWER_SCALE) {
6480 hdd_err("Invalid tx power scale level");
6481 return -EINVAL;
6482 }
6483
Peng Xu62c8c432016-05-09 15:23:02 -07006484 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006485
Peng Xu62c8c432016-05-09 15:23:02 -07006486 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006487 hdd_err("Set tx power scale failed");
6488 return -EINVAL;
6489 }
6490
6491 return 0;
6492}
6493
6494/**
6495 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6496 * @wiphy: Pointer to wireless phy
6497 * @wdev: Pointer to wireless device
6498 * @data: Pointer to data
6499 * @data_len: Data length
6500 *
6501 * Return: 0 on success, negative errno on failure
6502 */
6503static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6504 struct wireless_dev *wdev,
6505 const void *data,
6506 int data_len)
6507{
Peng Xu62c8c432016-05-09 15:23:02 -07006508 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006509
6510 cds_ssr_protect(__func__);
6511 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6512 data, data_len);
6513 cds_ssr_unprotect(__func__);
6514
6515 return ret;
6516}
6517
6518/**
6519 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6520 * @wiphy: Pointer to wireless phy
6521 * @wdev: Pointer to wireless device
6522 * @data: Pointer to data
6523 * @data_len: Data length
6524 *
6525 * Return: 0 on success, negative errno on failure
6526 */
6527static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6528 struct wireless_dev *wdev,
6529 const void *data,
6530 int data_len)
6531{
6532 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6533 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006534 hdd_adapter_t *adapter;
6535 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006536 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6537 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006538 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006539
Jeff Johnson1f61b612016-02-12 16:28:33 -08006540 ENTER_DEV(dev);
6541
Peng Xu4d67c8f2015-10-16 16:02:26 -07006542 ret = wlan_hdd_validate_context(hdd_ctx);
6543 if (ret)
6544 return ret;
6545
6546 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6547
6548 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6549 data, data_len, NULL)) {
6550 hdd_err("Invalid ATTR");
6551 return -EINVAL;
6552 }
6553
6554 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6555 hdd_err("attr tx power decrease db value failed");
6556 return -EINVAL;
6557 }
6558
6559 scale_value = nla_get_u8(tb
6560 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6561
Peng Xu62c8c432016-05-09 15:23:02 -07006562 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6563 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006564
Peng Xu62c8c432016-05-09 15:23:02 -07006565 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006566 hdd_err("Set tx power decrease db failed");
6567 return -EINVAL;
6568 }
6569
6570 return 0;
6571}
6572
6573/**
6574 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6575 * @wiphy: Pointer to wireless phy
6576 * @wdev: Pointer to wireless device
6577 * @data: Pointer to data
6578 * @data_len: Data length
6579 *
6580 * Return: 0 on success, negative errno on failure
6581 */
6582static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6583 struct wireless_dev *wdev,
6584 const void *data,
6585 int data_len)
6586{
Peng Xu62c8c432016-05-09 15:23:02 -07006587 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006588
6589 cds_ssr_protect(__func__);
6590 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6591 data, data_len);
6592 cds_ssr_unprotect(__func__);
6593
6594 return ret;
6595}
Peng Xu8fdaa492016-06-22 10:20:47 -07006596
6597/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306598 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6599 * @wiphy: Pointer to wireless phy
6600 * @wdev: Pointer to wireless device
6601 * @data: Pointer to data
6602 * @data_len: Data length
6603 *
6604 * Processes the conditional channel switch request and invokes the helper
6605 * APIs to process the channel switch request.
6606 *
6607 * Return: 0 on success, negative errno on failure
6608 */
6609static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6610 struct wireless_dev *wdev,
6611 const void *data,
6612 int data_len)
6613{
6614 int ret;
6615 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6616 struct net_device *dev = wdev->netdev;
6617 hdd_adapter_t *adapter;
6618 struct nlattr
6619 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6620 uint32_t freq_len, i;
6621 uint32_t *freq;
6622 uint8_t chans[QDF_MAX_NUM_CHAN];
6623
6624 ENTER_DEV(dev);
6625
6626 ret = wlan_hdd_validate_context(hdd_ctx);
6627 if (ret)
6628 return ret;
6629
6630 if (!hdd_ctx->config->enableDFSMasterCap) {
6631 hdd_err("DFS master capability is not present in the driver");
6632 return -EINVAL;
6633 }
6634
6635 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6636 hdd_err("Command not allowed in FTM mode");
6637 return -EPERM;
6638 }
6639
6640 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6641 if (adapter->device_mode != QDF_SAP_MODE) {
6642 hdd_err("Invalid device mode %d", adapter->device_mode);
6643 return -EINVAL;
6644 }
6645
6646 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6647 data, data_len, NULL)) {
6648 hdd_err("Invalid ATTR");
6649 return -EINVAL;
6650 }
6651
6652 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6653 hdd_err("Frequency list is missing");
6654 return -EINVAL;
6655 }
6656
6657 freq_len = nla_len(
6658 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6659 sizeof(uint32_t);
6660
6661 if (freq_len > QDF_MAX_NUM_CHAN) {
6662 hdd_err("insufficient space to hold channels");
6663 return -ENOMEM;
6664 }
6665
6666 hdd_debug("freq_len=%d", freq_len);
6667
6668 freq = nla_data(
6669 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6670
6671
6672 for (i = 0; i < freq_len; i++) {
6673 if (freq[i] == 0)
6674 chans[i] = 0;
6675 else
6676 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6677
6678 hdd_debug("freq[%d]=%d", i, freq[i]);
6679 }
6680
6681 /*
6682 * The input frequency list from user space is designed to be a
6683 * priority based frequency list. This is only to accommodate any
6684 * future request. But, current requirement is only to perform CAC
6685 * on a single channel. So, the first entry from the list is picked.
6686 *
6687 * If channel is zero, any channel in the available outdoor regulatory
6688 * domain will be selected.
6689 */
6690 ret = wlan_hdd_request_pre_cac(chans[0]);
6691 if (ret) {
6692 hdd_err("pre cac request failed with reason:%d", ret);
6693 return ret;
6694 }
6695
6696 return 0;
6697}
6698
6699/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006700 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6701 * @wiphy: Pointer to wireless phy
6702 * @wdev: Pointer to wireless device
6703 * @data: Pointer to data
6704 * @data_len: Data length
6705 *
6706 * This function is to process the p2p listen offload start vendor
6707 * command. It parses the input parameters and invoke WMA API to
6708 * send the command to firmware.
6709 *
6710 * Return: 0 on success, negative errno on failure
6711 */
6712static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6713 struct wireless_dev *wdev,
6714 const void *data,
6715 int data_len)
6716{
6717 int ret;
6718 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6719 struct net_device *dev = wdev->netdev;
6720 hdd_adapter_t *adapter;
6721 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6722 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006723
6724 ENTER_DEV(dev);
6725
6726 ret = wlan_hdd_validate_context(hdd_ctx);
6727 if (ret)
6728 return ret;
6729
6730 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6731 hdd_err("Command not allowed in FTM mode");
6732 return -EPERM;
6733 }
6734
6735 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6736 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6737 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6738 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6739 hdd_err("Invalid device mode %d", adapter->device_mode);
6740 return -EINVAL;
6741 }
6742
6743 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6744 data, data_len, NULL)) {
6745 hdd_err("Invalid ATTR");
6746 return -EINVAL;
6747 }
6748
6749 memset(&params, 0, sizeof(params));
6750
6751 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6752 params.ctl_flags = 1; /* set to default value */
6753 else
6754 params.ctl_flags = nla_get_u32(tb
6755 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6756
6757 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6758 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6759 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6760 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6761 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6762 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6763 hdd_err("Attribute parsing failed");
6764 return -EINVAL;
6765 }
6766
6767 params.vdev_id = adapter->sessionId;
6768 params.freq = nla_get_u32(tb
6769 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6770 if ((params.freq != 2412) && (params.freq != 2437) &&
6771 (params.freq != 2462)) {
6772 hdd_err("Invalid listening channel: %d", params.freq);
6773 return -EINVAL;
6774 }
6775
6776 params.period = nla_get_u32(tb
6777 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6778 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6779 hdd_err("Invalid period: %d", params.period);
6780 return -EINVAL;
6781 }
6782
6783 params.interval = nla_get_u32(tb
6784 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6785 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6786 hdd_err("Invalid interval: %d", params.interval);
6787 return -EINVAL;
6788 }
6789
6790 params.count = nla_get_u32(tb
6791 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006792 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006793 hdd_err("Invalid count: %d", params.count);
6794 return -EINVAL;
6795 }
6796
6797 params.device_types = nla_data(tb
6798 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6799 if (params.device_types == NULL) {
6800 hdd_err("Invalid device types");
6801 return -EINVAL;
6802 }
6803
6804 params.dev_types_len = nla_len(tb
6805 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6806 if (params.dev_types_len < 8) {
6807 hdd_err("Invalid device type length: %d", params.dev_types_len);
6808 return -EINVAL;
6809 }
6810
6811 params.probe_resp_tmplt = nla_data(tb
6812 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6813 if (params.probe_resp_tmplt == NULL) {
6814 hdd_err("Invalid probe response template");
6815 return -EINVAL;
6816 }
6817
6818 params.probe_resp_len = nla_len(tb
6819 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6820 if (params.probe_resp_len == 0) {
6821 hdd_err("Invalid probe resp template length: %d",
6822 params.probe_resp_len);
6823 return -EINVAL;
6824 }
6825
6826 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6827 params.freq, params.period, params.interval, params.count);
6828
Wu Gao9a704f42017-03-10 18:42:11 +08006829 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006830}
6831
6832
6833/**
6834 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6835 * @wiphy: Pointer to wireless phy
6836 * @wdev: Pointer to wireless device
6837 * @data: Pointer to data
6838 * @data_len: Data length
6839 *
6840 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6841 * to process p2p listen offload start vendor command.
6842 *
6843 * Return: 0 on success, negative errno on failure
6844 */
6845static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6846 struct wireless_dev *wdev,
6847 const void *data,
6848 int data_len)
6849{
6850 int ret = 0;
6851
6852 cds_ssr_protect(__func__);
6853 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6854 data, data_len);
6855 cds_ssr_unprotect(__func__);
6856
6857 return ret;
6858}
6859
6860/**
6861 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6862 * @wiphy: Pointer to wireless phy
6863 * @wdev: Pointer to wireless device
6864 * @data: Pointer to data
6865 * @data_len: Data length
6866 *
6867 * This function is to process the p2p listen offload stop vendor
6868 * command. It invokes WMA API to send command to firmware.
6869 *
6870 * Return: 0 on success, negative errno on failure
6871 */
6872static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6873 struct wireless_dev *wdev,
6874 const void *data,
6875 int data_len)
6876{
Peng Xu8fdaa492016-06-22 10:20:47 -07006877 hdd_adapter_t *adapter;
6878 struct net_device *dev = wdev->netdev;
6879
6880 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6881 hdd_err("Command not allowed in FTM mode");
6882 return -EPERM;
6883 }
6884
6885 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6886 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6887 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6888 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6889 hdd_err("Invalid device mode");
6890 return -EINVAL;
6891 }
6892
Wu Gao9a704f42017-03-10 18:42:11 +08006893 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006894}
6895
6896/**
6897 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6898 * @wiphy: Pointer to wireless phy
6899 * @wdev: Pointer to wireless device
6900 * @data: Pointer to data
6901 * @data_len: Data length
6902 *
6903 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6904 * to process p2p listen offload stop vendor command.
6905 *
6906 * Return: 0 on success, negative errno on failure
6907 */
6908static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6909 struct wireless_dev *wdev,
6910 const void *data,
6911 int data_len)
6912{
6913 int ret = 0;
6914
6915 cds_ssr_protect(__func__);
6916 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6917 data, data_len);
6918 cds_ssr_unprotect(__func__);
6919
6920 return ret;
6921}
6922
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306923/**
6924 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6925 * @wiphy: Pointer to wireless phy
6926 * @wdev: Pointer to wireless device
6927 * @data: Pointer to data
6928 * @data_len: Data length
6929 *
6930 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6931 * to process the conditional channel switch request.
6932 *
6933 * Return: 0 on success, negative errno on failure
6934 */
6935static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6936 struct wireless_dev *wdev,
6937 const void *data,
6938 int data_len)
6939{
6940 int ret;
6941
6942 cds_ssr_protect(__func__);
6943 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6944 data, data_len);
6945 cds_ssr_unprotect(__func__);
6946
6947 return ret;
6948}
6949
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306950/*
6951 * define short names for the global vendor params
6952 * used by __wlan_hdd_cfg80211_bpf_offload()
6953 */
6954#define BPF_INVALID \
6955 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6956#define BPF_SET_RESET \
6957 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6958#define BPF_VERSION \
6959 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6960#define BPF_FILTER_ID \
6961 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6962#define BPF_PACKET_SIZE \
6963 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6964#define BPF_CURRENT_OFFSET \
6965 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6966#define BPF_PROGRAM \
6967 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6968#define BPF_MAX \
6969 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006970
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306971static const struct nla_policy
6972wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6973 [BPF_SET_RESET] = {.type = NLA_U32},
6974 [BPF_VERSION] = {.type = NLA_U32},
6975 [BPF_FILTER_ID] = {.type = NLA_U32},
6976 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6977 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6978 [BPF_PROGRAM] = {.type = NLA_U8},
6979};
6980
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006981struct bpf_offload_priv {
6982 struct sir_bpf_get_offload bpf_get_offload;
6983};
6984
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306985/**
6986 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006987 * @context: opaque context originally passed to SME. HDD always passes
6988 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306989 * @bpf_get_offload: struct for get offload
6990 *
6991 * This function receives the response/data from the lower layer and
6992 * checks to see if the thread is still waiting then post the results to
6993 * upper layer, if the request has timed out then ignore.
6994 *
6995 * Return: None
6996 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006997static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006998 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306999{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007000 struct hdd_request *request;
7001 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307002
7003 ENTER();
7004
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007005 request = hdd_request_get(context);
7006 if (!request) {
7007 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307008 return;
7009 }
7010
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007011 priv = hdd_request_priv(request);
7012 priv->bpf_get_offload = *data;
7013 hdd_request_complete(request);
7014 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307015}
7016
7017/**
7018 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
7019 * @hdd_context: hdd_context
7020 * @bpf_get_offload: struct for get offload
7021 *
7022 * Return: 0 on success, error number otherwise.
7023 */
7024static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
7025 struct sir_bpf_get_offload *bpf_get_offload)
7026{
7027 struct sk_buff *skb;
7028 uint32_t nl_buf_len;
7029
7030 ENTER();
7031
7032 nl_buf_len = NLMSG_HDRLEN;
7033 nl_buf_len +=
7034 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
7035 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
7036
7037 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7038 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07007039 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307040 return -ENOMEM;
7041 }
7042
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007043 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307044 bpf_get_offload->bpf_version,
7045 bpf_get_offload->max_bytes_for_bpf_inst);
7046
7047 if (nla_put_u32(skb, BPF_PACKET_SIZE,
7048 bpf_get_offload->max_bytes_for_bpf_inst) ||
7049 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007050 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307051 goto nla_put_failure;
7052 }
7053
7054 cfg80211_vendor_cmd_reply(skb);
7055 EXIT();
7056 return 0;
7057
7058nla_put_failure:
7059 kfree_skb(skb);
7060 return -EINVAL;
7061}
7062
7063/**
7064 * hdd_get_bpf_offload - Get BPF offload Capabilities
7065 * @hdd_ctx: Hdd context
7066 *
7067 * Return: 0 on success, errno on failure
7068 */
7069static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
7070{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307071 QDF_STATUS status;
7072 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007073 void *cookie;
7074 struct hdd_request *request;
7075 struct bpf_offload_priv *priv;
7076 static const struct hdd_request_params params = {
7077 .priv_size = sizeof(*priv),
7078 .timeout_ms = WLAN_WAIT_TIME_BPF,
7079 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307080
7081 ENTER();
7082
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007083 request = hdd_request_alloc(&params);
7084 if (!request) {
7085 hdd_err("Unable to allocate request");
7086 return -EINVAL;
7087 }
7088 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307089
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007090 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
7091 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007092 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307093 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007094 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007095 ret = qdf_status_to_os_return(status);
7096 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307097 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007098 ret = hdd_request_wait_for_response(request);
7099 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007100 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007101 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307102 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007103 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307104 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007105 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307106 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007107 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307108
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007109cleanup:
7110 /*
7111 * either we never sent a request to SME, we sent a request to
7112 * SME and timed out, or we sent a request to SME, received a
7113 * response from SME, and posted the response to userspace.
7114 * regardless we are done with the request.
7115 */
7116 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307117 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007118
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307119 return ret;
7120}
7121
7122/**
7123 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7124 * @hdd_ctx: Hdd context
7125 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307126 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307127 *
7128 * Return: 0 on success; errno on failure
7129 */
7130static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7131 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307132 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307133{
7134 struct sir_bpf_set_offload *bpf_set_offload;
7135 QDF_STATUS status;
7136 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307137 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307138
7139 ENTER();
7140
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307141 if (adapter->device_mode == QDF_STA_MODE ||
7142 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7143 if (!hdd_conn_is_connected(
7144 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7145 hdd_err("Not in Connected state!");
7146 return -ENOTSUPP;
7147 }
7148 }
7149
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307150 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7151 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007152 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307153 return -ENOMEM;
7154 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307155
7156 /* Parse and fetch bpf packet size */
7157 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007158 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307159 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307160 goto fail;
7161 }
7162 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7163
7164 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007165 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307166 goto post_sme;
7167 }
7168
7169 /* Parse and fetch bpf program */
7170 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007171 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307172 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307173 goto fail;
7174 }
7175
7176 prog_len = nla_len(tb[BPF_PROGRAM]);
7177 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307178
7179 if (bpf_set_offload->program == NULL) {
7180 hdd_err("qdf_mem_malloc failed for bpf offload program");
7181 ret = -ENOMEM;
7182 goto fail;
7183 }
7184
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307185 bpf_set_offload->current_length = prog_len;
7186 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307187 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307188
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007189 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007190 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307191 bpf_set_offload->program, prog_len);
7192
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307193 /* Parse and fetch filter Id */
7194 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007195 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307196 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307197 goto fail;
7198 }
7199 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7200
7201 /* Parse and fetch current offset */
7202 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007203 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307204 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307205 goto fail;
7206 }
7207 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7208
7209post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007210 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 +05307211 bpf_set_offload->session_id,
7212 bpf_set_offload->version,
7213 bpf_set_offload->filter_id,
7214 bpf_set_offload->total_length,
7215 bpf_set_offload->current_length,
7216 bpf_set_offload->current_offset);
7217
7218 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7219 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007220 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307221 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307222 goto fail;
7223 }
7224 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307225
7226fail:
7227 if (bpf_set_offload->current_length)
7228 qdf_mem_free(bpf_set_offload->program);
7229 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307230 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307231}
7232
7233/**
7234 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7235 * @wiphy: wiphy structure pointer
7236 * @wdev: Wireless device structure pointer
7237 * @data: Pointer to the data received
7238 * @data_len: Length of @data
7239 *
7240 * Return: 0 on success; errno on failure
7241 */
7242static int
7243__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7244 struct wireless_dev *wdev,
7245 const void *data, int data_len)
7246{
7247 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7248 struct net_device *dev = wdev->netdev;
7249 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7250 struct nlattr *tb[BPF_MAX + 1];
7251 int ret_val, packet_filter_subcmd;
7252
7253 ENTER();
7254
7255 ret_val = wlan_hdd_validate_context(hdd_ctx);
7256 if (ret_val)
7257 return ret_val;
7258
7259 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007260 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307261 return -EINVAL;
7262 }
7263
7264 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007265 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307266 return -ENOTSUPP;
7267 }
7268
7269 if (nla_parse(tb, BPF_MAX, data, data_len,
7270 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007271 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307272 return -EINVAL;
7273 }
7274
7275 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007276 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307277 return -EINVAL;
7278 }
7279
7280 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7281
7282 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7283 return hdd_get_bpf_offload(hdd_ctx);
7284 else
7285 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307286 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307287}
7288
7289/**
7290 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7291 * @wiphy: wiphy structure pointer
7292 * @wdev: Wireless device structure pointer
7293 * @data: Pointer to the data received
7294 * @data_len: Length of @data
7295 *
7296 * Return: 0 on success; errno on failure
7297 */
7298
7299static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7300 struct wireless_dev *wdev,
7301 const void *data, int data_len)
7302{
7303 int ret;
7304
7305 cds_ssr_protect(__func__);
7306 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7307 cds_ssr_unprotect(__func__);
7308
7309 return ret;
7310}
7311
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307312/**
7313 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7314 * @pre_cac_adapter: AP adapter used for pre cac
7315 * @status: Status (true or false)
7316 * @handle: Global handle
7317 *
7318 * Sets the status of pre cac i.e., whether the pre cac is active or not
7319 *
7320 * Return: Zero on success, non-zero on failure
7321 */
7322static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7323 bool status, tHalHandle handle)
7324{
7325 QDF_STATUS ret;
7326
7327 ret = wlan_sap_set_pre_cac_status(
7328 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7329 if (QDF_IS_STATUS_ERROR(ret))
7330 return -EINVAL;
7331
7332 return 0;
7333}
7334
7335/**
7336 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7337 * @ap_adapter: AP adapter
7338 * @chan_before_pre_cac: Channel
7339 *
7340 * Saves the channel which the AP was beaconing on before moving to the pre
7341 * cac channel. If radar is detected on the pre cac channel, this saved
7342 * channel will be used for AP operations.
7343 *
7344 * Return: Zero on success, non-zero on failure
7345 */
7346static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7347 uint8_t chan_before_pre_cac)
7348{
7349 QDF_STATUS ret;
7350
7351 ret = wlan_sap_set_chan_before_pre_cac(
7352 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7353 if (QDF_IS_STATUS_ERROR(ret))
7354 return -EINVAL;
7355
7356 return 0;
7357}
7358
7359/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307360 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7361 * are in nol list from provided channel list
7362 * @adapter: AP adapter
7363 * @channel_count: channel count
7364 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307365 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307366 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307367 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307368static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7369 uint32_t *channel_count,
7370 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307371{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307372 uint8_t i, j;
7373 uint32_t nol_len = 0;
7374 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7375 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7376 uint32_t chan_count;
7377 bool found;
7378 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307379
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307380 if (!hdd_ctx) {
7381 hdd_err("hdd ctx not found");
7382 *channel_count = 0;
7383 return;
7384 }
7385
7386 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7387 hdd_err("invalid channel count %d", *channel_count);
7388 return;
7389 }
7390
7391 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7392 if (nol_len == 0)
7393 return;
7394
7395 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7396 chan_count = *channel_count;
7397 qdf_mem_zero(channel_list, chan_count);
7398 *channel_count = 0;
7399
7400 for (i = 0 ; i < chan_count; i++) {
7401 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7402 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7403 continue;
7404 found = false;
7405 for (j = 0; j < nol_len; j++) {
7406 if (tmp_chan_list[i] == nol[j]) {
7407 found = true;
7408 hdd_notice("skipped channel %d due to nol",
7409 nol[j]);
7410 break;
7411 }
7412 }
7413 if (!found) {
7414 channel_list[*channel_count] = tmp_chan_list[i];
7415 *channel_count = *channel_count + 1;
7416 }
7417 }
7418}
7419
7420int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7421 uint32_t *channel_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307422 uint8_t *channel_list,
7423 eCsrBand band)
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307424{
7425 tsap_Config_t *sap_config;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307426 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7427 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7428 uint32_t chan_count;
7429 uint8_t i;
7430 QDF_STATUS status;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307431
7432 sap_config = &adapter->sessionCtx.ap.sapConfig;
7433
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307434 status =
7435 policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7436 tmp_chan_list,
7437 &chan_count);
7438 if (QDF_IS_STATUS_ERROR(status)) {
7439 hdd_err("Failed to get channel list");
7440 return -EINVAL;
7441 }
7442 for (i = 0; i < chan_count; i++) {
7443 if (*channel_count < QDF_MAX_NUM_CHAN) {
7444 if ((eCSR_BAND_24 == band) &&
7445 (WLAN_REG_IS_24GHZ_CH(tmp_chan_list[i]))) {
7446 channel_list[*channel_count] = tmp_chan_list[i];
7447 *channel_count += 1;
7448 } else if ((eCSR_BAND_5G == band) &&
7449 (WLAN_REG_IS_5GHZ_CH(tmp_chan_list[i]))) {
7450 channel_list[*channel_count] = tmp_chan_list[i];
7451 *channel_count += 1;
7452 }
7453 } else {
7454 break;
7455 }
7456 }
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307457 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307458 if (*channel_count == 0) {
7459 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307460 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307461 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307462
7463 return 0;
7464}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307465
7466/**
7467 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7468 * @hdd_ctx: HDD context
7469 * @ap_adapter: AP adapter
7470 * @channel: Channel requested by userspace
7471 * @pre_cac_chan: Pointer to the pre CAC channel
7472 *
7473 * Validates the channel provided by userspace. If user provided channel 0,
7474 * a valid outdoor channel must be selected from the regulatory channel.
7475 *
7476 * Return: Zero on success and non zero value on error
7477 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007478static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7479 hdd_adapter_t *ap_adapter,
7480 uint8_t channel,
7481 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307482{
7483 uint32_t i, j;
7484 QDF_STATUS status;
7485 int ret;
7486 uint8_t nol[QDF_MAX_NUM_CHAN];
7487 uint32_t nol_len = 0, weight_len = 0;
7488 bool found;
7489 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7490 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7491 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7492
7493 if (0 == channel) {
7494 /* Channel is not obtained from PCL because PCL may not have
7495 * the entire channel list. For example: if SAP is up on
7496 * channel 6 and PCL is queried for the next SAP interface,
7497 * if SCC is preferred, the PCL will contain only the channel
7498 * 6. But, we are in need of a DFS channel. So, going with the
7499 * first channel from the valid channel list.
7500 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007501 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7502 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307503 if (QDF_IS_STATUS_ERROR(status)) {
7504 hdd_err("Failed to get channel list");
7505 return -EINVAL;
7506 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007507 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307508 pcl_weights, weight_len);
7509 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7510 for (i = 0; i < len; i++) {
7511 found = false;
7512 for (j = 0; j < nol_len; j++) {
7513 if (channel_list[i] == nol[j]) {
7514 found = true;
7515 break;
7516 }
7517 }
7518 if (found)
7519 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007520 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7521 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307522 *pre_cac_chan = channel_list[i];
7523 break;
7524 }
7525 }
7526 if (*pre_cac_chan == 0) {
7527 hdd_err("unable to find outdoor channel");
7528 return -EINVAL;
7529 }
7530 } else {
7531 /* Only when driver selects a channel, check is done for
7532 * unnsafe and NOL channels. When user provides a fixed channel
7533 * the user is expected to take care of this.
7534 */
7535 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007536 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307537 hdd_err("Invalid channel for pre cac:%d", channel);
7538 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307539 }
Jeff Johnson68755312017-02-10 11:46:55 -08007540
7541 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307542 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007543 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307544 return 0;
7545}
7546
7547/**
7548 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7549 * @channel: Channel option provided by userspace
7550 *
7551 * Sets the driver to the required hardware mode and start an adapater for
7552 * pre CAC which will mimic an AP.
7553 *
7554 * Return: Zero on success, non-zero value on error
7555 */
7556int wlan_hdd_request_pre_cac(uint8_t channel)
7557{
Krunal Sonib37bb352016-12-20 14:12:21 -08007558 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307559 hdd_context_t *hdd_ctx;
7560 int ret;
7561 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7562 hdd_ap_ctx_t *hdd_ap_ctx;
7563 QDF_STATUS status;
7564 struct wiphy *wiphy;
7565 struct net_device *dev;
7566 struct cfg80211_chan_def chandef;
7567 enum nl80211_channel_type channel_type;
7568 uint32_t freq;
7569 struct ieee80211_channel *chan;
7570 tHalHandle handle;
7571 bool val;
7572
7573 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7574 if (0 != wlan_hdd_validate_context(hdd_ctx))
7575 return -EINVAL;
7576
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007577 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307578 hdd_err("pre cac not allowed in concurrency");
7579 return -EINVAL;
7580 }
7581
7582 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7583 if (!ap_adapter) {
7584 hdd_err("unable to get SAP adapter");
7585 return -EINVAL;
7586 }
7587
7588 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7589 if (!handle) {
7590 hdd_err("Invalid handle");
7591 return -EINVAL;
7592 }
7593
7594 val = wlan_sap_is_pre_cac_active(handle);
7595 if (val) {
7596 hdd_err("pre cac is already in progress");
7597 return -EINVAL;
7598 }
7599
7600 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7601 if (!hdd_ap_ctx) {
7602 hdd_err("SAP context is NULL");
7603 return -EINVAL;
7604 }
7605
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007606 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7607 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307608 hdd_err("SAP is already on DFS channel:%d",
7609 hdd_ap_ctx->operatingChannel);
7610 return -EINVAL;
7611 }
7612
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007613 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307614 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7615 hdd_ap_ctx->operatingChannel);
7616 return -EINVAL;
7617 }
7618
Krunal Sonib37bb352016-12-20 14:12:21 -08007619 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7620 if (!mac_addr) {
7621 hdd_err("can't add virtual intf: Not getting valid mac addr");
7622 return -EINVAL;
7623 }
7624
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007625 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307626
7627 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7628 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007629 if (ret != 0) {
7630 hdd_err("can't validate pre-cac channel");
7631 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307632 }
7633
7634 hdd_debug("starting pre cac SAP adapter");
7635
7636 /* Starting a SAP adapter:
7637 * Instead of opening an adapter, we could just do a SME open session
7638 * for AP type. But, start BSS would still need an adapter.
7639 * So, this option is not taken.
7640 *
7641 * hdd open adapter is going to register this precac interface with
7642 * user space. This interface though exposed to user space will be in
7643 * DOWN state. Consideration was done to avoid this registration to the
7644 * user space. But, as part of SAP operations multiple events are sent
7645 * to user space. Some of these events received from unregistered
7646 * interface was causing crashes. So, retaining the registration.
7647 *
7648 * So, this interface would remain registered and will remain in DOWN
7649 * state for the CAC duration. We will add notes in the feature
7650 * announcement to not use this temporary interface for any activity
7651 * from user space.
7652 */
7653 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007654 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307655 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307656 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007657 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307658 }
7659
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307660 /*
7661 * This interface is internally created by the driver. So, no interface
7662 * up comes for this interface from user space and hence starting
7663 * the adapter internally.
7664 */
7665 if (hdd_start_adapter(pre_cac_adapter)) {
7666 hdd_err("error starting the pre cac adapter");
7667 goto close_pre_cac_adapter;
7668 }
7669
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307670 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7671
7672 wiphy = hdd_ctx->wiphy;
7673 dev = pre_cac_adapter->dev;
7674
7675 /* Since this is only a dummy interface lets us use the IEs from the
7676 * other active SAP interface. In regular scenarios, these IEs would
7677 * come from the user space entity
7678 */
7679 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7680 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7681 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7682 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307683 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307684 }
7685 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7686 ap_adapter->sessionCtx.ap.beacon,
7687 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7688 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7689 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7690 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7691 ap_adapter->sessionCtx.ap.sapConfig.authType;
7692
7693 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7694 * to operate on the same bandwidth as that of the 2.4GHz operations.
7695 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7696 */
7697 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7698 case CH_WIDTH_20MHZ:
7699 channel_type = NL80211_CHAN_HT20;
7700 break;
7701 case CH_WIDTH_40MHZ:
7702 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7703 ap_adapter->sessionCtx.ap.sapConfig.channel)
7704 channel_type = NL80211_CHAN_HT40PLUS;
7705 else
7706 channel_type = NL80211_CHAN_HT40MINUS;
7707 break;
7708 default:
7709 channel_type = NL80211_CHAN_NO_HT;
7710 break;
7711 }
7712
7713 freq = cds_chan_to_freq(pre_cac_chan);
7714 chan = __ieee80211_get_channel(wiphy, freq);
7715 if (!chan) {
7716 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307717 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307718 }
7719
7720 cfg80211_chandef_create(&chandef, chan, channel_type);
7721
7722 hdd_debug("orig width:%d channel_type:%d freq:%d",
7723 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7724 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007725 /*
7726 * Doing update after opening and starting pre-cac adapter will make
7727 * sure that driver won't do hardware mode change if there are any
7728 * initial hick-ups or issues in pre-cac adapter's configuration.
7729 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7730 * connection update should result in DBS mode
7731 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007732 status = policy_mgr_update_and_wait_for_connection_update(
7733 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007734 ap_adapter->sessionId,
7735 pre_cac_chan,
7736 SIR_UPDATE_REASON_PRE_CAC);
7737 if (QDF_IS_STATUS_ERROR(status)) {
7738 hdd_err("error in moving to DBS mode");
7739 goto stop_close_pre_cac_adapter;
7740 }
7741
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307742
7743 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7744 if (0 != ret) {
7745 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307746 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307747 }
7748
7749 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7750 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007751 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307752 if (QDF_IS_STATUS_ERROR(status)) {
7753 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307754 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307755 }
7756
7757 /*
7758 * The pre cac status is set here. But, it would not be reset explicitly
7759 * anywhere, since after the pre cac success/failure, the pre cac
7760 * adapter itself would be removed.
7761 */
7762 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7763 if (0 != ret) {
7764 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307765 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307766 }
7767
7768 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7769 hdd_ap_ctx->operatingChannel);
7770 if (0 != ret) {
7771 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307772 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307773 }
7774
7775 ap_adapter->pre_cac_chan = pre_cac_chan;
7776
7777 return 0;
7778
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307779stop_close_pre_cac_adapter:
7780 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307781 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7782 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307783close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307784 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007785release_intf_addr_and_return_failure:
7786 /*
7787 * Release the interface address as the adapter
7788 * failed to start, if you don't release then next
7789 * adapter which is trying to come wouldn't get valid
7790 * mac address. Remember we have limited pool of mac addresses
7791 */
7792 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307793 return -EINVAL;
7794}
7795
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307796static const struct nla_policy
7797wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7798 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7799};
7800
Agrawal Ashish65634612016-08-18 13:24:32 +05307801static const struct nla_policy
7802wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7803 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7804 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7805};
7806
7807/**
7808 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7809 * @wiphy: Pointer to wireless phy
7810 * @wdev: Pointer to wireless device
7811 * @data: Pointer to data
7812 * @data_len: Length of @data
7813 *
7814 * This function parses the incoming NL vendor command data attributes and
7815 * updates the SAP context about channel_hint and DFS mode.
7816 * If channel_hint is set, SAP will choose that channel
7817 * as operating channel.
7818 *
7819 * If DFS mode is enabled, driver will include DFS channels
7820 * in ACS else driver will skip DFS channels.
7821 *
7822 * Return: 0 on success, negative errno on failure
7823 */
7824static int
7825__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7826 struct wireless_dev *wdev,
7827 const void *data, int data_len)
7828{
7829 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7830 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7831 int ret;
7832 struct acs_dfs_policy *acs_policy;
7833 int mode = DFS_MODE_NONE;
7834 int channel_hint = 0;
7835
7836 ENTER_DEV(wdev->netdev);
7837
7838 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7839 hdd_err("Command not allowed in FTM mode");
7840 return -EINVAL;
7841 }
7842
7843 ret = wlan_hdd_validate_context(hdd_ctx);
7844 if (0 != ret)
7845 return ret;
7846
7847 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7848 data, data_len,
7849 wlan_hdd_set_acs_dfs_config_policy)) {
7850 hdd_err("invalid attr");
7851 return -EINVAL;
7852 }
7853
7854 acs_policy = &hdd_ctx->acs_policy;
7855 /*
7856 * SCM sends this attribute to restrict SAP from choosing
7857 * DFS channels from ACS.
7858 */
7859 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7860 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7861
7862 if (!IS_DFS_MODE_VALID(mode)) {
7863 hdd_err("attr acs dfs mode is not valid");
7864 return -EINVAL;
7865 }
7866 acs_policy->acs_dfs_mode = mode;
7867
7868 /*
7869 * SCM sends this attribute to provide an active channel,
7870 * to skip redundant ACS between drivers, and save driver start up time
7871 */
7872 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7873 channel_hint = nla_get_u8(
7874 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7875
7876 if (!IS_CHANNEL_VALID(channel_hint)) {
7877 hdd_err("acs channel is not valid");
7878 return -EINVAL;
7879 }
7880 acs_policy->acs_channel = channel_hint;
7881
7882 return 0;
7883}
7884
7885/**
7886 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7887 * @wiphy: wiphy structure pointer
7888 * @wdev: Wireless device structure pointer
7889 * @data: Pointer to the data received
7890 * @data_len: Length of @data
7891 *
7892 * This function parses the incoming NL vendor command data attributes and
7893 * updates the SAP context about channel_hint and DFS mode.
7894 *
7895 * Return: 0 on success; errno on failure
7896 */
7897static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7898 struct wireless_dev *wdev,
7899 const void *data, int data_len)
7900{
7901 int ret;
7902
7903 cds_ssr_protect(__func__);
7904 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7905 cds_ssr_unprotect(__func__);
7906
7907 return ret;
7908}
7909
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307910/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307911 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7912 * @mode : cfg80211 dfs mode
7913 *
7914 * Return: return csr sta roam dfs mode else return NONE
7915 */
7916static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7917 enum dfs_mode mode)
7918{
7919 switch (mode) {
7920 case DFS_MODE_ENABLE:
7921 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7922 break;
7923 case DFS_MODE_DISABLE:
7924 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7925 break;
7926 case DFS_MODE_DEPRIORITIZE:
7927 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7928 break;
7929 default:
7930 hdd_err("STA Roam policy dfs mode is NONE");
7931 return CSR_STA_ROAM_POLICY_NONE;
7932 }
7933}
7934
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307935/*
7936 * hdd_get_sap_operating_band: Get current operating channel
7937 * for sap.
7938 * @hdd_ctx: hdd context
7939 *
7940 * Return : Corresponding band for SAP operating channel
7941 */
7942uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7943{
7944 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7945 QDF_STATUS status;
7946 hdd_adapter_t *adapter;
7947 uint8_t operating_channel = 0;
7948 uint8_t sap_operating_band = 0;
7949 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7950 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7951 adapter = adapter_node->pAdapter;
7952
7953 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7954 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7955 &next);
7956 adapter_node = next;
7957 continue;
7958 }
7959 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7960 if (IS_24G_CH(operating_channel))
7961 sap_operating_band = eCSR_BAND_24;
7962 else if (IS_5G_CH(operating_channel))
7963 sap_operating_band = eCSR_BAND_5G;
7964 else
7965 sap_operating_band = eCSR_BAND_ALL;
7966 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7967 &next);
bings373b99b2017-01-23 10:35:08 +08007968 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307969 }
7970 return sap_operating_band;
7971}
7972
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307973static const struct nla_policy
7974wlan_hdd_set_sta_roam_config_policy[
7975QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7976 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7977 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7978};
7979
7980/**
7981 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7982 * for station connection or roaming.
7983 * @wiphy: Pointer to wireless phy
7984 * @wdev: Pointer to wireless device
7985 * @data: Pointer to data
7986 * @data_len: Length of @data
7987 *
7988 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7989 * channels needs to be skipped in scanning or not.
7990 * If dfs_mode is disabled, driver will not scan DFS channels.
7991 * If skip_unsafe_channels is set, driver will skip unsafe channels
7992 * in Scanning.
7993 *
7994 * Return: 0 on success, negative errno on failure
7995 */
7996static int
7997__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7998 struct wireless_dev *wdev,
7999 const void *data, int data_len)
8000{
8001 struct net_device *dev = wdev->netdev;
8002 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8003 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8004 struct nlattr *tb[
8005 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
8006 int ret;
8007 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
8008 enum dfs_mode mode = DFS_MODE_NONE;
8009 bool skip_unsafe_channels = false;
8010 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308011 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308012
8013 ENTER_DEV(dev);
8014
8015 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8016 hdd_err("Command not allowed in FTM mode");
8017 return -EINVAL;
8018 }
8019
8020 ret = wlan_hdd_validate_context(hdd_ctx);
8021 if (0 != ret)
8022 return ret;
8023 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
8024 data, data_len,
8025 wlan_hdd_set_sta_roam_config_policy)) {
8026 hdd_err("invalid attr");
8027 return -EINVAL;
8028 }
8029 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
8030 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
8031 if (!IS_DFS_MODE_VALID(mode)) {
8032 hdd_err("attr sta roam dfs mode policy is not valid");
8033 return -EINVAL;
8034 }
8035
8036 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
8037
8038 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
8039 skip_unsafe_channels = nla_get_u8(
8040 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308041 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308042 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308043 skip_unsafe_channels, adapter->sessionId,
8044 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308045
8046 if (!QDF_IS_STATUS_SUCCESS(status)) {
8047 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
8048 return -EINVAL;
8049 }
8050 return 0;
8051}
8052
8053/**
8054 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
8055 * connection and roaming for station.
8056 * @wiphy: wiphy structure pointer
8057 * @wdev: Wireless device structure pointer
8058 * @data: Pointer to the data received
8059 * @data_len: Length of @data
8060 *
8061 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8062 * channels needs to be skipped in scanning or not.
8063 * If dfs_mode is disabled, driver will not scan DFS channels.
8064 * If skip_unsafe_channels is set, driver will skip unsafe channels
8065 * in Scanning.
8066 * Return: 0 on success; errno on failure
8067 */
8068static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8069 struct wireless_dev *wdev,
8070 const void *data, int data_len)
8071{
8072 int ret;
8073
8074 cds_ssr_protect(__func__);
8075 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
8076 cds_ssr_unprotect(__func__);
8077
8078 return ret;
8079}
8080
Agrawal Ashish467dde42016-09-08 18:44:22 +05308081#ifdef FEATURE_WLAN_CH_AVOID
8082/**
8083 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8084 * is on unsafe channel.
8085 * @wiphy: wiphy structure pointer
8086 * @wdev: Wireless device structure pointer
8087 * @data: Pointer to the data received
8088 * @data_len: Length of @data
8089 *
8090 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8091 * on any of unsafe channels.
8092 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8093 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8094 *
8095 * Return: 0 on success; errno on failure
8096 */
8097static int
8098__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8099 struct wireless_dev *wdev,
8100 const void *data, int data_len)
8101{
8102 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8103 int ret;
8104 uint16_t unsafe_channel_count;
8105 int unsafe_channel_index;
8106 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8107
8108 ENTER_DEV(wdev->netdev);
8109
8110 if (!qdf_ctx) {
8111 cds_err("qdf_ctx is NULL");
8112 return -EINVAL;
8113 }
8114
8115 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8116 hdd_err("Command not allowed in FTM mode");
8117 return -EINVAL;
8118 }
8119
8120 ret = wlan_hdd_validate_context(hdd_ctx);
8121 if (0 != ret)
8122 return ret;
8123 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8124 &(hdd_ctx->unsafe_channel_count),
8125 sizeof(hdd_ctx->unsafe_channel_list));
8126
8127 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8128 (uint16_t)NUM_CHANNELS);
8129 for (unsafe_channel_index = 0;
8130 unsafe_channel_index < unsafe_channel_count;
8131 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008132 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308133 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8134 }
8135 hdd_unsafe_channel_restart_sap(hdd_ctx);
8136 return 0;
8137}
8138
8139/**
8140 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8141 * is on unsafe channel.
8142 * @wiphy: wiphy structure pointer
8143 * @wdev: Wireless device structure pointer
8144 * @data: Pointer to the data received
8145 * @data_len: Length of @data
8146 *
8147 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8148 * on any of unsafe channels.
8149 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8150 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8151 *
8152 * Return: 0 on success; errno on failure
8153 */
8154static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8155 struct wireless_dev *wdev,
8156 const void *data, int data_len)
8157{
8158 int ret;
8159
8160 cds_ssr_protect(__func__);
8161 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8162 cds_ssr_unprotect(__func__);
8163
8164 return ret;
8165}
8166
8167#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308168/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308169 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8170 * SAP is on unsafe channel.
8171 * @wiphy: wiphy structure pointer
8172 * @wdev: Wireless device structure pointer
8173 * @data: Pointer to the data received
8174 * @data_len: Length of @data
8175 *
8176 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8177 * driver.
8178 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8179 * will initiate restart of sap.
8180 *
8181 * Return: 0 on success; errno on failure
8182 */
8183static int
8184__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8185 struct wireless_dev *wdev,
8186 const void *data, int data_len)
8187{
8188 struct net_device *ndev = wdev->netdev;
8189 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8190 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8191 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8192 uint8_t config_channel = 0;
8193 hdd_ap_ctx_t *ap_ctx;
8194 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308195 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308196
8197 ENTER();
8198
8199 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008200 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308201 return -EINVAL;
8202 }
8203
8204 ret = wlan_hdd_validate_context(hdd_ctx);
8205 if (0 != ret)
8206 return -EINVAL;
8207
8208 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8209 data, data_len,
8210 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008211 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308212 return -EINVAL;
8213 }
8214
8215 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8216 if (!test_bit(SOFTAP_BSS_STARTED,
8217 &hostapd_adapter->event_flags)) {
8218 hdd_err("SAP is not started yet. Restart sap will be invalid");
8219 return -EINVAL;
8220 }
8221
8222 config_channel =
8223 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8224
8225 if (!((IS_24G_CH(config_channel)) ||
8226 (IS_5G_CH(config_channel)))) {
8227 hdd_err("Channel %d is not valid to restart SAP",
8228 config_channel);
8229 return -ENOTSUPP;
8230 }
8231
8232 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8233 ap_ctx->sapConfig.channel = config_channel;
8234 ap_ctx->sapConfig.ch_params.ch_width =
8235 ap_ctx->sapConfig.ch_width_orig;
8236
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008237 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8238 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308239 ap_ctx->sapConfig.sec_ch,
8240 &ap_ctx->sapConfig.ch_params);
8241
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008242 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308243 }
8244
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308245 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8246 uint32_t freq_len, i;
8247 uint32_t *freq;
8248 uint8_t chans[QDF_MAX_NUM_CHAN];
8249
8250 hdd_debug("setting mandatory freq/chan list");
8251
8252 freq_len = nla_len(
8253 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8254 sizeof(uint32_t);
8255
8256 if (freq_len > QDF_MAX_NUM_CHAN) {
8257 hdd_err("insufficient space to hold channels");
8258 return -ENOMEM;
8259 }
8260
8261 freq = nla_data(
8262 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8263
8264 hdd_debug("freq_len=%d", freq_len);
8265
8266 for (i = 0; i < freq_len; i++) {
8267 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8268 hdd_debug("freq[%d]=%d", i, freq[i]);
8269 }
8270
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008271 status = policy_mgr_set_sap_mandatory_channels(
8272 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308273 if (QDF_IS_STATUS_ERROR(status))
8274 return -EINVAL;
8275 }
8276
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308277 return 0;
8278}
8279
8280/**
8281 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8282 * @wiphy: wiphy structure pointer
8283 * @wdev: Wireless device structure pointer
8284 * @data: Pointer to the data received
8285 * @data_len: Length of @data
8286 *
8287 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8288 * driver.
8289 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8290 * will initiate restart of sap.
8291 *
8292 * Return: 0 on success; errno on failure
8293 */
8294static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8295 struct wireless_dev *wdev,
8296 const void *data, int data_len)
8297{
8298 int ret;
8299
8300 cds_ssr_protect(__func__);
8301 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8302 wdev, data, data_len);
8303 cds_ssr_unprotect(__func__);
8304
8305 return ret;
8306}
8307
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308308#undef BPF_INVALID
8309#undef BPF_SET_RESET
8310#undef BPF_VERSION
8311#undef BPF_ID
8312#undef BPF_PACKET_SIZE
8313#undef BPF_CURRENT_OFFSET
8314#undef BPF_PROGRAM
8315#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308316
8317/**
8318 * define short names for the global vendor params
8319 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8320 */
8321#define PARAM_TOTAL_CMD_EVENT_WAKE \
8322 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8323#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8324 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8325#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8326 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8327#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8328 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8329#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8330 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8331#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8332 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8333#define PARAM_TOTAL_RX_DATA_WAKE \
8334 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8335#define PARAM_RX_UNICAST_CNT \
8336 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8337#define PARAM_RX_MULTICAST_CNT \
8338 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8339#define PARAM_RX_BROADCAST_CNT \
8340 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8341#define PARAM_ICMP_PKT \
8342 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8343#define PARAM_ICMP6_PKT \
8344 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8345#define PARAM_ICMP6_RA \
8346 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8347#define PARAM_ICMP6_NA \
8348 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8349#define PARAM_ICMP6_NS \
8350 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8351#define PARAM_ICMP4_RX_MULTICAST_CNT \
8352 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8353#define PARAM_ICMP6_RX_MULTICAST_CNT \
8354 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8355#define PARAM_OTHER_RX_MULTICAST_CNT \
8356 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308357#define PARAM_RSSI_BREACH_CNT \
8358 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8359#define PARAM_LOW_RSSI_CNT \
8360 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8361#define PARAM_GSCAN_CNT \
8362 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8363#define PARAM_PNO_COMPLETE_CNT \
8364 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8365#define PARAM_PNO_MATCH_CNT \
8366 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8367
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308368
8369
8370/**
8371 * hdd_send_wakelock_stats() - API to send wakelock stats
8372 * @ctx: context to be passed to callback
8373 * @data: data passed to callback
8374 *
8375 * This function is used to send wake lock stats to HAL layer
8376 *
8377 * Return: 0 on success, error number otherwise.
8378 */
8379static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8380 const struct sir_wake_lock_stats *data)
8381{
8382 struct sk_buff *skb;
8383 uint32_t nl_buf_len;
8384 uint32_t total_rx_data_wake, rx_multicast_cnt;
8385 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308386 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308387
8388 ENTER();
8389
8390 nl_buf_len = NLMSG_HDRLEN;
8391 nl_buf_len +=
8392 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8393 (NLMSG_HDRLEN + sizeof(uint32_t));
8394
8395 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8396
8397 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008398 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308399 return -ENOMEM;
8400 }
8401
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008402 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308403 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008404 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308405 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008406 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308407 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008408 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308409 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008410 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308411 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008412 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308413 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008414 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308415 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008416 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8417 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308418 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008419 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308420 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008421 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308422 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008423 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308424 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008425 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308426 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008427 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308428 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308429
8430 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308431 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308432
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308433 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308434 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308435
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308436 rx_multicast_cnt =
8437 data->wow_ipv4_mcast_wake_up_count +
8438 ipv6_rx_multicast_addr_cnt;
8439
8440 total_rx_data_wake =
8441 data->wow_ucast_wake_up_count +
8442 data->wow_bcast_wake_up_count +
8443 rx_multicast_cnt;
8444
8445 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8446 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8447 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8448 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8449 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8450 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8451 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8452 total_rx_data_wake) ||
8453 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8454 data->wow_ucast_wake_up_count) ||
8455 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8456 rx_multicast_cnt) ||
8457 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8458 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308459 nla_put_u32(skb, PARAM_ICMP_PKT,
8460 data->wow_icmpv4_count) ||
8461 nla_put_u32(skb, PARAM_ICMP6_PKT,
8462 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308463 nla_put_u32(skb, PARAM_ICMP6_RA,
8464 data->wow_ipv6_mcast_ra_stats) ||
8465 nla_put_u32(skb, PARAM_ICMP6_NA,
8466 data->wow_ipv6_mcast_na_stats) ||
8467 nla_put_u32(skb, PARAM_ICMP6_NS,
8468 data->wow_ipv6_mcast_ns_stats) ||
8469 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8470 data->wow_ipv4_mcast_wake_up_count) ||
8471 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8472 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308473 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8474 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8475 data->wow_rssi_breach_wake_up_count) ||
8476 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8477 data->wow_low_rssi_wake_up_count) ||
8478 nla_put_u32(skb, PARAM_GSCAN_CNT,
8479 data->wow_gscan_wake_up_count) ||
8480 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8481 data->wow_pno_complete_wake_up_count) ||
8482 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8483 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008484 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308485 goto nla_put_failure;
8486 }
8487
8488 cfg80211_vendor_cmd_reply(skb);
8489
8490 EXIT();
8491 return 0;
8492
8493nla_put_failure:
8494 kfree_skb(skb);
8495 return -EINVAL;
8496}
8497
8498/**
8499 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8500 * @wiphy: wiphy pointer
8501 * @wdev: pointer to struct wireless_dev
8502 * @data: pointer to incoming NL vendor data
8503 * @data_len: length of @data
8504 *
8505 * This function parses the incoming NL vendor command data attributes and
8506 * invokes the SME Api and blocks on a completion variable.
8507 * WMA copies required data and invokes callback
8508 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8509 *
8510 * Return: 0 on success; error number otherwise.
8511 */
8512static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8513 struct wireless_dev *wdev,
8514 const void *data,
8515 int data_len)
8516{
8517 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8518 int status, ret;
8519 struct sir_wake_lock_stats wake_lock_stats;
8520 QDF_STATUS qdf_status;
8521
8522 ENTER();
8523
8524 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008525 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308526 return -EINVAL;
8527 }
8528
8529 status = wlan_hdd_validate_context(hdd_ctx);
8530 if (0 != status)
8531 return -EINVAL;
8532
8533 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8534 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008535 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308536 return -EINVAL;
8537 }
8538
8539 ret = hdd_send_wakelock_stats(hdd_ctx,
8540 &wake_lock_stats);
8541 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008542 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308543
8544 EXIT();
8545 return ret;
8546}
8547
8548/**
8549 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8550 * @wiphy: wiphy pointer
8551 * @wdev: pointer to struct wireless_dev
8552 * @data: pointer to incoming NL vendor data
8553 * @data_len: length of @data
8554 *
8555 * This function parses the incoming NL vendor command data attributes and
8556 * invokes the SME Api and blocks on a completion variable.
8557 * WMA copies required data and invokes callback
8558 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8559 *
8560 * Return: 0 on success; error number otherwise.
8561 */
8562static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8563 struct wireless_dev *wdev,
8564 const void *data, int data_len)
8565{
8566 int ret;
8567
8568 cds_ssr_protect(__func__);
8569 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8570 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008571 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308572
8573 return ret;
8574}
8575
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308576/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308577 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8578 * @wiphy: wiphy structure pointer
8579 * @wdev: Wireless device structure pointer
8580 * @data: Pointer to the data received
8581 * @data_len: Length of @data
8582 *
8583 * This function reads wmi max bus size and fill in the skb with
8584 * NL attributes and send up the NL event.
8585 * Return: 0 on success; errno on failure
8586 */
8587static int
8588__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8589 struct wireless_dev *wdev,
8590 const void *data, int data_len)
8591{
8592 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8593 int ret_val;
8594 struct sk_buff *skb;
8595 uint32_t nl_buf_len;
8596
8597 ENTER();
8598
8599 ret_val = wlan_hdd_validate_context(hdd_ctx);
8600 if (ret_val)
8601 return ret_val;
8602
8603 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8604 hdd_err("Command not allowed in FTM mode");
8605 return -EINVAL;
8606 }
8607
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008608 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308609
8610 nl_buf_len = NLMSG_HDRLEN;
8611 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8612
8613 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8614 if (!skb) {
8615 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8616 return -ENOMEM;
8617 }
8618
8619 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8620 hdd_ctx->wmi_max_len)) {
8621 hdd_err("nla put failure");
8622 goto nla_put_failure;
8623 }
8624
8625 cfg80211_vendor_cmd_reply(skb);
8626
8627 EXIT();
8628
8629 return 0;
8630
8631nla_put_failure:
8632 kfree_skb(skb);
8633 return -EINVAL;
8634}
8635
8636/**
8637 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8638 * @wiphy: wiphy structure pointer
8639 * @wdev: Wireless device structure pointer
8640 * @data: Pointer to the data received
8641 * @data_len: Length of @data
8642 *
8643 * Return: 0 on success; errno on failure
8644 */
8645static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8646 struct wireless_dev *wdev,
8647 const void *data, int data_len)
8648{
8649 int ret;
8650
8651 cds_ssr_protect(__func__);
8652 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8653 cds_ssr_unprotect(__func__);
8654
8655 return ret;
8656}
8657
8658/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308659 *__wlan_hdd_cfg80211_setband() - set band
8660 * @wiphy: Pointer to wireless phy
8661 * @wdev: Pointer to wireless device
8662 * @data: Pointer to data
8663 * @data_len: Length of @data
8664 *
8665 * Return: 0 on success, negative errno on failure
8666 */
8667static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8668 struct wireless_dev *wdev,
8669 const void *data, int data_len)
8670{
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308671 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008672 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308673 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8674 int ret;
8675 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8676 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8677
8678 ENTER();
8679
8680 ret = wlan_hdd_validate_context(hdd_ctx);
8681 if (ret)
8682 return ret;
8683
8684 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8685 hdd_err(FL("Invalid ATTR"));
8686 return -EINVAL;
8687 }
8688
8689 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8690 hdd_err(FL("attr SETBAND_VALUE failed"));
8691 return -EINVAL;
8692 }
8693
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07008694 ret = hdd_reg_set_band(dev,
8695 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308696
8697 EXIT();
8698 return ret;
8699}
8700
8701/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308702 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8703 * @adapter: hdd adapter
8704 * @channel: channel number
8705 *
8706 * return: QDF status based on success or failure
8707 */
8708static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8709 int channel, int chan_bw)
8710{
8711 if (QDF_STATUS_SUCCESS !=
8712 wlan_hdd_validate_operation_channel(adapter, channel))
8713 return QDF_STATUS_E_FAILURE;
8714 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8715 channel,
8716 PHY_SINGLE_CHANNEL_CENTERED))) {
8717 hdd_notice("channel %d is in nol", channel);
8718 return -EINVAL;
8719 }
8720
8721 if ((wlansap_is_channel_leaking_in_nol(
8722 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8723 channel, chan_bw))) {
8724 hdd_notice("channel %d is leaking in nol", channel);
8725 return -EINVAL;
8726 }
8727
8728 return 0;
8729
8730}
8731
Kapil Gupta8878ad92017-02-13 11:56:04 +05308732static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8733 tsap_Config_t *sap_config,
8734 struct hdd_vendor_chan_info *channel_list)
8735{
8736 sap_config->channel = channel_list->pri_ch;
8737
8738 sap_config->ch_params.center_freq_seg0 =
8739 channel_list->vht_seg0_center_ch;
8740 sap_config->ch_params.center_freq_seg1 =
8741 channel_list->vht_seg1_center_ch;
8742
8743 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8744 sap_config->ch_params.ch_width = channel_list->chan_width;
8745 if (sap_config->channel >= 36)
8746 sap_config->ch_width_orig =
8747 hdd_ctx->config->vhtChannelWidth;
8748 else
8749 sap_config->ch_width_orig =
8750 hdd_ctx->config->nChannelBondingMode24GHz ?
8751 eHT_CHANNEL_WIDTH_40MHZ :
8752 eHT_CHANNEL_WIDTH_20MHZ;
8753
8754 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8755 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8756 sap_config->acs_cfg.vht_seg0_center_ch =
8757 channel_list->vht_seg0_center_ch;
8758 sap_config->acs_cfg.vht_seg1_center_ch =
8759 channel_list->vht_seg1_center_ch;
8760 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8761}
8762
8763static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8764 uint8_t channel_cnt,
8765 struct hdd_vendor_chan_info *channel_list)
8766{
8767 tsap_Config_t *sap_config;
8768 hdd_ap_ctx_t *hdd_ap_ctx;
8769 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8770 QDF_STATUS status = QDF_STATUS_SUCCESS;
8771
8772 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8773 sap_config = &adapter->sessionCtx.ap.sapConfig;
8774
8775 if (QDF_TIMER_STATE_RUNNING ==
8776 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8777 ap.vendor_acs_timer)) {
8778 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8779 }
8780
8781 if (channel_list && channel_list->pri_ch == 0) {
8782 /* Check mode, set default channel */
8783 channel_list->pri_ch = 6;
8784 /*
8785 * sap_select_default_oper_chan(hdd_ctx->hHal,
8786 * sap_config->acs_cfg.hw_mode);
8787 */
8788 }
8789
8790 switch (reason) {
8791 /* SAP init case */
8792 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8793 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8794 /* Update Hostapd */
8795 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8796 break;
8797
8798 /* DFS detected on current channel */
8799 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8800 wlan_sap_update_next_channel(
8801 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8802 channel_list->pri_ch,
8803 channel_list->chan_width);
8804 status = sme_update_new_channel_event(
8805 WLAN_HDD_GET_HAL_CTX(adapter),
8806 adapter->sessionId);
8807 break;
8808
8809 /* LTE coex event on current channel */
8810 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8811 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8812 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8813 hdd_ap_ctx->sapConfig.ch_width_orig =
8814 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008815 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308816 break;
8817
8818 default:
8819 hdd_info("invalid reason for timer invoke");
8820 }
8821 qdf_mem_free(channel_list);
8822 EXIT();
8823 return status;
8824}
8825
8826/**
8827 * Define short name for vendor channel set config
8828 */
8829#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8830#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8831#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8832#define SET_CHAN_PRIMARY_CHANNEL \
8833 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8834#define SET_CHAN_SECONDARY_CHANNEL \
8835 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8836#define SET_CHAN_SEG0_CENTER_CHANNEL \
8837 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8838#define SET_CHAN_SEG1_CENTER_CHANNEL \
8839 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8840#define SET_CHAN_CHANNEL_WIDTH \
8841 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8842#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8843
8844/**
8845 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8846 * @channel_list: pointer to hdd_vendor_chan_info
8847 * @reason: channel change reason
8848 * @channel_cnt: channel count
8849 * @data: data
8850 * @data_len: data len
8851 *
8852 * Return: 0 on success, negative errno on failure
8853 */
8854static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8855 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8856 const void *data, int data_len)
8857{
8858 int rem, i = 0;
8859 struct nlattr *tb[SET_CHAN_MAX + 1];
8860 struct nlattr *tb2[SET_CHAN_MAX + 1];
8861 struct nlattr *curr_attr;
8862 struct hdd_vendor_chan_info *channel_list;
8863
8864 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8865 hdd_err("Invalid ATTR");
8866 return -EINVAL;
8867 }
8868
8869 if (tb[SET_CHAN_REASON])
8870 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8871
8872 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8873 *channel_cnt = nla_get_u8(tb[
8874 SET_CHAN_CHANNEL_COUNT]);
8875 hdd_info("channel count %d", *channel_cnt);
8876 }
8877
8878 if (!(*channel_cnt)) {
8879 hdd_err("channel count is %d", *channel_cnt);
8880 return -EINVAL;
8881 }
8882
8883 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8884 (*channel_cnt));
8885
8886 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8887 if (nla_parse(tb2,
8888 SET_CHAN_MAX,
8889 nla_data(curr_attr), nla_len(curr_attr),
8890 NULL)) {
8891 hdd_err("nla_parse failed");
8892 return -EINVAL;
8893 }
8894 /* Parse and Fetch allowed SSID list*/
8895 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8896 channel_list[i].pri_ch =
8897 nla_get_u8(
8898 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8899 }
8900 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8901 channel_list[i].ht_sec_ch =
8902 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8903 }
8904 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8905 channel_list[i].vht_seg0_center_ch =
8906 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8907 }
8908 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8909 channel_list[i].vht_seg1_center_ch =
8910 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8911 }
8912 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8913 channel_list[i].chan_width =
8914 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8915 }
8916 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8917 i, channel_list[i].pri_ch,
8918 channel_list[i].ht_sec_ch,
8919 channel_list[i].vht_seg0_center_ch,
8920 channel_list[i].vht_seg1_center_ch,
8921 channel_list[i].chan_width);
8922 i++;
8923 if (i > *channel_cnt)
8924 break;
8925 }
8926 *chan_list_ptr = channel_list;
8927
8928 return 0;
8929}
8930
8931/**
8932 * Undef short names for vendor set channel configuration
8933 */
8934#undef SET_CHAN_REASON
8935#undef SET_CHAN_CHANNEL_COUNT
8936#undef SET_CHAN_CHAN_LIST
8937#undef SET_CHAN_PRIMARY_CHANNEL
8938#undef SET_CHAN_SECONDARY_CHANNEL
8939#undef SET_CHAN_SEG0_CENTER_CHANNEL
8940#undef SET_CHAN_SEG1_CENTER_CHANNEL
8941#undef SET_CHAN_CHANNEL_WIDTH
8942#undef SET_CHAN_MAX
8943
8944/**
8945 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8946 * @wiphy: Pointer to wireless phy
8947 * @wdev: Pointer to wireless device
8948 * @data: Pointer to data
8949 * @data_len: Length of @data
8950 *
8951 * Return: 0 on success, negative errno on failure
8952 */
8953static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8954 struct wireless_dev *wdev,
8955 const void *data, int data_len)
8956{
8957 int ret_val;
8958 QDF_STATUS qdf_status;
8959 uint8_t channel_cnt = 0, reason = -1;
8960 struct hdd_vendor_chan_info *channel_list = NULL;
8961 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8962 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8963
8964 ENTER();
8965
8966 ret_val = wlan_hdd_validate_context(hdd_ctx);
8967 if (ret_val)
8968 return ret_val;
8969
8970 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8971 hdd_err("Command not allowed in FTM mode");
8972 return -EINVAL;
8973 }
8974
8975 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8976 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8977 else {
8978 hdd_err("already timeout happened for acs");
8979 return -EINVAL;
8980 }
8981
8982 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8983 &channel_cnt, data, data_len);
8984 if (ret_val)
8985 return ret_val;
8986
8987 /* Validate channel to be set */
8988 while (channel_cnt && channel_list) {
8989 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8990 channel_list->pri_ch,
8991 channel_list->chan_width);
8992 if (qdf_status == QDF_STATUS_SUCCESS)
8993 break;
8994 channel_cnt--;
8995 channel_list++;
8996 }
8997 if ((channel_cnt <= 0) || !channel_list) {
8998 hdd_err("no available channel/chanlist %p", channel_list);
8999 return -EINVAL;
9000 }
9001
9002 qdf_status = hdd_update_acs_channel(adapter, reason,
9003 channel_cnt, channel_list);
9004 return qdf_status_to_os_return(qdf_status);
9005}
9006
9007/**
9008 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9009 * @wiphy: Pointer to wireless phy
9010 * @wdev: Pointer to wireless device
9011 * @data: Pointer to data
9012 * @data_len: Length of @data
9013 *
9014 * Return: 0 on success, negative errno on failure
9015 */
9016static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9017 struct wireless_dev *wdev,
9018 const void *data, int data_len)
9019{
9020 int ret;
9021
9022 cds_ssr_protect(__func__);
9023 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
9024 data_len);
9025 cds_ssr_protect(__func__);
9026
9027 return ret;
9028}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309029
9030/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309031 * wlan_hdd_cfg80211_setband() - Wrapper to setband
9032 * @wiphy: wiphy structure pointer
9033 * @wdev: Wireless device structure pointer
9034 * @data: Pointer to the data received
9035 * @data_len: Length of @data
9036 *
9037 * Return: 0 on success; errno on failure
9038 */
9039static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9040 struct wireless_dev *wdev,
9041 const void *data, int data_len)
9042{
9043 int ret;
9044
9045 cds_ssr_protect(__func__);
9046 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
9047 cds_ssr_unprotect(__func__);
9048
9049 return ret;
9050}
9051
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009052/**
9053 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
9054 * @nl80211_value: Vendor command attribute value
9055 * @wmi_value: Pointer to return converted WMI return value
9056 *
9057 * Convert NL80211 vendor command value for SAR limit set to WMI value
9058 * Return: 0 on success, -1 on invalid value
9059 */
9060static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
9061 u32 *wmi_value)
9062{
9063 int ret = 0;
9064
9065 switch (nl80211_value) {
9066 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
9067 *wmi_value = WMI_SAR_FEATURE_OFF;
9068 break;
9069 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
9070 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
9071 break;
9072 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
9073 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
9074 break;
9075 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
9076 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
9077 break;
9078 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
9079 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
9080 break;
9081 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
9082 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
9083 break;
9084 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
9085 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
9086 break;
9087 default:
9088 ret = -1;
9089 }
9090 return ret;
9091}
9092
9093/**
9094 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
9095 * @nl80211_value: Vendor command attribute value
9096 * @wmi_value: Pointer to return converted WMI return value
9097 *
9098 * Convert NL80211 vendor command value for SAR BAND to WMI value
9099 * Return: 0 on success, -1 on invalid value
9100 */
9101static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
9102{
9103 int ret = 0;
9104
9105 switch (nl80211_value) {
9106 case NL80211_BAND_2GHZ:
9107 *wmi_value = WMI_SAR_2G_ID;
9108 break;
9109 case NL80211_BAND_5GHZ:
9110 *wmi_value = WMI_SAR_5G_ID;
9111 break;
9112 default:
9113 ret = -1;
9114 }
9115 return ret;
9116}
9117
9118/**
9119 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9120 * @nl80211_value: Vendor command attribute value
9121 * @wmi_value: Pointer to return converted WMI return value
9122 *
9123 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9124 * Return: 0 on success, -1 on invalid value
9125 */
9126static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9127 u32 *wmi_value)
9128{
9129 int ret = 0;
9130
9131 switch (nl80211_value) {
9132 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9133 *wmi_value = WMI_SAR_MOD_CCK;
9134 break;
9135 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9136 *wmi_value = WMI_SAR_MOD_OFDM;
9137 break;
9138 default:
9139 ret = -1;
9140 }
9141 return ret;
9142}
9143
9144
9145/**
9146 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9147 * @wiphy: Pointer to wireless phy
9148 * @wdev: Pointer to wireless device
9149 * @data: Pointer to data
9150 * @data_len: Length of @data
9151 *
9152 * This function is used to setup Specific Absorption Rate limit specs.
9153 *
9154 * Return: 0 on success, negative errno on failure
9155 */
9156static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9157 struct wireless_dev *wdev,
9158 const void *data, int data_len)
9159{
9160 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9161 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9162 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9163 *sar_spec_list;
9164 struct sar_limit_cmd_params sar_limit_cmd = {0};
9165 int ret = -EINVAL, i = 0, rem = 0;
9166
9167 ENTER();
9168
9169 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9170 hdd_err("Command not allowed in FTM mode");
9171 return -EPERM;
9172 }
9173
9174 if (wlan_hdd_validate_context(hdd_ctx))
9175 return -EINVAL;
9176
9177 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9178 data, data_len, NULL)) {
9179 hdd_err("Invalid SAR attributes");
9180 return -EINVAL;
9181 }
9182
9183 /* Vendor command manadates all SAR Specs in single call */
9184 sar_limit_cmd.commit_limits = 1;
9185 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9186 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9187 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9188 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9189 &sar_limit_cmd.sar_enable) < 0) {
9190 hdd_err("Invalid SAR Enable attr");
9191 goto fail;
9192 }
9193 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009194 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009195
9196 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9197 sar_limit_cmd.num_limit_rows = nla_get_u32(
9198 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009199 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009200 sar_limit_cmd.num_limit_rows);
9201 }
9202 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9203 hdd_err("SAR Spec list exceed supported size");
9204 goto fail;
9205 }
9206 if (sar_limit_cmd.num_limit_rows == 0)
9207 goto send_sar_limits;
9208 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9209 struct sar_limit_cmd_row) *
9210 sar_limit_cmd.num_limit_rows);
9211 if (!sar_limit_cmd.sar_limit_row_list) {
9212 ret = -ENOMEM;
9213 goto fail;
9214 }
9215 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9216 hdd_err("Invalid SAR SPECs list");
9217 goto fail;
9218 }
9219
9220 nla_for_each_nested(sar_spec_list,
9221 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9222 if (i == sar_limit_cmd.num_limit_rows) {
9223 hdd_warn("SAR Cmd has excess SPECs in list");
9224 break;
9225 }
9226
9227 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9228 nla_data(sar_spec_list), nla_len(sar_spec_list),
9229 NULL)) {
9230 hdd_err("nla_parse failed for SAR Spec list");
9231 goto fail;
9232 }
9233 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9234 if (sar_spec[
9235 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9236 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9237 nla_get_u32(sar_spec[
9238 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9239 } else {
9240 hdd_err("SAR Spec does not have power limit value");
9241 goto fail;
9242 }
9243
9244 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9245 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9246 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9247 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9248 < 0) {
9249 hdd_err("Invalid SAR Band attr");
9250 goto fail;
9251 }
9252 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9253 WMI_SAR_BAND_ID_VALID_MASK;
9254 }
9255 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9256 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9257 nla_get_u32(sar_spec[
9258 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9259 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9260 WMI_SAR_CHAIN_ID_VALID_MASK;
9261 }
9262 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9263 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9264 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9265 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9266 < 0) {
9267 hdd_err("Invalid SAR Modulation attr");
9268 goto fail;
9269 }
9270 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9271 WMI_SAR_MOD_ID_VALID_MASK;
9272 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009273 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009274 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9275 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9276 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9277 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9278 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9279 i++;
9280 }
9281
9282 if (i < sar_limit_cmd.num_limit_rows) {
9283 hdd_warn("SAR Cmd has less SPECs in list");
9284 sar_limit_cmd.num_limit_rows = i;
9285 }
9286
9287send_sar_limits:
9288 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9289 QDF_STATUS_SUCCESS)
9290 ret = 0;
9291fail:
9292 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9293 return ret;
9294}
9295
9296/**
9297 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9298 * @wiphy: Pointer to wireless phy
9299 * @wdev: Pointer to wireless device
9300 * @data: Pointer to data
9301 * @data_len: Length of @data
9302 *
9303 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9304 *
9305 * Return: 0 on success, negative errno on failure
9306 */
9307static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9308 struct wireless_dev *wdev,
9309 const void *data,
9310 int data_len)
9311{
9312 int ret;
9313
9314 cds_ssr_protect(__func__);
9315 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9316 data_len);
9317 cds_ssr_unprotect(__func__);
9318
9319 return ret;
9320}
9321
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309322static const struct
9323nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9324 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9325 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9326 .len = QDF_MAC_ADDR_SIZE},
9327};
9328
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309329void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9330{
9331 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9332 hdd_adapter_t *adapter;
9333
9334 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9335 if (!adapter) {
9336 hdd_err("adapter NULL");
9337 return;
9338 }
9339
9340 adapter->lfr_fw_status.is_disabled = rso_status->status;
9341 complete(&adapter->lfr_fw_status.disable_lfr_event);
9342}
9343
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309344/**
9345 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9346 * @wiphy: Pointer to wireless phy
9347 * @wdev: Pointer to wireless device
9348 * @data: Pointer to data
9349 * @data_len: Length of @data
9350 *
9351 * This function is used to enable/disable roaming using vendor commands
9352 *
9353 * Return: 0 on success, negative errno on failure
9354 */
9355static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9356 struct wireless_dev *wdev,
9357 const void *data, int data_len)
9358{
9359 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9360 struct net_device *dev = wdev->netdev;
9361 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9362 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309363 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309364 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309365 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309366 unsigned long rc;
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309367 hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309368
9369 ENTER_DEV(dev);
9370
9371 ret = wlan_hdd_validate_context(hdd_ctx);
9372 if (0 != ret)
9373 return ret;
9374
9375 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9376 hdd_err("Command not allowed in FTM mode");
9377 return -EINVAL;
9378 }
9379
9380 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9381 qca_wlan_vendor_attr);
9382 if (ret) {
9383 hdd_err("Invalid ATTR");
9384 return -EINVAL;
9385 }
9386
9387 /* Parse and fetch Enable flag */
9388 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9389 hdd_err("attr enable failed");
9390 return -EINVAL;
9391 }
9392
9393 is_fast_roam_enabled = nla_get_u32(
9394 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009395 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009396 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309397
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009398 if (!adapter->fast_roaming_allowed) {
9399 hdd_err("fast roaming not allowed on %s interface",
9400 adapter->dev->name);
9401 return -EINVAL;
9402 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309403 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309404 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309405 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309406 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309407 if (qdf_status != QDF_STATUS_SUCCESS)
9408 hdd_err("sme_config_fast_roaming failed with status=%d",
9409 qdf_status);
9410 ret = qdf_status_to_os_return(qdf_status);
9411
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309412 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.connState &&
9413 QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9414
9415 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309416 /*
9417 * wait only for LFR disable in fw as LFR enable
9418 * is always success
9419 */
9420 rc = wait_for_completion_timeout(
9421 &adapter->lfr_fw_status.disable_lfr_event,
9422 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9423 if (!rc) {
9424 hdd_err("Timed out waiting for RSO CMD status");
9425 return -ETIMEDOUT;
9426 }
9427
9428 if (!adapter->lfr_fw_status.is_disabled) {
9429 hdd_err("Roam disable attempt in FW fails");
9430 return -EBUSY;
9431 }
9432 }
9433
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309434 EXIT();
9435 return ret;
9436}
9437
9438/**
9439 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9440 * @wiphy: Pointer to wireless phy
9441 * @wdev: Pointer to wireless device
9442 * @data: Pointer to data
9443 * @data_len: Length of @data
9444 *
9445 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9446 *
9447 * Return: 0 on success, negative errno on failure
9448 */
9449static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9450 struct wireless_dev *wdev,
9451 const void *data, int data_len)
9452{
9453 int ret;
9454
9455 cds_ssr_protect(__func__);
9456 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9457 cds_ssr_unprotect(__func__);
9458
9459 return ret;
9460}
9461
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309462
9463void hdd_update_cca_info_cb(void *context, uint32_t congestion,
9464 uint32_t vdev_id)
9465{
9466 hdd_context_t *hdd_ctx = (hdd_context_t *)context;
9467 int status;
9468 hdd_adapter_t *adapter = NULL;
9469 hdd_station_ctx_t *hdd_sta_ctx;
9470
9471 status = wlan_hdd_validate_context(hdd_ctx);
9472 if (status != 0)
9473 return;
9474
9475 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9476 if (adapter == NULL) {
9477 hdd_err("vdev_id %d does not exist with host", vdev_id);
9478 return;
9479 }
9480
9481 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9482 hdd_sta_ctx->conn_info.cca = congestion;
9483 hdd_info("congestion:%d", congestion);
9484}
9485
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309486static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9487 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9488 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9489 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9490 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9491};
9492
9493/**
9494 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9495 * @wiphy: Pointer to wireless phy
9496 * @wdev: Pointer to wireless device
9497 * @data: Pointer to data
9498 * @data_len: Length of @data
9499 *
9500 * Return: 0 on success, negative errno on failure
9501 */
9502static int
9503__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9504 struct wireless_dev *wdev,
9505 const void *data,
9506 int data_len)
9507{
9508 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9509 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9510 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9511 struct nlattr *apth;
9512 int rem;
9513 int ret = 1;
9514 int print_idx = -1;
9515 int module_id = -1;
9516 int bit_mask = -1;
9517 int status;
9518
9519 ENTER();
9520
9521 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9522 hdd_err("Command not allowed in FTM mode");
9523 return -EINVAL;
9524 }
9525
9526 ret = wlan_hdd_validate_context(hdd_ctx);
9527 if (ret != 0)
9528 return -EINVAL;
9529
9530 print_idx = qdf_get_pidx();
9531 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9532 hdd_err("Invalid print controle object index");
9533 return -EINVAL;
9534 }
9535
9536 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9537 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9538 hdd_err("Invalid attr");
9539 return -EINVAL;
9540 }
9541
9542 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9543 hdd_err("attr trace level param failed");
9544 return -EINVAL;
9545 }
9546
9547 nla_for_each_nested(apth,
9548 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9549 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9550 nla_data(apth), nla_len(apth), NULL)) {
9551 hdd_err("Invalid attr");
9552 return -EINVAL;
9553 }
9554
9555 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9556 hdd_err("attr Module ID failed");
9557 return -EINVAL;
9558 }
9559 module_id = nla_get_u32
9560 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9561
9562 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9563 hdd_err("attr Verbose mask failed");
9564 return -EINVAL;
9565 }
9566 bit_mask = nla_get_u32
9567 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9568
9569 status = hdd_qdf_trace_enable(module_id, bit_mask);
9570
9571 if (status != 0)
9572 hdd_err("can not set verbose mask %d for the category %d",
9573 bit_mask, module_id);
9574 }
9575
9576 EXIT();
9577 return ret;
9578}
9579
9580/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309581 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9582 * @wiphy: Pointer to wireless phy
9583 * @wdev: Pointer to wireless device
9584 * @data: Pointer to data
9585 * @data_len: Length of @data
9586 *
9587 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9588 *
9589 * Return: 0 on success, negative errno on failure
9590 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309591
9592static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9593 struct wireless_dev *wdev,
9594 const void *data,
9595 int data_len)
9596{
9597 int ret;
9598
9599 cds_ssr_protect(__func__);
9600 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9601 cds_ssr_unprotect(__func__);
9602
9603 return ret;
9604}
9605
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009606const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9607 {
9608 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9609 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9610 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309611 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009612 .doit = is_driver_dfs_capable
9613 },
9614
9615#ifdef WLAN_FEATURE_NAN
9616 {
9617 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9618 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9619 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9620 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9621 .doit = wlan_hdd_cfg80211_nan_request
9622 },
9623#endif
9624
9625#ifdef WLAN_FEATURE_STATS_EXT
9626 {
9627 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9628 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9629 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9630 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9631 .doit = wlan_hdd_cfg80211_stats_ext_request
9632 },
9633#endif
9634#ifdef FEATURE_WLAN_EXTSCAN
9635 {
9636 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9637 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9638 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9639 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9640 .doit = wlan_hdd_cfg80211_extscan_start
9641 },
9642 {
9643 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9644 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9645 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9646 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9647 .doit = wlan_hdd_cfg80211_extscan_stop
9648 },
9649 {
9650 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9651 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9652 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9653 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9654 },
9655 {
9656 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9657 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9658 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9659 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9660 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9661 },
9662 {
9663 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9664 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9665 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9666 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9667 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9668 },
9669 {
9670 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9671 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9672 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9673 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9674 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9675 },
9676 {
9677 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9678 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9679 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9680 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9681 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9682 },
9683 {
9684 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9685 .info.subcmd =
9686 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9687 .flags =
9688 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9689 WIPHY_VENDOR_CMD_NEED_RUNNING,
9690 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9691 },
9692 {
9693 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9694 .info.subcmd =
9695 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9696 .flags =
9697 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9698 WIPHY_VENDOR_CMD_NEED_RUNNING,
9699 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9700 },
9701 {
9702 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9703 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9704 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9705 WIPHY_VENDOR_CMD_NEED_NETDEV |
9706 WIPHY_VENDOR_CMD_NEED_RUNNING,
9707 .doit = wlan_hdd_cfg80211_set_epno_list
9708 },
9709#endif /* FEATURE_WLAN_EXTSCAN */
9710
9711#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9712 {
9713 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9714 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9715 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9716 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9717 .doit = wlan_hdd_cfg80211_ll_stats_clear
9718 },
9719
9720 {
9721 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9722 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9723 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9724 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9725 .doit = wlan_hdd_cfg80211_ll_stats_set
9726 },
9727
9728 {
9729 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9730 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9731 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9732 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9733 .doit = wlan_hdd_cfg80211_ll_stats_get
9734 },
9735#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9736#ifdef FEATURE_WLAN_TDLS
9737 {
9738 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9739 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9740 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9741 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9742 .doit = wlan_hdd_cfg80211_exttdls_enable
9743 },
9744 {
9745 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9746 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9747 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9748 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9749 .doit = wlan_hdd_cfg80211_exttdls_disable
9750 },
9751 {
9752 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9753 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9754 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9755 .doit = wlan_hdd_cfg80211_exttdls_get_status
9756 },
9757#endif
9758 {
9759 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9760 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9761 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9762 .doit = wlan_hdd_cfg80211_get_supported_features
9763 },
9764 {
9765 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9766 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309767 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9768 WIPHY_VENDOR_CMD_NEED_NETDEV |
9769 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009770 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9771 },
9772 {
9773 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9774 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9775 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309776 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009777 },
9778 {
9779 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9780 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9781 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309782 WIPHY_VENDOR_CMD_NEED_NETDEV |
9783 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009784 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9785 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009786 {
9787 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9788 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9789 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309790 WIPHY_VENDOR_CMD_NEED_NETDEV |
9791 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -07009792 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9793 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009794 {
9795 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309796 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9797 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9798 WIPHY_VENDOR_CMD_NEED_NETDEV |
9799 WIPHY_VENDOR_CMD_NEED_RUNNING,
9800 .doit = hdd_cfg80211_get_station_cmd
9801 },
9802 {
9803 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009804 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9805 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9806 WIPHY_VENDOR_CMD_NEED_NETDEV |
9807 WIPHY_VENDOR_CMD_NEED_RUNNING,
9808 .doit = wlan_hdd_cfg80211_do_acs
9809 },
9810
9811 {
9812 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9813 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9814 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9815 WIPHY_VENDOR_CMD_NEED_NETDEV,
9816 .doit = wlan_hdd_cfg80211_get_features
9817 },
9818#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9819 {
9820 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9821 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9822 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9823 WIPHY_VENDOR_CMD_NEED_NETDEV |
9824 WIPHY_VENDOR_CMD_NEED_RUNNING,
9825 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9826 },
9827#endif
9828#ifdef FEATURE_WLAN_EXTSCAN
9829 {
9830 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9831 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9832 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9833 WIPHY_VENDOR_CMD_NEED_NETDEV |
9834 WIPHY_VENDOR_CMD_NEED_RUNNING,
9835 .doit = wlan_hdd_cfg80211_set_passpoint_list
9836 },
9837 {
9838 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9839 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9840 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9841 WIPHY_VENDOR_CMD_NEED_NETDEV |
9842 WIPHY_VENDOR_CMD_NEED_RUNNING,
9843 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9844 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009845#endif /* FEATURE_WLAN_EXTSCAN */
9846 {
9847 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9848 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9849 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9850 WIPHY_VENDOR_CMD_NEED_NETDEV,
9851 .doit = wlan_hdd_cfg80211_get_wifi_info
9852 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009853#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009854 {
9855 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9856 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9857 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9858 WIPHY_VENDOR_CMD_NEED_NETDEV |
9859 WIPHY_VENDOR_CMD_NEED_RUNNING,
9860 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9861 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009862#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009863 {
9864 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9865 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9866 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309867 WIPHY_VENDOR_CMD_NEED_NETDEV |
9868 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009869 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9870 },
9871 {
9872 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9873 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9874 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309875 WIPHY_VENDOR_CMD_NEED_NETDEV |
9876 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009877 .doit = wlan_hdd_cfg80211_wifi_logger_start
9878 },
9879 {
9880 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9881 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9882 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309883 WIPHY_VENDOR_CMD_NEED_NETDEV |
9884 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009885 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9886 },
9887 {
9888 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9889 .info.subcmd =
9890 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9891 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9892 WIPHY_VENDOR_CMD_NEED_NETDEV |
9893 WIPHY_VENDOR_CMD_NEED_RUNNING,
9894 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9895 },
9896 {
9897 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9898 .info.subcmd =
9899 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9900 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9901 WIPHY_VENDOR_CMD_NEED_NETDEV |
9902 WIPHY_VENDOR_CMD_NEED_RUNNING,
9903 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9904 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009905#ifdef WLAN_FEATURE_TSF
9906 {
9907 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9908 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9909 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9910 WIPHY_VENDOR_CMD_NEED_NETDEV |
9911 WIPHY_VENDOR_CMD_NEED_RUNNING,
9912 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9913 },
9914#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009915#ifdef FEATURE_WLAN_TDLS
9916 {
9917 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9918 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9919 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9920 WIPHY_VENDOR_CMD_NEED_NETDEV |
9921 WIPHY_VENDOR_CMD_NEED_RUNNING,
9922 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9923 },
9924#endif
9925#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9926 {
9927 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9928 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9929 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9930 WIPHY_VENDOR_CMD_NEED_NETDEV |
9931 WIPHY_VENDOR_CMD_NEED_RUNNING,
9932 .doit = wlan_hdd_cfg80211_offloaded_packets
9933 },
9934#endif
9935 {
9936 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9937 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9938 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9939 WIPHY_VENDOR_CMD_NEED_NETDEV |
9940 WIPHY_VENDOR_CMD_NEED_RUNNING,
9941 .doit = wlan_hdd_cfg80211_monitor_rssi
9942 },
9943 {
9944 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309945 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9946 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9947 WIPHY_VENDOR_CMD_NEED_NETDEV |
9948 WIPHY_VENDOR_CMD_NEED_RUNNING,
9949 .doit = wlan_hdd_cfg80211_set_ns_offload
9950 },
9951 {
9952 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009953 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9954 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9955 WIPHY_VENDOR_CMD_NEED_NETDEV |
9956 WIPHY_VENDOR_CMD_NEED_RUNNING,
9957 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9958 },
9959#ifdef WLAN_FEATURE_MEMDUMP
9960 {
9961 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9962 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9963 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9964 WIPHY_VENDOR_CMD_NEED_NETDEV |
9965 WIPHY_VENDOR_CMD_NEED_RUNNING,
9966 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9967 },
9968#endif /* WLAN_FEATURE_MEMDUMP */
9969 {
9970 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9971 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9972 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9973 WIPHY_VENDOR_CMD_NEED_NETDEV |
9974 WIPHY_VENDOR_CMD_NEED_RUNNING,
9975 .doit = wlan_hdd_cfg80211_vendor_scan
9976 },
9977
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309978 /* Vendor abort scan */
9979 {
9980 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9981 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9982 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9983 WIPHY_VENDOR_CMD_NEED_NETDEV |
9984 WIPHY_VENDOR_CMD_NEED_RUNNING,
9985 .doit = wlan_hdd_vendor_abort_scan
9986 },
9987
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009988 /* OCB commands */
9989 {
9990 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9991 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9992 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9993 WIPHY_VENDOR_CMD_NEED_NETDEV |
9994 WIPHY_VENDOR_CMD_NEED_RUNNING,
9995 .doit = wlan_hdd_cfg80211_ocb_set_config
9996 },
9997 {
9998 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9999 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
10000 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10001 WIPHY_VENDOR_CMD_NEED_NETDEV |
10002 WIPHY_VENDOR_CMD_NEED_RUNNING,
10003 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
10004 },
10005 {
10006 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10007 .info.subcmd =
10008 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
10009 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10010 WIPHY_VENDOR_CMD_NEED_NETDEV |
10011 WIPHY_VENDOR_CMD_NEED_RUNNING,
10012 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
10013 },
10014 {
10015 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10016 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
10017 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10018 WIPHY_VENDOR_CMD_NEED_NETDEV |
10019 WIPHY_VENDOR_CMD_NEED_RUNNING,
10020 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
10021 },
10022 {
10023 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10024 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
10025 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10026 WIPHY_VENDOR_CMD_NEED_NETDEV |
10027 WIPHY_VENDOR_CMD_NEED_RUNNING,
10028 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
10029 },
10030 {
10031 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10032 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
10033 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10034 WIPHY_VENDOR_CMD_NEED_NETDEV |
10035 WIPHY_VENDOR_CMD_NEED_RUNNING,
10036 .doit = wlan_hdd_cfg80211_dcc_get_stats
10037 },
10038 {
10039 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10040 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
10041 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10042 WIPHY_VENDOR_CMD_NEED_NETDEV |
10043 WIPHY_VENDOR_CMD_NEED_RUNNING,
10044 .doit = wlan_hdd_cfg80211_dcc_clear_stats
10045 },
10046 {
10047 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10048 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
10049 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10050 WIPHY_VENDOR_CMD_NEED_NETDEV |
10051 WIPHY_VENDOR_CMD_NEED_RUNNING,
10052 .doit = wlan_hdd_cfg80211_dcc_update_ndl
10053 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010054 {
10055 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10056 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
10057 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10058 WIPHY_VENDOR_CMD_NEED_NETDEV |
10059 WIPHY_VENDOR_CMD_NEED_RUNNING,
10060 .doit = wlan_hdd_cfg80211_get_link_properties
10061 },
Peng Xu278d0122015-09-24 16:34:17 -070010062 {
Peng Xud2220962016-07-11 17:59:17 -070010063 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -070010064 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
10065 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10066 WIPHY_VENDOR_CMD_NEED_NETDEV |
10067 WIPHY_VENDOR_CMD_NEED_RUNNING,
10068 .doit = wlan_hdd_cfg80211_set_ota_test
10069 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -080010070#ifdef FEATURE_LFR_SUBNET_DETECTION
10071 {
10072 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10073 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
10074 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10075 WIPHY_VENDOR_CMD_NEED_NETDEV |
10076 WIPHY_VENDOR_CMD_NEED_RUNNING,
10077 .doit = wlan_hdd_cfg80211_set_gateway_params
10078 },
10079#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -070010080 {
Peng Xud2220962016-07-11 17:59:17 -070010081 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -070010082 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
10083 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10084 WIPHY_VENDOR_CMD_NEED_NETDEV |
10085 WIPHY_VENDOR_CMD_NEED_RUNNING,
10086 .doit = wlan_hdd_cfg80211_txpower_scale
10087 },
10088 {
10089 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10090 .info.subcmd =
10091 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
10092 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10093 WIPHY_VENDOR_CMD_NEED_NETDEV |
10094 WIPHY_VENDOR_CMD_NEED_RUNNING,
10095 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
10096 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +053010097 {
10098 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10099 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
10100 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10101 WIPHY_VENDOR_CMD_NEED_NETDEV |
10102 WIPHY_VENDOR_CMD_NEED_RUNNING,
10103 .doit = wlan_hdd_cfg80211_bpf_offload
10104 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010105 {
10106 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053010107 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
10108 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10109 WIPHY_VENDOR_CMD_NEED_NETDEV |
10110 WIPHY_VENDOR_CMD_NEED_RUNNING,
10111 .doit = wlan_hdd_cfg80211_acs_dfs_mode
10112 },
10113 {
10114 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010115 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
10116 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10117 WIPHY_VENDOR_CMD_NEED_NETDEV |
10118 WIPHY_VENDOR_CMD_NEED_RUNNING,
10119 .doit = wlan_hdd_cfg80211_sta_roam_policy
10120 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053010121#ifdef FEATURE_WLAN_CH_AVOID
10122 {
10123 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10124 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
10125 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10126 WIPHY_VENDOR_CMD_NEED_NETDEV |
10127 WIPHY_VENDOR_CMD_NEED_RUNNING,
10128 .doit = wlan_hdd_cfg80211_avoid_freq
10129 },
10130#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010131 {
10132 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010133 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
10134 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10135 WIPHY_VENDOR_CMD_NEED_NETDEV |
10136 WIPHY_VENDOR_CMD_NEED_RUNNING,
10137 .doit = wlan_hdd_cfg80211_sap_configuration_set
10138 },
Peng Xu8fdaa492016-06-22 10:20:47 -070010139 {
Peng Xu4225c152016-07-14 21:18:14 -070010140 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070010141 .info.subcmd =
10142 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
10143 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10144 WIPHY_VENDOR_CMD_NEED_NETDEV |
10145 WIPHY_VENDOR_CMD_NEED_RUNNING,
10146 .doit = wlan_hdd_cfg80211_p2p_lo_start
10147 },
10148 {
10149 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10150 .info.subcmd =
10151 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
10152 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10153 WIPHY_VENDOR_CMD_NEED_NETDEV |
10154 WIPHY_VENDOR_CMD_NEED_RUNNING,
10155 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10156 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010157 {
10158 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10159 .info.subcmd =
10160 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10161 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10162 WIPHY_VENDOR_CMD_NEED_NETDEV |
10163 WIPHY_VENDOR_CMD_NEED_RUNNING,
10164 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10165 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010166#ifdef WLAN_FEATURE_NAN_DATAPATH
10167 {
10168 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10169 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10170 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10171 WIPHY_VENDOR_CMD_NEED_NETDEV |
10172 WIPHY_VENDOR_CMD_NEED_RUNNING,
10173 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10174 },
10175#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010176 {
10177 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10178 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10179 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10180 WIPHY_VENDOR_CMD_NEED_NETDEV |
10181 WIPHY_VENDOR_CMD_NEED_RUNNING,
10182 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10183 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010184 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010185 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10186 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10187 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10188 WIPHY_VENDOR_CMD_NEED_NETDEV |
10189 WIPHY_VENDOR_CMD_NEED_RUNNING,
10190 .doit = wlan_hdd_cfg80211_get_bus_size
10191 },
10192 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010193 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10194 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10195 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10196 WIPHY_VENDOR_CMD_NEED_NETDEV |
10197 WIPHY_VENDOR_CMD_NEED_RUNNING,
10198 .doit = wlan_hdd_cfg80211_update_vendor_channel
10199 },
10200 {
bingsd09dea32017-03-17 10:08:26 +080010201 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010202 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10203 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10204 WIPHY_VENDOR_CMD_NEED_NETDEV |
10205 WIPHY_VENDOR_CMD_NEED_RUNNING,
10206 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010207 },
10208 {
10209 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10210 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10211 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10212 WIPHY_VENDOR_CMD_NEED_NETDEV |
10213 WIPHY_VENDOR_CMD_NEED_RUNNING,
10214 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010215 },
10216#ifdef WLAN_FEATURE_DISA
10217 {
10218 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10219 .info.subcmd =
10220 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10221 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10222 WIPHY_VENDOR_CMD_NEED_NETDEV |
10223 WIPHY_VENDOR_CMD_NEED_RUNNING,
10224 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10225 },
10226#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010227#ifdef FEATURE_WLAN_TDLS
10228 {
10229 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10230 .info.subcmd =
10231 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10232 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10233 WIPHY_VENDOR_CMD_NEED_NETDEV |
10234 WIPHY_VENDOR_CMD_NEED_RUNNING,
10235 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010236 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010237#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010238 {
10239 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10240 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10241 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10242 WIPHY_VENDOR_CMD_NEED_RUNNING,
10243 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10244 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010245 {
10246 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10247 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10248 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10249 WIPHY_VENDOR_CMD_NEED_NETDEV |
10250 WIPHY_VENDOR_CMD_NEED_RUNNING,
10251 .doit = wlan_hdd_cfg80211_set_trace_level
10252 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080010253 {
10254 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10255 .info.subcmd =
10256 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
10257 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10258 WIPHY_VENDOR_CMD_NEED_NETDEV |
10259 WIPHY_VENDOR_CMD_NEED_RUNNING,
10260 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
10261 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010262
Paul Zhang3a210c52016-12-08 10:18:12 +080010263#ifdef WLAN_UMAC_CONVERGENCE
10264 COMMON_VENDOR_COMMANDS
10265#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010266 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010267};
10268
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010269#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10270 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10271 defined(FEATURE_WLAN_SCAN_PNO)
10272/**
10273 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10274 * @wiphy: pointer to wiphy
10275 * @config: pointer to config
10276 *
10277 * Return: None
10278 */
10279static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10280 struct hdd_config *config)
10281{
10282 if (config->configPNOScanSupport) {
10283 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010284 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10285 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010286 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010287 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010288 if (config->max_sched_scan_plan_interval)
10289 wiphy->max_sched_scan_plan_interval =
10290 config->max_sched_scan_plan_interval;
10291 if (config->max_sched_scan_plan_iterations)
10292 wiphy->max_sched_scan_plan_iterations =
10293 config->max_sched_scan_plan_iterations;
10294 }
10295}
10296#else
10297static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10298 struct hdd_config *config)
10299{
10300}
10301#endif
10302
10303
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010304/**
10305 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10306 * @priv_size: Size of the hdd context.
10307 *
10308 * Allocate wiphy context and hdd context.
10309 *
10310 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010311 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010312hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010313{
10314 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010315 hdd_context_t *hdd_ctx;
10316
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010317 ENTER();
10318
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010319 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10320
10321 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010322 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010323 return NULL;
10324 }
10325
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010326 hdd_ctx = wiphy_priv(wiphy);
10327
10328 hdd_ctx->wiphy = wiphy;
10329
10330 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010331}
10332
10333/*
10334 * FUNCTION: wlan_hdd_cfg80211_update_band
10335 * This function is called from the supplicant through a
10336 * private ioctl to change the band value
10337 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010338int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10339 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010340{
10341 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010342 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010343
10344 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010345 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010346
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010347 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010348 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010349
10350 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10351 struct ieee80211_supported_band *band = wiphy->bands[i];
10352
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010353 channelEnabledState = wlan_reg_get_channel_state(
10354 hdd_ctx->hdd_pdev,
10355 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010356
Dustin Browna30892e2016-10-12 17:28:36 -070010357 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010358 /* 5G only */
10359#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10360 /* Enable Social channels for P2P */
10361 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10362 (band->channels[j].center_freq)
10363 && CHANNEL_STATE_ENABLE ==
10364 channelEnabledState)
10365 band->channels[j].flags &=
10366 ~IEEE80211_CHAN_DISABLED;
10367 else
10368#endif
10369 band->channels[j].flags |=
10370 IEEE80211_CHAN_DISABLED;
10371 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010372 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010373 eCSR_BAND_24 == eBand) {
10374 /* 2G only */
10375 band->channels[j].flags |=
10376 IEEE80211_CHAN_DISABLED;
10377 continue;
10378 }
10379
Amar Singhal6842e8f2016-02-23 16:30:32 -080010380 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010381 band->channels[j].flags &=
10382 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010383 }
10384 }
10385 return 0;
10386}
10387
Peng Xuacfdda12017-02-06 16:15:38 -080010388#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010389/*
10390 * FUNCTION: wlan_hdd_cfg80211_init
10391 * This function is called by hdd_wlan_startup()
10392 * during initialization.
10393 * This function is used to initialize and register wiphy structure.
10394 */
10395int wlan_hdd_cfg80211_init(struct device *dev,
10396 struct wiphy *wiphy, struct hdd_config *pCfg)
10397{
10398 int i, j;
10399 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10400
10401 ENTER();
10402
10403 /* Now bind the underlying wlan device with wiphy */
10404 set_wiphy_dev(wiphy, dev);
10405
10406 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10407
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010408 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10409 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10410 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10411#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10412 | WIPHY_FLAG_4ADDR_STATION
10413#endif
10414 | WIPHY_FLAG_OFFCHAN_TX;
10415
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010416#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10417 wiphy->wowlan = &wowlan_support_cfg80211_init;
10418#else
10419 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10420 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10421 wiphy->wowlan.pattern_min_len = 1;
10422 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10423#endif
10424
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010425 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010426#ifdef FEATURE_WLAN_ESE
10427 || pCfg->isEseIniFeatureEnabled
10428#endif
10429 ) {
10430 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10431 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010432#ifdef FEATURE_WLAN_TDLS
10433 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10434 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10435#endif
10436
10437 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10438
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010439#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10440 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10441#endif
10442
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010443 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010444
10445#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010446 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010447#endif
10448
10449 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010450 * driver can still register regulatory callback and
10451 * it will get regulatory settings in wiphy->band[], but
10452 * driver need to determine what to do with both
10453 * regulatory settings
10454 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010455
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010456#if defined QCA_WIFI_FTM
10457}
10458#endif
10459
10460 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10461
10462 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10463
10464 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10465
Arun Khandavallifae92942016-08-01 13:31:08 +053010466 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10467 | BIT(NL80211_IFTYPE_ADHOC)
10468 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10469 | BIT(NL80211_IFTYPE_P2P_GO)
10470 | BIT(NL80211_IFTYPE_AP)
10471 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010472
Arun Khandavallifae92942016-08-01 13:31:08 +053010473 if (pCfg->advertiseConcurrentOperation) {
10474 if (pCfg->enableMCC) {
10475 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010476
Arun Khandavallifae92942016-08-01 13:31:08 +053010477 for (i = 0;
10478 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10479 i++) {
10480 if (!pCfg->allowMCCGODiffBI)
10481 wlan_hdd_iface_combination[i].
10482 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010483 }
10484 }
10485 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010486 ARRAY_SIZE(wlan_hdd_iface_combination);
10487 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010488 }
10489
10490 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010491 * on ini values
10492 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010493 if (!pCfg->ShortGI20MhzEnable) {
10494 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10495 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010496 }
10497
10498 if (!pCfg->ShortGI40MhzEnable) {
10499 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10500 }
10501
10502 if (!pCfg->nChannelBondingMode5GHz) {
10503 wlan_hdd_band_5_ghz.ht_cap.cap &=
10504 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10505 }
10506
Abhishek Singhf512bf32016-05-04 16:47:46 +053010507 /*
10508 * In case of static linked driver at the time of driver unload,
10509 * module exit doesn't happens. Module cleanup helps in cleaning
10510 * of static memory.
10511 * If driver load happens statically, at the time of driver unload,
10512 * wiphy flags don't get reset because of static memory.
10513 * It's better not to store channel in static memory.
10514 */
Dustin Browna30892e2016-10-12 17:28:36 -070010515 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10516 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010517 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010518 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010519 hdd_err("Not enough memory to allocate channels");
10520 return -ENOMEM;
10521 }
Dustin Browna30892e2016-10-12 17:28:36 -070010522 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010523 &hdd_channels_2_4_ghz[0],
10524 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010525 if ((hdd_is_5g_supported(pHddCtx)) &&
10526 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10527 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10528 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10529 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010530 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10531 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010532 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010533 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010534 hdd_err("Not enough memory to allocate channels");
10535 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010536 bands[NL80211_BAND_2GHZ]->channels);
10537 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010538 return -ENOMEM;
10539 }
Dustin Browna30892e2016-10-12 17:28:36 -070010540 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010541 &hdd_channels_5_ghz[0],
10542 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010543 }
10544
Dustin Browna30892e2016-10-12 17:28:36 -070010545 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010546
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010547 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010548 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010549
10550 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10551 struct ieee80211_supported_band *band = wiphy->bands[i];
10552
Dustin Browna30892e2016-10-12 17:28:36 -070010553 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010554 eCSR_BAND_5G == pCfg->nBandCapability) {
10555 /* 5G only */
10556#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10557 /* Enable social channels for P2P */
10558 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10559 (band->channels[j].center_freq))
10560 band->channels[j].flags &=
10561 ~IEEE80211_CHAN_DISABLED;
10562 else
10563#endif
10564 band->channels[j].flags |=
10565 IEEE80211_CHAN_DISABLED;
10566 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010567 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010568 eCSR_BAND_24 == pCfg->nBandCapability) {
10569 /* 2G only */
10570 band->channels[j].flags |=
10571 IEEE80211_CHAN_DISABLED;
10572 continue;
10573 }
10574 }
10575 }
10576 /*Initialise the supported cipher suite details */
10577 wiphy->cipher_suites = hdd_cipher_suites;
10578 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10579
10580 /*signal strength in mBm (100*dBm) */
10581 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10582 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10583
Anurag Chouhan6d760662016-02-20 16:05:43 +053010584 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010585 wiphy->n_vendor_commands =
10586 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10587 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10588
10589 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10590 wiphy->n_vendor_events =
10591 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10592 }
10593
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010594 if (pCfg->enableDFSMasterCap) {
10595 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10596 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010597
10598 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10599
10600#ifdef QCA_HT_2040_COEX
10601 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10602#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010603 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010604
10605#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10606 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10607 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10608 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10609 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10610#endif
10611
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010612 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010613 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010614
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010615 EXIT();
10616 return 0;
10617}
10618
Abhishek Singhf512bf32016-05-04 16:47:46 +053010619/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010620 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10621 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010622 *
10623 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010624 * memory allocated in wlan_hdd_cfg80211_init also
10625 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010626 *
10627 * Return: void
10628 */
10629void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10630{
10631 int i;
10632
Dustin Browna30892e2016-10-12 17:28:36 -070010633 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010634 if (NULL != wiphy->bands[i] &&
10635 (NULL != wiphy->bands[i]->channels)) {
10636 qdf_mem_free(wiphy->bands[i]->channels);
10637 wiphy->bands[i]->channels = NULL;
10638 }
10639 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010640
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010641 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010642}
10643
Yingying Tang80e15f32016-09-27 18:23:01 +080010644/**
10645 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10646 * @hdd_ctx: HDD context
10647 *
10648 * this function will update capabilities for supported bands
10649 *
10650 * Return: void
10651 */
10652static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10653{
10654 uint32_t val32;
10655 uint16_t val16;
10656 tSirMacHTCapabilityInfo *ht_cap_info;
10657 QDF_STATUS status;
10658
10659 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10660 if (QDF_STATUS_SUCCESS != status) {
10661 hdd_err("could not get HT capability info");
10662 val32 = 0;
10663 }
10664 val16 = (uint16_t)val32;
10665 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10666
10667 if (ht_cap_info->txSTBC == true) {
10668 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10669 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10670 IEEE80211_HT_CAP_TX_STBC;
10671 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10672 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10673 IEEE80211_HT_CAP_TX_STBC;
10674 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010675
10676 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10677 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10678 vht_cap.vht_supported = 0;
10679 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10680 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10681 vht_cap.vht_supported = 0;
10682 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10683 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010684}
10685
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010686/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010687 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010688 * initialization. In wlan_hdd_cfg80211_init, only the
10689 * default values will be initialized. The final initialization
10690 * of all required members can be done here.
10691 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010692void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010693{
Yingying Tang80e15f32016-09-27 18:23:01 +080010694 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10695
10696 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010697}
10698
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010699/**
10700 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10701 * @cfg: hdd cfg
10702 *
10703 * this function update 11n mode in hdd cfg
10704 *
10705 * Return: void
10706 */
10707void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10708{
10709 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010710 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010711 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010712 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010713 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10714 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10715 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10716 cfg->sap_p2p_11ac_override = 0;
10717 }
10718 }
10719}
10720
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010721/* In this function we are registering wiphy. */
10722int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10723{
10724 ENTER();
10725 /* Register our wiphy dev with cfg80211 */
10726 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010727 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010728 return -EIO;
10729 }
10730
10731 EXIT();
10732 return 0;
10733}
10734
10735/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010736 * HDD function to update wiphy capability based on target offload status.
10737 *
10738 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10739 * capability even before downloading firmware to the target. In discrete
10740 * case, host will get know certain offload capability (say sched_scan
10741 * caps) only after downloading firmware to the target and target boots up.
10742 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10743 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010744 */
10745void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10746{
10747#ifdef FEATURE_WLAN_SCAN_PNO
10748 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10749 struct hdd_config *pCfg = pHddCtx->config;
10750
10751 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10752 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010753 * have PNO support.
10754 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010755 if (!pCfg->PnoOffload) {
10756 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10757 wiphy->max_sched_scan_ssids = 0;
10758 wiphy->max_match_sets = 0;
10759 wiphy->max_sched_scan_ie_len = 0;
10760 }
10761#endif
10762}
10763
10764/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070010765#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
10766
Wu Gao84d120c2017-03-24 18:46:00 +080010767void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10768{
10769 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10770 /* Register for all P2P action, public action etc frames */
10771 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10772
10773 ENTER();
10774
10775 /* Register frame indication call back */
10776 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10777
10778 /* Register for p2p ack indication */
10779 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10780
10781 /* Right now we are registering these frame when driver is getting
10782 * initialized. Once we will move to 2.6.37 kernel, in which we have
10783 * frame register ops, we will move this code as a part of that
10784 */
10785
10786 /* GAS Initial Request */
10787 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10788 (uint8_t *) GAS_INITIAL_REQ,
10789 GAS_INITIAL_REQ_SIZE);
10790
10791 /* GAS Initial Response */
10792 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10793 (uint8_t *) GAS_INITIAL_RSP,
10794 GAS_INITIAL_RSP_SIZE);
10795
10796 /* GAS Comeback Request */
10797 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10798 (uint8_t *) GAS_COMEBACK_REQ,
10799 GAS_COMEBACK_REQ_SIZE);
10800
10801 /* GAS Comeback Response */
10802 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10803 (uint8_t *) GAS_COMEBACK_RSP,
10804 GAS_COMEBACK_RSP_SIZE);
10805
10806 /* WNM BSS Transition Request frame */
10807 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10808 (uint8_t *) WNM_BSS_ACTION_FRAME,
10809 WNM_BSS_ACTION_FRAME_SIZE);
10810
10811 /* WNM-Notification */
10812 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10813 (uint8_t *) WNM_NOTIFICATION_FRAME,
10814 WNM_NOTIFICATION_FRAME_SIZE);
10815}
10816#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010817void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10818{
10819 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10820 /* Register for all P2P action, public action etc frames */
10821 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10822
10823 ENTER();
10824
Abhishek Singh7996eb72015-12-30 17:24:02 +053010825 /* Register frame indication call back */
10826 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10827
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010828 /* Register for p2p ack indication */
10829 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10830
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010831 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010832 * initialized. Once we will move to 2.6.37 kernel, in which we have
10833 * frame register ops, we will move this code as a part of that
10834 */
10835
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010836 /* GAS Initial Request */
10837 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10838 (uint8_t *) GAS_INITIAL_REQ,
10839 GAS_INITIAL_REQ_SIZE);
10840
10841 /* GAS Initial Response */
10842 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10843 (uint8_t *) GAS_INITIAL_RSP,
10844 GAS_INITIAL_RSP_SIZE);
10845
10846 /* GAS Comeback Request */
10847 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10848 (uint8_t *) GAS_COMEBACK_REQ,
10849 GAS_COMEBACK_REQ_SIZE);
10850
10851 /* GAS Comeback Response */
10852 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10853 (uint8_t *) GAS_COMEBACK_RSP,
10854 GAS_COMEBACK_RSP_SIZE);
10855
10856 /* P2P Public Action */
10857 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10858 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10859 P2P_PUBLIC_ACTION_FRAME_SIZE);
10860
10861 /* P2P Action */
10862 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10863 (uint8_t *) P2P_ACTION_FRAME,
10864 P2P_ACTION_FRAME_SIZE);
10865
10866 /* WNM BSS Transition Request frame */
10867 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10868 (uint8_t *) WNM_BSS_ACTION_FRAME,
10869 WNM_BSS_ACTION_FRAME_SIZE);
10870
10871 /* WNM-Notification */
10872 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10873 (uint8_t *) WNM_NOTIFICATION_FRAME,
10874 WNM_NOTIFICATION_FRAME_SIZE);
10875}
Wu Gao84d120c2017-03-24 18:46:00 +080010876#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010877
10878void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10879{
10880 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10881 /* Register for all P2P action, public action etc frames */
10882 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10883
10884 ENTER();
10885
10886 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010887 * initialized. Once we will move to 2.6.37 kernel, in which we have
10888 * frame register ops, we will move this code as a part of that
10889 */
10890
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010891 /* GAS Initial Request */
10892
10893 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10894 (uint8_t *) GAS_INITIAL_REQ,
10895 GAS_INITIAL_REQ_SIZE);
10896
10897 /* GAS Initial Response */
10898 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10899 (uint8_t *) GAS_INITIAL_RSP,
10900 GAS_INITIAL_RSP_SIZE);
10901
10902 /* GAS Comeback Request */
10903 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10904 (uint8_t *) GAS_COMEBACK_REQ,
10905 GAS_COMEBACK_REQ_SIZE);
10906
10907 /* GAS Comeback Response */
10908 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10909 (uint8_t *) GAS_COMEBACK_RSP,
10910 GAS_COMEBACK_RSP_SIZE);
10911
10912 /* P2P Public Action */
10913 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10914 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10915 P2P_PUBLIC_ACTION_FRAME_SIZE);
10916
10917 /* P2P Action */
10918 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10919 (uint8_t *) P2P_ACTION_FRAME,
10920 P2P_ACTION_FRAME_SIZE);
10921
10922 /* WNM-Notification */
10923 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10924 (uint8_t *) WNM_NOTIFICATION_FRAME,
10925 WNM_NOTIFICATION_FRAME_SIZE);
10926}
10927
10928#ifdef FEATURE_WLAN_WAPI
10929void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10930 const uint8_t *mac_addr, const uint8_t *key,
10931 int key_Len)
10932{
10933 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10934 tCsrRoamSetKey setKey;
10935 bool isConnected = true;
10936 int status = 0;
10937 uint32_t roamId = 0xFF;
10938 uint8_t *pKeyPtr = NULL;
10939 int n = 0;
10940
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010941 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010942 hdd_device_mode_to_string(pAdapter->device_mode),
10943 pAdapter->device_mode);
10944
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010945 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010946 setKey.keyId = key_index; /* Store Key ID */
10947 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10948 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10949 setKey.paeRole = 0; /* the PAE role */
10950 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010951 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010952 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010953 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010954 }
10955 setKey.keyLength = key_Len;
10956 pKeyPtr = setKey.Key;
10957 memcpy(pKeyPtr, key, key_Len);
10958
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010959 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010961 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070010962 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010963
10964 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10965 if (isConnected) {
10966 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10967 pAdapter->sessionId, &setKey, &roamId);
10968 }
10969 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010970 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010971 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10972 }
10973}
10974#endif /* FEATURE_WLAN_WAPI */
10975
10976uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10977 uint8_t eid)
10978{
10979 int left = length;
10980 uint8_t *ptr = (uint8_t *)ies_ptr;
10981 uint8_t elem_id, elem_len;
10982
10983 while (left >= 2) {
10984 elem_id = ptr[0];
10985 elem_len = ptr[1];
10986 left -= 2;
10987 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010988 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010989 eid, elem_len, left);
10990 return NULL;
10991 }
10992 if (elem_id == eid) {
10993 return ptr;
10994 }
10995
10996 left -= elem_len;
10997 ptr += (elem_len + 2);
10998 }
10999 return NULL;
11000}
11001
11002/*
11003 * FUNCTION: wlan_hdd_validate_operation_channel
11004 * called by wlan_hdd_cfg80211_start_bss() and
11005 * wlan_hdd_set_channel()
11006 * This function validates whether given channel is part of valid
11007 * channel list.
11008 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011009QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011010 int channel)
11011{
11012
11013 uint32_t num_ch = 0;
11014 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
11015 u32 indx = 0;
11016 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11017 uint8_t fValidChannel = false, count = 0;
11018 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
11019
11020 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
11021
11022 if (hdd_pConfig_ini->sapAllowAllChannel) {
11023 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080011024 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070011025 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011026 fValidChannel = true;
11027 break;
11028 }
11029 }
11030 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011031 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011032 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011033 }
11034 } else {
11035 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
11036 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011037 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011038 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011039 }
11040 for (indx = 0; indx < num_ch; indx++) {
11041 if (channel == valid_ch[indx]) {
11042 break;
11043 }
11044 }
11045
11046 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011047 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011048 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011049 }
11050 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011051 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011052
11053}
11054
11055#ifdef DHCP_SERVER_OFFLOAD
11056static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
11057{
11058 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
11059 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
11060 uint8_t numEntries = 0;
11061 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
11062 uint8_t num;
11063 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011064 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011065 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070011066 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011067 return;
11068 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011069 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
11070 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
11071 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
11072 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
11073 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
11074 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011075 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011076 goto end;
11077 }
11078 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011079 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011080 goto end;
11081 }
11082 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011083 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011084 goto end;
11085 }
11086 for (num = 0; num < numEntries; num++) {
11087 temp = srv_ip[num];
11088 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
11089 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011090 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011091 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011092 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011093 goto end;
11094 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011095 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011096end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011097 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011098 return;
11099}
11100#endif /* DHCP_SERVER_OFFLOAD */
11101
11102static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11103 struct net_device *dev,
11104 struct bss_parameters *params)
11105{
11106 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11107 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11108 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011109 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011110
11111 ENTER();
11112
Anurag Chouhan6d760662016-02-20 16:05:43 +053011113 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011114 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011115 return -EINVAL;
11116 }
11117
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011118 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11119 hdd_err("invalid session id: %d", pAdapter->sessionId);
11120 return -EINVAL;
11121 }
11122
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011123 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011124 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
11125 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011126 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011127 hdd_device_mode_to_string(pAdapter->device_mode),
11128 pAdapter->device_mode, params->ap_isolate);
11129
11130 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11131 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011132 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011133 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011134
Krunal Sonib4326f22016-03-10 13:05:51 -080011135 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
11136 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011137 return -EOPNOTSUPP;
11138 }
11139
11140 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011141 * want to update this parameter
11142 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011143 if (-1 != params->ap_isolate) {
11144 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
11145 !!params->ap_isolate;
11146
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011147 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011148 pAdapter->sessionId,
11149 pAdapter->sessionCtx.
11150 ap.
11151 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011152 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011153 ret = -EINVAL;
11154 }
11155 }
11156
11157 EXIT();
11158 return ret;
11159}
11160
Krunal Soni8c37e322016-02-03 16:08:37 -080011161/**
11162 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
11163 * @ndev: pointer to net device provided by supplicant
11164 * @type: type of the interface, upper layer wanted to change
11165 *
11166 * Upper layer provides the new interface mode that needs to be changed
11167 * for given net device
11168 *
11169 * Return: success or failure in terms of integer value
11170 */
11171static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011172 enum nl80211_iftype type)
11173{
Krunal Soni8c37e322016-02-03 16:08:37 -080011174 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11175 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11176 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011177 hdd_wext_state_t *wext;
11178 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011179 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011180
11181 ENTER();
11182
Krunal Soni8c37e322016-02-03 16:08:37 -080011183 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011184 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011185 return 0;
11186 }
11187
11188 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011189 hdd_stop_adapter(hdd_ctx, adapter, true);
11190 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011191 wdev->iftype = type;
11192 /*Check for sub-string p2p to confirm its a p2p interface */
11193 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011194 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011195 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011196 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011197 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011198 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011199 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011200 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011201 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011202 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011203 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011204 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11205 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011206 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11207 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011208 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011209 adapter->scan_info.scanAddIE.length;
11210 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011211 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011212 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11213 wext->roamProfile.phyMode =
11214 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11215 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011216 EXIT();
11217 return status;
11218}
11219
11220static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11221 struct net_device *dev,
11222 struct bss_parameters *params)
11223{
11224 int ret;
11225
11226 cds_ssr_protect(__func__);
11227 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11228 cds_ssr_unprotect(__func__);
11229
11230 return ret;
11231}
11232
11233/* FUNCTION: wlan_hdd_change_country_code_cd
11234 * to wait for contry code completion
11235 */
11236void *wlan_hdd_change_country_code_cb(void *pAdapter)
11237{
11238 hdd_adapter_t *call_back_pAdapter = pAdapter;
11239 complete(&call_back_pAdapter->change_country_code);
11240 return NULL;
11241}
11242
Rajeev Kumar98edb772016-01-19 12:42:19 -080011243/**
11244 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11245 * @wiphy: Pointer to the wiphy structure
11246 * @ndev: Pointer to the net device
11247 * @type: Interface type
11248 * @flags: Flags for change interface
11249 * @params: Pointer to change interface parameters
11250 *
11251 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011252 */
11253static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11254 struct net_device *ndev,
11255 enum nl80211_iftype type,
11256 u32 *flags,
11257 struct vif_params *params)
11258{
11259 struct wireless_dev *wdev;
11260 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11261 hdd_context_t *pHddCtx;
11262 tCsrRoamProfile *pRoamProfile = NULL;
11263 eCsrRoamBssType LastBSSType;
11264 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011265 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011266 int status;
11267
11268 ENTER();
11269
Anurag Chouhan6d760662016-02-20 16:05:43 +053011270 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011271 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011272 return -EINVAL;
11273 }
11274
11275 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11276 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011277 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011278 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011279
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011280 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011281 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11282 pAdapter->sessionId, type));
11283
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011284 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011285 pAdapter->device_mode, type);
11286
Arun Khandavallifae92942016-08-01 13:31:08 +053011287 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11288 if (status) {
11289 hdd_err("Failed to start modules");
11290 return -EINVAL;
11291 }
11292
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011293 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011294 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11295 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011296 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011297 return -EINVAL;
11298 }
11299
11300 pConfig = pHddCtx->config;
11301 wdev = ndev->ieee80211_ptr;
11302
11303 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011304 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11305 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011306
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011307 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011308 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011309 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11310 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11311 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11312 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011313 hdd_wext_state_t *pWextState =
11314 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11315
11316 pRoamProfile = &pWextState->roamProfile;
11317 LastBSSType = pRoamProfile->BSSType;
11318
11319 switch (type) {
11320 case NL80211_IFTYPE_STATION:
11321 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011322 case NL80211_IFTYPE_ADHOC:
11323 if (type == NL80211_IFTYPE_ADHOC) {
11324 wlan_hdd_tdls_exit(pAdapter);
11325 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011326 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011327 }
11328 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11329 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011330 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011331 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011332 if (hdd_start_adapter(pAdapter)) {
11333 hdd_err("Failed to start adapter :%d",
11334 pAdapter->device_mode);
11335 return -EINVAL;
11336 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011337 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011338 case NL80211_IFTYPE_AP:
11339 case NL80211_IFTYPE_P2P_GO:
11340 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011341 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011342 (type ==
11343 NL80211_IFTYPE_AP) ? "SoftAP" :
11344 "P2pGo");
11345
11346 /* Cancel any remain on channel for GO mode */
11347 if (NL80211_IFTYPE_P2P_GO == type) {
11348 wlan_hdd_cancel_existing_remain_on_channel
11349 (pAdapter);
11350 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011351
Arun Khandavallifae92942016-08-01 13:31:08 +053011352 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011353 /* De-init the adapter */
11354 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11355 memset(&pAdapter->sessionCtx, 0,
11356 sizeof(pAdapter->sessionCtx));
11357 pAdapter->device_mode =
11358 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011359 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11360 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011361
11362 /*
11363 * Fw will take care incase of concurrency
11364 */
11365
Krunal Sonib4326f22016-03-10 13:05:51 -080011366 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011367 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011368 /* To meet Android requirements create
11369 * a randomized MAC address of the
11370 * form 02:1A:11:Fx:xx:xx
11371 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011372 get_random_bytes(&ndev->dev_addr[3], 3);
11373 ndev->dev_addr[0] = 0x02;
11374 ndev->dev_addr[1] = 0x1A;
11375 ndev->dev_addr[2] = 0x11;
11376 ndev->dev_addr[3] |= 0xF0;
11377 memcpy(pAdapter->macAddressCurrent.
11378 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011379 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011380 pr_info("wlan: Generated HotSpot BSSID "
11381 MAC_ADDRESS_STR "\n",
11382 MAC_ADDR_ARRAY(ndev->dev_addr));
11383 }
11384
11385 hdd_set_ap_ops(pAdapter->dev);
11386
Arun Khandavallifae92942016-08-01 13:31:08 +053011387 if (hdd_start_adapter(pAdapter)) {
11388 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011389 return -EINVAL;
11390 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011391 /* Interface type changed update in wiphy structure */
11392 if (wdev) {
11393 wdev->iftype = type;
11394 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011395 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011396 return -EINVAL;
11397 }
11398 goto done;
11399 }
11400
11401 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011402 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011403 return -EOPNOTSUPP;
11404 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011405 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11406 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011407 switch (type) {
11408 case NL80211_IFTYPE_STATION:
11409 case NL80211_IFTYPE_P2P_CLIENT:
11410 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011411 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11412 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011413 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011414 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011415 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011416 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011417 pAdapter->device_mode);
11418 return -EINVAL;
11419 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011420 goto done;
11421
11422 case NL80211_IFTYPE_AP:
11423 case NL80211_IFTYPE_P2P_GO:
11424 wdev->iftype = type;
11425 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011426 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011427 goto done;
11428
11429 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011430 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011431 return -EOPNOTSUPP;
11432 }
11433 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011434 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011435 pAdapter->device_mode);
11436 return -EOPNOTSUPP;
11437 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011438done:
11439 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011440 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11441 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011442
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011443 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011444
11445 EXIT();
11446 return 0;
11447}
11448
Rajeev Kumar98edb772016-01-19 12:42:19 -080011449/**
11450 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11451 * @wiphy: Pointer to the wiphy structure
11452 * @ndev: Pointer to the net device
11453 * @type: Interface type
11454 * @flags: Flags for change interface
11455 * @params: Pointer to change interface parameters
11456 *
11457 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011458 */
11459static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11460 struct net_device *ndev,
11461 enum nl80211_iftype type,
11462 u32 *flags,
11463 struct vif_params *params)
11464{
11465 int ret;
11466
11467 cds_ssr_protect(__func__);
11468 ret =
11469 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11470 cds_ssr_unprotect(__func__);
11471
11472 return ret;
11473}
11474
Frank Liud4b2fa02017-03-29 11:46:48 +080011475#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011476static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11477 int index, uint8_t match)
11478{
11479 int i;
11480 for (i = 0; i < index; i++) {
11481 if (arr[i] == match)
11482 return true;
11483 }
11484 return false;
11485}
11486#endif
11487
11488/**
11489 * __wlan_hdd_change_station() - change station
11490 * @wiphy: Pointer to the wiphy structure
11491 * @dev: Pointer to the net device.
11492 * @mac: bssid
11493 * @params: Pointer to station parameters
11494 *
11495 * Return: 0 for success, error number on failure.
11496 */
11497#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11498static int __wlan_hdd_change_station(struct wiphy *wiphy,
11499 struct net_device *dev,
11500 const uint8_t *mac,
11501 struct station_parameters *params)
11502#else
11503static int __wlan_hdd_change_station(struct wiphy *wiphy,
11504 struct net_device *dev,
11505 uint8_t *mac,
11506 struct station_parameters *params)
11507#endif
11508{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011509 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011510 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11511 hdd_context_t *pHddCtx;
11512 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011513 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011514#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011515 tCsrStaParams StaParams = { 0 };
11516 uint8_t isBufSta = 0;
11517 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011518 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011519#endif
11520 int ret;
11521
11522 ENTER();
11523
Anurag Chouhan6d760662016-02-20 16:05:43 +053011524 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011525 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011526 return -EINVAL;
11527 }
11528
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011529 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011530 TRACE_CODE_HDD_CHANGE_STATION,
11531 pAdapter->sessionId, params->listen_interval));
11532
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011533 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11534 hdd_err("invalid session id: %d", pAdapter->sessionId);
11535 return -EINVAL;
11536 }
11537
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011538 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11539 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011540 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011541 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011542
11543 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11544
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011545 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011546
Krunal Sonib4326f22016-03-10 13:05:51 -080011547 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11548 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011549 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11550 status =
11551 hdd_softap_change_sta_state(pAdapter,
11552 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011553 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011554
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011555 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011556 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011557 return -EINVAL;
11558 }
11559 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011560 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11561 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011562 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011563#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11564 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11565 dev, mac, params);
11566#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011567
11568 if (cds_is_sub_20_mhz_enabled()) {
11569 hdd_err("TDLS not allowed with sub 20 MHz");
11570 return -EINVAL;
11571 }
11572
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011573 StaParams.capability = params->capability;
11574 StaParams.uapsd_queues = params->uapsd_queues;
11575 StaParams.max_sp = params->max_sp;
11576
11577 /* Convert (first channel , number of channels) tuple to
11578 * the total list of channels. This goes with the assumption
11579 * that if the first channel is < 14, then the next channels
11580 * are an incremental of 1 else an incremental of 4 till the number
11581 * of channels.
11582 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011583 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011584 if (0 != params->supported_channels_len) {
11585 int i = 0, j = 0, k = 0, no_of_channels = 0;
11586 int num_unique_channels;
11587 int next;
11588 for (i = 0;
11589 i < params->supported_channels_len
11590 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11591 int wifi_chan_index;
11592 if (!wlan_hdd_is_duplicate_channel
11593 (StaParams.supported_channels, j,
11594 params->supported_channels[i])) {
11595 StaParams.
11596 supported_channels[j] =
11597 params->
11598 supported_channels[i];
11599 } else {
11600 continue;
11601 }
11602 wifi_chan_index =
11603 ((StaParams.supported_channels[j] <=
11604 HDD_CHANNEL_14) ? 1 : 4);
11605 no_of_channels =
11606 params->supported_channels[i + 1];
11607
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011608 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 -080011609 StaParams.
11610 supported_channels[j],
11611 wifi_chan_index,
11612 no_of_channels);
11613 for (k = 1; k <= no_of_channels &&
11614 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11615 k++) {
11616 next =
11617 StaParams.
11618 supported_channels[j] +
11619 wifi_chan_index;
11620 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11621 StaParams.
11622 supported_channels[j
11623 +
11624 1]
11625 = next;
11626 } else {
11627 continue;
11628 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011629 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011630 j + 1,
11631 StaParams.
11632 supported_channels[j +
11633 1]);
11634 j += 1;
11635 }
11636 }
11637 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011638 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011639 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011640 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641 StaParams.
11642 supported_channels[i]);
11643 }
11644 if (MAX_CHANNEL < num_unique_channels)
11645 num_unique_channels = MAX_CHANNEL;
11646 StaParams.supported_channels_len =
11647 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011648 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011649 StaParams.supported_channels_len);
11650 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011651 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011652 params->supported_oper_classes,
11653 params->supported_oper_classes_len);
11654 StaParams.supported_oper_classes_len =
11655 params->supported_oper_classes_len;
11656
11657 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011658 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011659 params->ext_capab,
11660 sizeof(StaParams.extn_capability));
11661
11662 if (NULL != params->ht_capa) {
11663 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011664 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011665 sizeof(tSirHTCap));
11666 }
11667
11668 StaParams.supported_rates_len =
11669 params->supported_rates_len;
11670
11671 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11672 * The supported_rates array , for all the structures propogating till Add Sta
11673 * to the firmware has to be modified , if the supplicant (ieee80211) is
11674 * modified to send more rates.
11675 */
11676
11677 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11678 */
11679 if (StaParams.supported_rates_len >
11680 SIR_MAC_MAX_SUPP_RATES)
11681 StaParams.supported_rates_len =
11682 SIR_MAC_MAX_SUPP_RATES;
11683
11684 if (0 != StaParams.supported_rates_len) {
11685 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011686 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011687 params->supported_rates,
11688 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011689 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011690 StaParams.supported_rates_len);
11691 for (i = 0; i < StaParams.supported_rates_len;
11692 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011693 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011694 StaParams.supported_rates[i]);
11695 }
11696
11697 if (NULL != params->vht_capa) {
11698 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011699 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011700 params->vht_capa,
11701 sizeof(tSirVHTCap));
11702 }
11703
11704 if (0 != params->ext_capab_len) {
11705 /*Define A Macro : TODO Sunil */
11706 if ((1 << 4) & StaParams.extn_capability[3]) {
11707 isBufSta = 1;
11708 }
11709 /* TDLS Channel Switching Support */
11710 if ((1 << 6) & StaParams.extn_capability[3]) {
11711 isOffChannelSupported = 1;
11712 }
11713 }
11714
Nitesh Shah99934ac2016-09-05 15:54:08 +053011715 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011716 (params->ht_capa || params->vht_capa ||
11717 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011718 is_qos_wmm_sta = true;
11719
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011720 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011721 " is_qos_wmm_sta= %d HTcapPresent = %d",
11722 __func__, is_qos_wmm_sta,
11723 StaParams.htcap_present);
11724
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011725 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011726 &StaParams,
11727 isBufSta,
11728 isOffChannelSupported,
11729 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011730 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011731 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011732 return -EINVAL;
11733 }
11734
11735 status =
11736 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11737 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011738 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011739 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011740 return -EINVAL;
11741 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011742#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080011743 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011744 }
11745 EXIT();
11746 return ret;
11747}
11748
11749/**
11750 * wlan_hdd_change_station() - cfg80211 change station handler function
11751 * @wiphy: Pointer to the wiphy structure
11752 * @dev: Pointer to the net device.
11753 * @mac: bssid
11754 * @params: Pointer to station parameters
11755 *
11756 * This is the cfg80211 change station handler function which invokes
11757 * the internal function @__wlan_hdd_change_station with
11758 * SSR protection.
11759 *
11760 * Return: 0 for success, error number on failure.
11761 */
11762#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11763static int wlan_hdd_change_station(struct wiphy *wiphy,
11764 struct net_device *dev,
11765 const u8 *mac,
11766 struct station_parameters *params)
11767#else
11768static int wlan_hdd_change_station(struct wiphy *wiphy,
11769 struct net_device *dev,
11770 u8 *mac,
11771 struct station_parameters *params)
11772#endif
11773{
11774 int ret;
11775
11776 cds_ssr_protect(__func__);
11777 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11778 cds_ssr_unprotect(__func__);
11779
11780 return ret;
11781}
11782
11783/*
11784 * FUNCTION: __wlan_hdd_cfg80211_add_key
11785 * This function is used to initialize the key information
11786 */
11787static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11788 struct net_device *ndev,
11789 u8 key_index, bool pairwise,
11790 const u8 *mac_addr,
11791 struct key_params *params)
11792{
11793 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11794 tCsrRoamSetKey setKey;
11795 int status;
11796 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011797 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011798 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011799 hdd_context_t *pHddCtx;
11800 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11801
11802 ENTER();
11803
Anurag Chouhan6d760662016-02-20 16:05:43 +053011804 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011805 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011806 return -EINVAL;
11807 }
11808
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011809 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011810 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011811 return -EINVAL;
11812 }
11813
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011814 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011815 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11816 pAdapter->sessionId, params->key_len));
11817 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11818 status = wlan_hdd_validate_context(pHddCtx);
11819
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011820 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011821 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011822
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011823 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011824 hdd_device_mode_to_string(pAdapter->device_mode),
11825 pAdapter->device_mode);
11826
11827 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011828 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011829
11830 return -EINVAL;
11831 }
11832
11833 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011834 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011835
11836 return -EINVAL;
11837 }
11838
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011839 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011840
11841 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011842 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011843 setKey.keyId = key_index;
11844 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011845 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011846
11847 switch (params->cipher) {
11848 case WLAN_CIPHER_SUITE_WEP40:
11849 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11850 break;
11851
11852 case WLAN_CIPHER_SUITE_WEP104:
11853 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11854 break;
11855
11856 case WLAN_CIPHER_SUITE_TKIP:
11857 {
11858 u8 *pKey = &setKey.Key[0];
11859 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11860
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011861 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011862
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011863 /* Supplicant sends the 32bytes key in this order
11864 *
11865 * |--------------|----------|----------|
11866 * | Tk1 |TX-MIC | RX Mic |
11867 * |--------------|----------|----------|
11868 * <---16bytes---><--8bytes--><--8bytes-->
11869 *
11870 * Sme expects the 32 bytes key to be in the below order
11871 *
11872 * |--------------|----------|----------|
11873 * | Tk1 |RX-MIC | TX Mic |
11874 * |--------------|----------|----------|
11875 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011876 */
11877 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011878 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011879
11880 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011881 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011882
11883 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011884 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011885
11886 break;
11887 }
11888
11889 case WLAN_CIPHER_SUITE_CCMP:
11890 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11891 break;
11892
11893#ifdef FEATURE_WLAN_WAPI
11894 case WLAN_CIPHER_SUITE_SMS4:
11895 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011896 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011897 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11898 mac_addr, params->key,
11899 params->key_len);
11900 return 0;
11901 }
11902#endif
11903
11904#ifdef FEATURE_WLAN_ESE
11905 case WLAN_CIPHER_SUITE_KRK:
11906 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11907 break;
11908#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11909 case WLAN_CIPHER_SUITE_BTK:
11910 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11911 break;
11912#endif
11913#endif
11914
11915#ifdef WLAN_FEATURE_11W
11916 case WLAN_CIPHER_SUITE_AES_CMAC:
11917 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11918 break;
11919#endif
11920
11921 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011922 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011923 return -EOPNOTSUPP;
11924 }
11925
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011926 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011927
11928 if (!pairwise) {
11929 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011930 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011931 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011932 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011933 } else {
11934 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011935 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011936 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011937 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011938 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011939 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011940 /* if a key is already installed, block all subsequent ones */
11941 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011942 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011943 return 0;
11944 }
11945
11946 setKey.keyDirection = eSIR_TX_RX;
11947 /*Set the group key */
11948 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11949 pAdapter->sessionId, &setKey, &roamId);
11950
11951 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011952 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011953 return -EINVAL;
11954 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011955 /* Save the keys here and call sme_roam_set_key for setting
11956 * the PTK after peer joins the IBSS network
11957 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011958 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011959 &setKey, sizeof(tCsrRoamSetKey));
11960
11961 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11962 return status;
11963 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011964 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11965 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011966 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11967 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011968 status = wlansap_set_key_sta(
11969 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011970 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011971 hdd_err("wlansap_set_key_sta failed status: %d",
11972 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011973 }
11974 }
11975
11976 /* Save the key in ap ctx for use on START_BASS and restart */
11977 if (pairwise ||
11978 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11979 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011980 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011981 sizeof(tCsrRoamSetKey));
11982 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011983 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011984 sizeof(tCsrRoamSetKey));
11985
Krunal Sonib4326f22016-03-10 13:05:51 -080011986 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11987 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011988 hdd_wext_state_t *pWextState =
11989 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11990 hdd_station_ctx_t *pHddStaCtx =
11991 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11992
11993 if (!pairwise) {
11994 /* set group key */
11995 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011996 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011997 __func__, __LINE__);
11998 hdd_perform_roam_set_key_complete(pAdapter);
11999 }
12000 }
12001
12002 pWextState->roamProfile.Keys.KeyLength[key_index] =
12003 (u8) params->key_len;
12004
12005 pWextState->roamProfile.Keys.defaultIndex = key_index;
12006
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012007 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012008 KeyMaterial[key_index][0], params->key,
12009 params->key_len);
12010
12011 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
12012
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012013 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012014 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12015 setKey.keyDirection);
12016
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012017 /* The supplicant may attempt to set the PTK once
12018 * pre-authentication is done. Save the key in the
12019 * UMAC and include it in the ADD BSS request
12020 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012021 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012022 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012023 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012024 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012025 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012026 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012027 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012028 return -EINVAL;
12029 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012030
12031 /* issue set key request to SME */
12032 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12033 pAdapter->sessionId, &setKey, &roamId);
12034
12035 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012036 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012037 pHddStaCtx->roam_info.roamingState =
12038 HDD_ROAM_STATE_NONE;
12039 return -EINVAL;
12040 }
12041
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012042 /* in case of IBSS as there was no information
12043 * available about WEP keys during IBSS join, group
12044 * key intialized with NULL key, so re-initialize
12045 * group key with correct value
12046 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012047 if ((eCSR_BSS_TYPE_START_IBSS ==
12048 pWextState->roamProfile.BSSType)
12049 &&
12050 !((IW_AUTH_KEY_MGMT_802_1X ==
12051 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
12052 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
12053 pHddStaCtx->conn_info.authType)
12054 )
12055 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
12056 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
12057 )
12058 ) {
12059 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012060 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012061
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012062 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012063 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12064 setKey.keyDirection);
12065
12066 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12067 pAdapter->sessionId, &setKey,
12068 &roamId);
12069
12070 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012071 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012072 pHddStaCtx->roam_info.roamingState =
12073 HDD_ROAM_STATE_NONE;
12074 return -EINVAL;
12075 }
12076 }
12077 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012078 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012079 return 0;
12080}
12081
12082static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12083 struct net_device *ndev,
12084 u8 key_index, bool pairwise,
12085 const u8 *mac_addr,
12086 struct key_params *params)
12087{
12088 int ret;
12089 cds_ssr_protect(__func__);
12090 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
12091 mac_addr, params);
12092 cds_ssr_unprotect(__func__);
12093
12094 return ret;
12095}
12096
12097/*
12098 * FUNCTION: __wlan_hdd_cfg80211_get_key
12099 * This function is used to get the key information
12100 */
12101static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12102 struct net_device *ndev,
12103 u8 key_index, bool pairwise,
12104 const u8 *mac_addr, void *cookie,
12105 void (*callback)(void *cookie,
12106 struct key_params *)
12107 )
12108{
12109 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12110 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12111 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
12112 struct key_params params;
12113
12114 ENTER();
12115
Anurag Chouhan6d760662016-02-20 16:05:43 +053012116 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012117 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012118 return -EINVAL;
12119 }
12120
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012121 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012122 hdd_device_mode_to_string(pAdapter->device_mode),
12123 pAdapter->device_mode);
12124
12125 memset(&params, 0, sizeof(params));
12126
12127 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012128 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012129 return -EINVAL;
12130 }
12131
12132 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
12133 case eCSR_ENCRYPT_TYPE_NONE:
12134 params.cipher = IW_AUTH_CIPHER_NONE;
12135 break;
12136
12137 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
12138 case eCSR_ENCRYPT_TYPE_WEP40:
12139 params.cipher = WLAN_CIPHER_SUITE_WEP40;
12140 break;
12141
12142 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
12143 case eCSR_ENCRYPT_TYPE_WEP104:
12144 params.cipher = WLAN_CIPHER_SUITE_WEP104;
12145 break;
12146
12147 case eCSR_ENCRYPT_TYPE_TKIP:
12148 params.cipher = WLAN_CIPHER_SUITE_TKIP;
12149 break;
12150
12151 case eCSR_ENCRYPT_TYPE_AES:
12152 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
12153 break;
12154
12155 default:
12156 params.cipher = IW_AUTH_CIPHER_NONE;
12157 break;
12158 }
12159
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012160 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012161 TRACE_CODE_HDD_CFG80211_GET_KEY,
12162 pAdapter->sessionId, params.cipher));
12163
12164 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12165 params.seq_len = 0;
12166 params.seq = NULL;
12167 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12168 callback(cookie, &params);
12169
12170 EXIT();
12171 return 0;
12172}
12173
12174static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12175 struct net_device *ndev,
12176 u8 key_index, bool pairwise,
12177 const u8 *mac_addr, void *cookie,
12178 void (*callback)(void *cookie,
12179 struct key_params *)
12180 )
12181{
12182 int ret;
12183
12184 cds_ssr_protect(__func__);
12185 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12186 mac_addr, cookie, callback);
12187 cds_ssr_unprotect(__func__);
12188
12189 return ret;
12190}
12191
12192/**
12193 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12194 * @wiphy: wiphy interface context
12195 * @ndev: pointer to net device
12196 * @key_index: Key index used in 802.11 frames
12197 * @unicast: true if it is unicast key
12198 * @multicast: true if it is multicast key
12199 *
12200 * This function is required for cfg80211_ops API.
12201 * It is used to delete the key information
12202 * Underlying hardware implementation does not have API to delete the
12203 * encryption key. It is automatically deleted when the peer is
12204 * removed. Hence this function currently does nothing.
12205 * Future implementation may interprete delete key operation to
12206 * replacing the key with a random junk value, effectively making it
12207 * useless.
12208 *
12209 * Return: status code, always 0.
12210 */
12211
12212static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12213 struct net_device *ndev,
12214 u8 key_index,
12215 bool pairwise, const u8 *mac_addr)
12216{
12217 EXIT();
12218 return 0;
12219}
12220
12221/**
12222 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12223 * @wiphy: Pointer to wiphy structure.
12224 * @dev: Pointer to net_device structure.
12225 * @key_index: key index
12226 * @pairwise: pairwise
12227 * @mac_addr: mac address
12228 *
12229 * This is the cfg80211 delete key handler function which invokes
12230 * the internal function @__wlan_hdd_cfg80211_del_key with
12231 * SSR protection.
12232 *
12233 * Return: 0 for success, error number on failure.
12234 */
12235static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12236 struct net_device *dev,
12237 u8 key_index,
12238 bool pairwise, const u8 *mac_addr)
12239{
12240 int ret;
12241
12242 cds_ssr_protect(__func__);
12243 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12244 pairwise, mac_addr);
12245 cds_ssr_unprotect(__func__);
12246
12247 return ret;
12248}
12249
12250/*
12251 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12252 * This function is used to set the default tx key index
12253 */
12254static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12255 struct net_device *ndev,
12256 u8 key_index,
12257 bool unicast, bool multicast)
12258{
12259 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12260 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12261 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12262 hdd_context_t *pHddCtx;
12263 int status;
12264
12265 ENTER();
12266
Anurag Chouhan6d760662016-02-20 16:05:43 +053012267 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012268 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012269 return -EINVAL;
12270 }
12271
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012272 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012273 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012274 return -EINVAL;
12275 }
12276
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012277 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012278 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12279 pAdapter->sessionId, key_index));
12280
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012281 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012282 hdd_device_mode_to_string(pAdapter->device_mode),
12283 pAdapter->device_mode, key_index);
12284
12285 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012286 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012287 return -EINVAL;
12288 }
12289
12290 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12291 status = wlan_hdd_validate_context(pHddCtx);
12292
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012293 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012294 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012295
Krunal Sonib4326f22016-03-10 13:05:51 -080012296 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12297 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012298 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12299 pHddStaCtx->conn_info.ucEncryptionType) &&
12300 (eCSR_ENCRYPT_TYPE_AES !=
12301 pHddStaCtx->conn_info.ucEncryptionType)) {
12302 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012303 * then update the default key index
12304 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012305
12306 tCsrRoamSetKey setKey;
12307 uint32_t roamId = 0xFF;
12308 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12309
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012310 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012311
12312 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012313 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012314 setKey.keyId = key_index;
12315 setKey.keyLength = Keys->KeyLength[key_index];
12316
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012317 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012318 &Keys->KeyMaterial[key_index][0],
12319 Keys->KeyLength[key_index]);
12320
12321 setKey.keyDirection = eSIR_TX_RX;
12322
Anurag Chouhanc5548422016-02-24 18:33:27 +053012323 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324 &pHddStaCtx->conn_info.bssId);
12325
12326 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12327 pWextState->roamProfile.EncryptionType.
12328 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012329 /* In the case of dynamic wep
12330 * supplicant hardcodes DWEP type to
12331 * eCSR_ENCRYPT_TYPE_WEP104 even
12332 * though ap is configured for WEP-40
12333 * encryption. In this canse the key
12334 * length is 5 but the encryption type
12335 * is 104 hence checking the key
12336 * lenght(5) and encryption type(104)
12337 * and switching encryption type to 40
12338 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012339 pWextState->roamProfile.EncryptionType.
12340 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12341 pWextState->roamProfile.mcEncryptionType.
12342 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12343 }
12344
12345 setKey.encType =
12346 pWextState->roamProfile.EncryptionType.
12347 encryptionType[0];
12348
12349 /* Issue set key request */
12350 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12351 pAdapter->sessionId, &setKey,
12352 &roamId);
12353
12354 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012355 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012356 status);
12357 return -EINVAL;
12358 }
12359 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012360 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012361 /* In SoftAp mode setting key direction for default mode */
12362 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12363 pWextState->roamProfile.EncryptionType.encryptionType[0])
12364 && (eCSR_ENCRYPT_TYPE_AES !=
12365 pWextState->roamProfile.EncryptionType.
12366 encryptionType[0])) {
12367 /* Saving key direction for default key index to TX default */
12368 hdd_ap_ctx_t *pAPCtx =
12369 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12370 pAPCtx->wepKey[key_index].keyDirection =
12371 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012372 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012373 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012374 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012375 }
12376 }
12377
12378 EXIT();
12379 return status;
12380}
12381
12382static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12383 struct net_device *ndev,
12384 u8 key_index,
12385 bool unicast, bool multicast)
12386{
12387 int ret;
12388 cds_ssr_protect(__func__);
12389 ret =
12390 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12391 multicast);
12392 cds_ssr_unprotect(__func__);
12393
12394 return ret;
12395}
12396
Abhishek Singhc9941602016-08-09 16:06:22 +053012397/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012398 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12399 * interface that BSS might have been lost.
12400 * @pAdapter: adaptor
12401 * @bssid: bssid which might have been lost
12402 *
12403 * Return: bss which is unlinked from kernel cache
12404 */
12405struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12406 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012407{
12408 struct net_device *dev = pAdapter->dev;
12409 struct wireless_dev *wdev = dev->ieee80211_ptr;
12410 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012411 struct cfg80211_bss *bss = NULL;
12412
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012413 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012414 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012415 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012416 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012417 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012418 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012419 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012420 cfg80211_unlink_bss(wiphy, bss);
12421 }
12422 return bss;
12423}
12424
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012425#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12426 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12427static struct cfg80211_bss *
12428wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12429 struct ieee80211_channel *chan,
12430 struct ieee80211_mgmt *mgmt,
12431 size_t frame_len,
12432 int rssi, gfp_t gfp,
12433 uint64_t boottime_ns)
12434{
12435 struct cfg80211_bss *bss_status = NULL;
12436 struct cfg80211_inform_bss data = {0};
12437
12438 data.chan = chan;
12439 data.boottime_ns = boottime_ns;
12440 data.signal = rssi;
12441 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12442 frame_len, gfp);
12443 return bss_status;
12444}
12445#else
12446static struct cfg80211_bss *
12447wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12448 struct ieee80211_channel *chan,
12449 struct ieee80211_mgmt *mgmt,
12450 size_t frame_len,
12451 int rssi, gfp_t gfp,
12452 uint64_t boottime_ns)
12453{
12454 struct cfg80211_bss *bss_status = NULL;
12455
12456 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12457 rssi, gfp);
12458 return bss_status;
12459}
12460#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012462/**
12463 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12464 * @pAdapter: Pointer to adapter
12465 * @bss_desc: Pointer to bss descriptor
12466 *
12467 * This function is used to inform the BSS details to nl80211 interface.
12468 *
12469 * Return: struct cfg80211_bss pointer
12470 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012471struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12472 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012473{
12474 /*
12475 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12476 * already exists in bss data base of cfg80211 for that particular BSS
12477 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12478 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12479 * As of now there is no possibility to get the mgmt(probe response)
12480 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12481 * and passing to cfg80211_inform_bss_frame.
12482 */
12483 struct net_device *dev = pAdapter->dev;
12484 struct wireless_dev *wdev = dev->ieee80211_ptr;
12485 struct wiphy *wiphy = wdev->wiphy;
12486 int chan_no = bss_desc->channelId;
12487#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12488 qcom_ie_age *qie_age = NULL;
12489 int ie_length =
12490 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12491#else
12492 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12493#endif
12494 const char *ie =
12495 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12496 unsigned int freq;
12497 struct ieee80211_channel *chan;
12498 struct ieee80211_mgmt *mgmt = NULL;
12499 struct cfg80211_bss *bss_status = NULL;
12500 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12501 int rssi = 0;
12502 hdd_context_t *pHddCtx;
12503 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012504 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012505 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012506
12507 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12508 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012509 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012510 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012511
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012512 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012513 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012514 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012515 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012516 return NULL;
12517 }
12518
12519 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12520
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012521 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012522 * Instead it wants a monotonic increasing value
12523 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012524 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012525 mgmt->u.probe_resp.timestamp =
12526 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012527
12528 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12529 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12530
12531#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12532 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12533 /* Assuming this is the last IE, copy at the end */
12534 ie_length -= sizeof(qcom_ie_age);
12535 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12536 qie_age->element_id = QCOM_VENDOR_IE_ID;
12537 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12538 qie_age->oui_1 = QCOM_OUI1;
12539 qie_age->oui_2 = QCOM_OUI2;
12540 qie_age->oui_3 = QCOM_OUI3;
12541 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012542 /*
12543 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12544 * all bss related timestamp is in units of ms. Due to this when scan
12545 * results are sent to lowi the scan age is high.To address this,
12546 * send age in units of 1/10 ms.
12547 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012548 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012549 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012550 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012551 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12552 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012553 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12554 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012555#endif
12556
12557 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12558 if (bss_desc->fProbeRsp) {
12559 mgmt->frame_control |=
12560 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12561 } else {
12562 mgmt->frame_control |=
12563 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12564 }
12565
12566 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012567 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012568 freq =
12569 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012570 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012571 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012572 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012573 freq =
12574 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012575 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012576 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012577 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012578 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012579 return NULL;
12580 }
12581
12582 chan = __ieee80211_get_channel(wiphy, freq);
12583 /* When the band is changed on the fly using the GUI, three things are done
12584 * 1. scan abort
12585 * 2. flush scan results from cache
12586 * 3. update the band with the new band user specified (refer to the
12587 * hdd_set_band_helper function) as part of the scan abort, message will be
12588 * queued to PE and we proceed with flushing and changinh the band.
12589 * PE will stop the scanning further and report back the results what ever
12590 * it had till now by calling the call back function.
12591 * if the time between update band and scandone call back is sufficient
12592 * enough the band change reflects in SME, SME validates the channels
12593 * and discards the channels correponding to previous band and calls back
12594 * with zero bss results. but if the time between band update and scan done
12595 * callback is very small then band change will not reflect in SME and SME
12596 * reports to HDD all the channels correponding to previous band.this is due
12597 * to race condition.but those channels are invalid to the new band and so
12598 * this function __ieee80211_get_channel will return NULL.Each time we
12599 * report scan result with this pointer null warning kernel trace is printed.
12600 * if the scan results contain large number of APs continuosly kernel
12601 * warning trace is printed and it will lead to apps watch dog bark.
12602 * So drop the bss and continue to next bss.
12603 */
12604 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012605 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12606 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012607 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012608 return NULL;
12609 }
12610
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012611 /* Based on .ini configuration, raw rssi can be reported for bss.
12612 * Raw rssi is typically used for estimating power.
12613 */
12614
12615 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12616 bss_desc->rssi;
12617
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012618 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012619 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012620
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012621 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012622 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012623 (int)(rssi / 100),
12624 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012625
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012626 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12627 frame_len, rssi,
12628 GFP_KERNEL,
12629 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012630 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012631 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012632 return bss_status;
12633}
12634
12635/**
12636 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12637 * @pAdapter: Pointer to adapter
12638 * @pRoamInfo: Pointer to roam info
12639 *
12640 * This function is used to update the BSS data base of CFG8011
12641 *
12642 * Return: struct cfg80211_bss pointer
12643 */
12644struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12645 tCsrRoamInfo *pRoamInfo)
12646{
12647 tCsrRoamConnectedProfile roamProfile;
12648 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12649 struct cfg80211_bss *bss = NULL;
12650
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012651 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12652 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12653
12654 if (NULL != roamProfile.pBssDesc) {
12655 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12656 roamProfile.pBssDesc);
12657
12658 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012659 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012660
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012661 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012662 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012663 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012664 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012665 return bss;
12666}
12667/**
12668 * wlan_hdd_cfg80211_update_bss() - update bss
12669 * @wiphy: Pointer to wiphy
12670 * @pAdapter: Pointer to adapter
12671 * @scan_time: scan request timestamp
12672 *
12673 * Return: zero if success, non-zero otherwise
12674 */
12675int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12676 hdd_adapter_t *pAdapter,
12677 uint32_t scan_time)
12678{
12679 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12680 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012681 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012682 tScanResultHandle pResult;
12683 struct cfg80211_bss *bss_status = NULL;
12684 hdd_context_t *pHddCtx;
12685 int ret;
12686
12687 ENTER();
12688
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012689 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12690 hdd_err("invalid session id: %d", pAdapter->sessionId);
12691 return -EINVAL;
12692 }
12693
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012694 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012695 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12696 NO_SESSION, pAdapter->sessionId));
12697
12698 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12699 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012700 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012701 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012702
12703 /* start getting scan results and populate cgf80211 BSS database */
12704 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12705
12706 /* no scan results */
12707 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012708 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012709 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012710 }
12711
12712 pScanResult = sme_scan_result_get_first(hHal, pResult);
12713
12714 while (pScanResult) {
12715 /*
12716 * - cfg80211_inform_bss() is not updating ie field of bss
12717 * entry if entry already exists in bss data base of cfg80211
12718 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12719 * to update thebss entry instead of cfg80211_inform_bss,
12720 * But this call expects mgmt packet as input. As of now
12721 * there is no possibility to get the mgmt(probe response)
12722 * frame from PE, converting bss_desc to
12723 * ieee80211_mgmt(probe response) and passing to c
12724 * fg80211_inform_bss_frame.
12725 * - Update BSS only if beacon timestamp is later than
12726 * scan request timestamp.
12727 */
12728 if ((scan_time == 0) ||
12729 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012730 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012731 bss_status =
12732 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12733 &pScanResult->BssDescriptor);
12734
12735 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012736 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012737 } else {
12738 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012739 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012740 bss_status);
12741 }
12742 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012743 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012744 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12745 }
12746 pScanResult = sme_scan_result_get_next(hHal, pResult);
12747 }
12748
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012749 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012750 /*
12751 * For SAP mode, scan is invoked by hostapd during SAP start
12752 * if hostapd is restarted, we need to flush previous scan
12753 * result so that it will reflect environment change
12754 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012755 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012756#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12757 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12758#endif
12759 )
12760 sme_scan_flush_result(hHal);
12761
12762 EXIT();
12763 return 0;
12764}
12765
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012766/**
12767 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12768 * @pAdapter: Pointer to adapter
12769 * @pRoamInfo: Pointer to roam info
12770 * @index: Index
12771 * @preauth: Preauth flag
12772 *
12773 * This function is used to notify the supplicant of a new PMKSA candidate.
12774 *
12775 * Return: 0 for success, non-zero for failure
12776 */
12777int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12778 tCsrRoamInfo *pRoamInfo,
12779 int index, bool preauth)
12780{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012781 struct net_device *dev = pAdapter->dev;
12782 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12783
12784 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012785 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012786
12787 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012788 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012789 return -EINVAL;
12790 }
12791
12792 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012793 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012794 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12795 cfg80211_pmksa_candidate_notify(dev, index,
12796 pRoamInfo->bssid.bytes,
12797 preauth, GFP_KERNEL);
12798 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012799 return 0;
12800}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012801
12802#ifdef FEATURE_WLAN_LFR_METRICS
12803/**
12804 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12805 * @pAdapter: Pointer to adapter
12806 * @pRoamInfo: Pointer to roam info
12807 *
12808 * 802.11r/LFR metrics reporting function to report preauth initiation
12809 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012810 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012811 */
12812#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012813QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012814 tCsrRoamInfo *pRoamInfo)
12815{
12816 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12817 union iwreq_data wrqu;
12818
12819 ENTER();
12820
12821 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012822 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012823 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012824 }
12825
12826 /* create the event */
12827 memset(&wrqu, 0, sizeof(wrqu));
12828 memset(metrics_notification, 0, sizeof(metrics_notification));
12829
12830 wrqu.data.pointer = metrics_notification;
12831 wrqu.data.length = scnprintf(metrics_notification,
12832 sizeof(metrics_notification),
12833 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12834 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12835
12836 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12837 metrics_notification);
12838
12839 EXIT();
12840
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012841 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012842}
12843
12844/**
12845 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12846 * @pAdapter: Pointer to adapter
12847 * @pRoamInfo: Pointer to roam info
12848 * @preauth_status: Preauth status
12849 *
12850 * 802.11r/LFR metrics reporting function to report handover initiation
12851 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012852 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012853 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012854QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012855wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12856 tCsrRoamInfo *pRoamInfo,
12857 bool preauth_status)
12858{
12859 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12860 union iwreq_data wrqu;
12861
12862 ENTER();
12863
12864 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012865 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012866 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012867 }
12868
12869 /* create the event */
12870 memset(&wrqu, 0, sizeof(wrqu));
12871 memset(metrics_notification, 0, sizeof(metrics_notification));
12872
12873 scnprintf(metrics_notification, sizeof(metrics_notification),
12874 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12875 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12876
12877 if (1 == preauth_status)
12878 strlcat(metrics_notification, " true",
12879 sizeof(metrics_notification));
12880 else
12881 strlcat(metrics_notification, " false",
12882 sizeof(metrics_notification));
12883
12884 wrqu.data.pointer = metrics_notification;
12885 wrqu.data.length = strlen(metrics_notification);
12886
12887 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12888 metrics_notification);
12889
12890 EXIT();
12891
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012892 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012893}
12894
12895/**
12896 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12897 * @pAdapter: Pointer to adapter
12898 * @pRoamInfo: Pointer to roam info
12899 *
12900 * 802.11r/LFR metrics reporting function to report handover initiation
12901 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012902 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012903 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012904QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012905 tCsrRoamInfo *pRoamInfo)
12906{
12907 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12908 union iwreq_data wrqu;
12909
12910 ENTER();
12911
12912 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012913 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012914 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012915 }
12916
12917 /* create the event */
12918 memset(&wrqu, 0, sizeof(wrqu));
12919 memset(metrics_notification, 0, sizeof(metrics_notification));
12920
12921 wrqu.data.pointer = metrics_notification;
12922 wrqu.data.length = scnprintf(metrics_notification,
12923 sizeof(metrics_notification),
12924 "QCOM: LFR_PREAUTH_HANDOVER "
12925 MAC_ADDRESS_STR,
12926 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12927
12928 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12929 metrics_notification);
12930
12931 EXIT();
12932
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012933 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012934}
12935#endif
12936
12937/**
12938 * hdd_select_cbmode() - select channel bonding mode
12939 * @pAdapter: Pointer to adapter
12940 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012941 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012942 *
12943 * Return: none
12944 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012945void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080012946 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012947{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012948 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012949 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012950 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012951 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012952
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012953 /*
12954 * CDS api expects secondary channel for calculating
12955 * the channel params
12956 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012957 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012958 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012959 if (operationChannel >= 1 && operationChannel <= 5)
12960 sec_ch = operationChannel + 4;
12961 else if (operationChannel >= 6 && operationChannel <= 13)
12962 sec_ch = operationChannel - 4;
12963 }
12964
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012965 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012966 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
12967 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012968
12969 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070012970 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012971 uint8_t iniDot11Mode =
12972 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12973
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012974 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012975 switch (iniDot11Mode) {
12976 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012977 case eHDD_DOT11_MODE_11ax:
12978 case eHDD_DOT11_MODE_11ax_ONLY:
12979 if (sme_is_feature_supported_by_fw(DOT11AX))
12980 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12981 else if (sme_is_feature_supported_by_fw(DOT11AC))
12982 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12983 else
12984 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12985 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012986 case eHDD_DOT11_MODE_11ac:
12987 case eHDD_DOT11_MODE_11ac_ONLY:
12988 if (sme_is_feature_supported_by_fw(DOT11AC))
12989 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12990 else
12991 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12992 break;
12993 case eHDD_DOT11_MODE_11n:
12994 case eHDD_DOT11_MODE_11n_ONLY:
12995 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12996 break;
12997 default:
12998 hdd_dot11_mode = iniDot11Mode;
12999 break;
13000 }
13001 ch_info->channel_width = ch_params->ch_width;
13002 ch_info->phy_mode =
13003 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013004 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013005 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013006 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013007 ch_info->channel_width, ch_info->phy_mode,
13008 ch_info->channel);
13009 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013010}
13011
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013012/**
13013 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
13014 * @adapter: STA adapter
13015 * @roam_profile: STA roam profile
13016 *
13017 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
13018 *
13019 * Return: false if sta-sap conc is not allowed, else return true
13020 */
13021static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
13022 tCsrRoamProfile *roam_profile)
13023{
13024 hdd_context_t *hdd_ctx;
13025 hdd_adapter_t *ap_adapter;
13026 hdd_ap_ctx_t *hdd_ap_ctx;
13027 hdd_hostapd_state_t *hostapd_state;
13028 uint8_t channel = 0;
13029 QDF_STATUS status;
13030
13031 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13032 if (!hdd_ctx) {
13033 hdd_err("HDD context is NULL");
13034 return true;
13035 }
13036
13037 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
13038 /* probably no sap running, no handling required */
13039 if (ap_adapter == NULL)
13040 return true;
13041
13042 /*
13043 * sap is not in started state, so it is fine to go ahead with sta.
13044 * if sap is currently doing CAC then don't allow sta to go further.
13045 */
13046 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
13047 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
13048 return true;
13049
13050 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
13051 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
13052 return false;
13053 }
13054
13055 /*
13056 * log and return error, if we allow STA to go through, we don't
13057 * know what is going to happen better stop sta connection
13058 */
13059 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
13060 if (NULL == hdd_ap_ctx) {
13061 hdd_err("AP context not found");
13062 return false;
13063 }
13064
13065 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013066 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
13067 hdd_ap_ctx->operatingChannel)) {
13068 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013069 return true;
13070 }
13071 /*
13072 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053013073 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013074 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013075 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013076 roam_profile, &channel);
13077
Nitesh Shah59774522016-09-16 15:14:21 +053013078 /*
13079 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
13080 * channels for roaming case.
13081 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013082 if (WLAN_REG_IS_24GHZ_CH(channel)) {
13083 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053013084 return true;
13085 }
13086
13087 /*
13088 * If channel is 0 or DFS then better to call pcl and find out the
13089 * best channel. If channel is non-dfs 5 GHz then better move SAP
13090 * to STA's channel to make scc, so we have room for 3port MCC
13091 * scenario.
13092 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013093 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013094 channel = policy_mgr_get_nondfs_preferred_channel(
13095 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013096
13097 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
13098 qdf_event_reset(&hostapd_state->qdf_event);
13099 status = wlansap_set_channel_change_with_csa(
13100 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
13101 hdd_ap_ctx->sapConfig.ch_width_orig);
13102
13103 if (QDF_STATUS_SUCCESS != status) {
13104 hdd_err("Set channel with CSA IE failed, can't allow STA");
13105 return false;
13106 }
13107
13108 /*
13109 * wait here for SAP to finish the channel switch. When channel
13110 * switch happens, SAP sends few beacons with CSA_IE. After
13111 * successfully Transmission of those beacons, it will move its
13112 * state from started to disconnected and move to new channel.
13113 * once it moves to new channel, sap again moves its state
13114 * machine from disconnected to started and set this event.
13115 * wait for 10 secs to finish this.
13116 */
13117 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
13118 if (!QDF_IS_STATUS_SUCCESS(status)) {
13119 hdd_err("wait for qdf_event failed, STA not allowed!!");
13120 return false;
13121 }
13122
13123 return true;
13124}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013125
Abhishek Singhcfb44482017-03-10 12:42:37 +053013126#ifdef WLAN_FEATURE_11W
13127/**
13128 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
13129 * @roam_profile: pointer to roam profile
13130 *
13131 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13132 * or pmf=2 is an explicit configuration in the supplicant
13133 * configuration, drop the connection request.
13134 *
13135 * Return: 0 if check result is valid, otherwise return error code
13136 */
13137static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13138{
13139 if (roam_profile->MFPEnabled &&
13140 !(roam_profile->MFPRequired ||
13141 roam_profile->MFPCapable)) {
13142 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13143 roam_profile->MFPEnabled,
13144 roam_profile->MFPRequired,
13145 roam_profile->MFPCapable);
13146 return -EINVAL;
13147 }
13148 return 0;
13149}
13150#else
13151static inline
13152int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13153{
13154 return 0;
13155}
13156#endif
13157
Krunal Soni31949422016-07-29 17:17:53 -070013158/**
13159 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013160 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070013161 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013162 * @ssid_len: Length of ssid
13163 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070013164 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013165 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013166 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013167 *
13168 * This function is used to start the association process
13169 *
13170 * Return: 0 for success, non-zero for failure
13171 */
Krunal Soni31949422016-07-29 17:17:53 -070013172static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013173 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013174 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013175 u8 operatingChannel,
13176 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013177{
13178 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013179 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013180 hdd_wext_state_t *pWextState;
13181 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013182 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013183 uint32_t roamId;
13184 tCsrRoamProfile *pRoamProfile;
13185 eCsrAuthType RSNAuthType;
13186 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013187 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013188
13189 ENTER();
13190
13191 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13192 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013193 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013194
13195 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013196 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013197 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013198
13199 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013200 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013201 status = -EINVAL;
13202 goto ret_status;
13203 }
13204
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013205 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013206 hdd_err("Connection refused: conn in progress");
13207 status = -EINVAL;
13208 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013209 }
13210
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013211 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013212 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13213
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013214 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013215 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13216 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013217
13218 if (pRoamProfile) {
13219 hdd_station_ctx_t *pHddStaCtx;
13220 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13221
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013222 /* Restart the opportunistic timer
13223 *
13224 * If hw_mode_change_in_progress is true, then wait
13225 * till firmware sends the callback for hw_mode change.
13226 *
13227 * Else set connect_in_progress as true and proceed.
13228 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013229 policy_mgr_restart_opportunistic_timer(
13230 pHddCtx->hdd_psoc, false);
13231 if (policy_mgr_is_hw_mode_change_in_progress(
13232 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013233 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013234 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013235 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013236 hdd_err("qdf wait for event failed!!");
13237 status = -EINVAL;
13238 goto ret_status;
13239 }
13240 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013241 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013242
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013243 if (HDD_WMM_USER_MODE_NO_QOS ==
13244 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13245 /*QoS not enabled in cfg file */
13246 pRoamProfile->uapsd_mask = 0;
13247 } else {
13248 /*QoS enabled, update uapsd mask from cfg file */
13249 pRoamProfile->uapsd_mask =
13250 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13251 }
13252
13253 pRoamProfile->SSIDs.numOfSSIDs = 1;
13254 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013255 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013256 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013257 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013258 ssid, ssid_len);
13259
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013260 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013261 /* cleanup bssid hint */
13262 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13263 QDF_MAC_ADDR_SIZE);
13264 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13265 QDF_MAC_ADDR_SIZE);
13266
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013267 if (bssid) {
13268 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013269 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013270 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013271 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013272 /*
13273 * Save BSSID in seperate variable as
13274 * pRoamProfile's BSSID is getting zeroed out in the
13275 * association process. In case of join failure
13276 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013277 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013278 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013279 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013280 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013281 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013282 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13283 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013284 /*
13285 * Save BSSID in a separate variable as
13286 * pRoamProfile's BSSID is getting zeroed out in the
13287 * association process. In case of join failure
13288 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013289 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013290 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013291 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013292 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013293 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013294 }
13295
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013296 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013297 pRoamProfile->SSIDs.SSIDList->SSID.length,
13298 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13299 operatingChannel);
13300
13301 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13302 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013303 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013304 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13305 }
13306#ifdef FEATURE_WLAN_WAPI
13307 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013308 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013309 switch (pAdapter->wapi_info.wapiAuthMode) {
13310 case WAPI_AUTH_MODE_PSK:
13311 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013312 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013313 pAdapter->wapi_info.wapiAuthMode);
13314 pRoamProfile->AuthType.authType[0] =
13315 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13316 break;
13317 }
13318 case WAPI_AUTH_MODE_CERT:
13319 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013320 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013321 pAdapter->wapi_info.wapiAuthMode);
13322 pRoamProfile->AuthType.authType[0] =
13323 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13324 break;
13325 }
13326 } /* End of switch */
13327 if (pAdapter->wapi_info.wapiAuthMode ==
13328 WAPI_AUTH_MODE_PSK
13329 || pAdapter->wapi_info.wapiAuthMode ==
13330 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013331 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013332 pRoamProfile->AuthType.numEntries = 1;
13333 pRoamProfile->EncryptionType.numEntries = 1;
13334 pRoamProfile->EncryptionType.encryptionType[0] =
13335 eCSR_ENCRYPT_TYPE_WPI;
13336 pRoamProfile->mcEncryptionType.numEntries = 1;
13337 pRoamProfile->mcEncryptionType.
13338 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13339 }
13340 }
Krunal Soni31949422016-07-29 17:17:53 -070013341#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013342 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013343 pRoamProfile->csrPersona = pAdapter->device_mode;
13344
13345 if (operatingChannel) {
13346 pRoamProfile->ChannelInfo.ChannelList =
13347 &operatingChannel;
13348 pRoamProfile->ChannelInfo.numOfChannels = 1;
13349 } else {
13350 pRoamProfile->ChannelInfo.ChannelList = NULL;
13351 pRoamProfile->ChannelInfo.numOfChannels = 0;
13352 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013353 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013354 && operatingChannel) {
13355 /*
13356 * Need to post the IBSS power save parameters
13357 * to WMA. WMA will configure this parameters
13358 * to firmware if power save is enabled by the
13359 * firmware.
13360 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013361 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013362
Abhishek Singh471652b2017-04-14 12:28:32 +053013363 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013364 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013365 status = -EINVAL;
13366 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013367 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013368 pRoamProfile->ch_params.ch_width =
13369 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013370 /*
13371 * In IBSS mode while operating in 2.4 GHz,
13372 * the device supports only 20 MHz.
13373 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013374 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013375 pRoamProfile->ch_params.ch_width =
13376 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013377 hdd_select_cbmode(pAdapter, operatingChannel,
13378 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013379 }
13380
Abhishek Singhcfb44482017-03-10 12:42:37 +053013381 if (wlan_hdd_cfg80211_check_pmf_valid(
13382 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013383 status = -EINVAL;
13384 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013385 }
13386
Krunal Soni31949422016-07-29 17:17:53 -070013387 /*
13388 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013389 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013390 * enhancements, the supplicant is not issuing the scan command
13391 * now. So the unicast frames which are sent from the host are
13392 * not having the additional IEs. If it is P2P CLIENT and there
13393 * is no additional IE present in roamProfile, then use the
13394 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013395 */
13396
Krunal Sonib4326f22016-03-10 13:05:51 -080013397 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013398 (!pRoamProfile->pAddIEScan)) {
13399 pRoamProfile->pAddIEScan =
13400 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13401 pRoamProfile->nAddIEScanLength =
13402 pAdapter->scan_info.scanAddIE.length;
13403 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013404
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013405 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13406 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013407 pRoamProfile))) {
13408 hdd_err("sap-sta conc will fail, can't allow sta");
13409 hdd_conn_set_connection_state(pAdapter,
13410 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013411 status = -ENOMEM;
13412 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013413 }
13414
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013415 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013416 if (!sme_config) {
13417 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013418 hdd_conn_set_connection_state(pAdapter,
13419 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013420 status = -ENOMEM;
13421 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013422 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013423 sme_get_config_param(pHddCtx->hHal, sme_config);
13424 /* These values are not sessionized. So, any change in these SME
13425 * configs on an older or parallel interface will affect the
13426 * cb mode. So, restoring the default INI params before starting
13427 * interfaces such as sta, cli etc.,
13428 */
13429 sme_config->csrConfig.channelBondingMode5GHz =
13430 pHddCtx->config->nChannelBondingMode5GHz;
13431 sme_config->csrConfig.channelBondingMode24GHz =
13432 pHddCtx->config->nChannelBondingMode24GHz;
13433 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013434 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013435 /*
13436 * Change conn_state to connecting before sme_roam_connect(),
13437 * because sme_roam_connect() has a direct path to call
13438 * hdd_sme_roam_callback(), which will change the conn_state
13439 * If direct path, conn_state will be accordingly changed to
13440 * NotConnected or Associated by either
13441 * hdd_association_completion_handler() or
13442 * hdd_dis_connect_handler() in sme_RoamCallback()if
13443 * sme_RomConnect is to be queued,
13444 * Connecting state will remain until it is completed.
13445 *
13446 * If connection state is not changed, connection state will
13447 * remain in eConnectionState_NotConnected state.
13448 * In hdd_association_completion_handler, "hddDisconInProgress"
13449 * is set to true if conn state is
13450 * eConnectionState_NotConnected.
13451 * If "hddDisconInProgress" is set to true then cfg80211 layer
13452 * is not informed of connect result indication which
13453 * is an issue.
13454 */
13455 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013456 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013457 hdd_conn_set_connection_state(pAdapter,
13458 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013459
Komal Seelama89be8d2016-09-29 11:09:26 +053013460 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13461 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013462 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013463 pAdapter->sessionId, pRoamProfile,
13464 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013465 if (QDF_IS_STATUS_ERROR(qdf_status))
13466 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013467
Rajeev Kumard31e1542017-01-13 14:37:42 -080013468 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013469 (QDF_STA_MODE == pAdapter->device_mode ||
13470 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013471 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013472 "qdf_status %d. -> NotConnected",
13473 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013474 /* change back to NotAssociated */
13475 hdd_conn_set_connection_state(pAdapter,
13476 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013477 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13478 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013479 }
13480
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013481 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013482 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013483
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013484 pRoamProfile->ChannelInfo.ChannelList = NULL;
13485 pRoamProfile->ChannelInfo.numOfChannels = 0;
13486
Nitesh Shah044fd672016-10-13 18:53:25 +053013487 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013488 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13489 && !policy_mgr_is_hw_dbs_2x2_capable(
13490 pHddCtx->hdd_psoc)) {
13491 policy_mgr_get_channel_from_scan_result(
13492 pHddCtx->hdd_psoc,
13493 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013494 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013495 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013496 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13497 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013498 }
13499
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013500 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013501 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013502 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013503 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013504 goto ret_status;
13505
13506conn_failure:
13507 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013508 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013509
13510ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013511 EXIT();
13512 return status;
13513}
13514
13515/**
13516 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13517 * @pAdapter: Pointer to adapter
13518 * @auth_type: Auth type
13519 *
13520 * This function is used to set the authentication type (OPEN/SHARED).
13521 *
13522 * Return: 0 for success, non-zero for failure
13523 */
13524static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13525 enum nl80211_auth_type auth_type)
13526{
13527 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13528 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13529
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013530 /*set authentication type */
13531 switch (auth_type) {
13532 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013533 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013534 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13535 break;
13536
13537 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013538 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013539 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013540 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13541 break;
13542
13543 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013544 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013545 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13546 break;
13547#ifdef FEATURE_WLAN_ESE
13548 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013549 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013550 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13551 break;
13552#endif
13553
13554 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013555 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013556 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13557 return -EINVAL;
13558 }
13559
13560 pWextState->roamProfile.AuthType.authType[0] =
13561 pHddStaCtx->conn_info.authType;
13562 return 0;
13563}
13564
13565/**
13566 * wlan_hdd_set_akm_suite() - set key management type
13567 * @pAdapter: Pointer to adapter
13568 * @key_mgmt: Key management type
13569 *
13570 * This function is used to set the key mgmt type(PSK/8021x).
13571 *
13572 * Return: 0 for success, non-zero for failure
13573 */
13574static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13575{
13576 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13577
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013578#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013579#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013580#endif
13581#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013582#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013583#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013584 /*set key mgmt type */
13585 switch (key_mgmt) {
13586 case WLAN_AKM_SUITE_PSK:
13587 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013588 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013589 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013590 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13591 break;
13592
13593 case WLAN_AKM_SUITE_8021X_SHA256:
13594 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013595 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013596 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013597 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13598 break;
13599#ifdef FEATURE_WLAN_ESE
13600#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13601#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13602 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013603 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013604 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13605 break;
13606#endif
13607#ifndef WLAN_AKM_SUITE_OSEN
13608#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13609#endif
13610 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013611 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013612 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13613 break;
13614
13615 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013616 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013617 return -EINVAL;
13618
13619 }
13620 return 0;
13621}
13622
13623/**
13624 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13625 * @pAdapter: Pointer to adapter
13626 * @cipher: Cipher type
13627 * @ucast: Unicast flag
13628 *
13629 * This function is used to set the encryption type
13630 * (NONE/WEP40/WEP104/TKIP/CCMP).
13631 *
13632 * Return: 0 for success, non-zero for failure
13633 */
13634static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13635 u32 cipher, bool ucast)
13636{
13637 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13638 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13639 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13640
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013641 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013642 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013643 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13644 } else {
13645
13646 /*set encryption method */
13647 switch (cipher) {
13648 case IW_AUTH_CIPHER_NONE:
13649 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13650 break;
13651
13652 case WLAN_CIPHER_SUITE_WEP40:
13653 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13654 break;
13655
13656 case WLAN_CIPHER_SUITE_WEP104:
13657 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13658 break;
13659
13660 case WLAN_CIPHER_SUITE_TKIP:
13661 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13662 break;
13663
13664 case WLAN_CIPHER_SUITE_CCMP:
13665 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13666 break;
13667#ifdef FEATURE_WLAN_WAPI
13668 case WLAN_CIPHER_SUITE_SMS4:
13669 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13670 break;
13671#endif
13672
13673#ifdef FEATURE_WLAN_ESE
13674 case WLAN_CIPHER_SUITE_KRK:
13675 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13676 break;
13677#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13678 case WLAN_CIPHER_SUITE_BTK:
13679 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13680 break;
13681#endif
13682#endif
13683 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013684 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013685 return -EOPNOTSUPP;
13686 }
13687 }
13688
13689 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013690 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013691 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13692 pWextState->roamProfile.EncryptionType.numEntries = 1;
13693 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13694 encryptionType;
13695 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013696 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013697 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13698 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13699 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13700 encryptionType;
13701 }
13702
13703 return 0;
13704}
13705
13706/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013707 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13708 * @wext_state: Pointer to wext state
13709 * @gen_ie: Pointer to IE data
13710 * @len: length of IE data
13711 *
13712 * Return: 0 for success, non-zero for failure
13713 */
13714static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13715 const uint8_t *gen_ie, uint16_t len)
13716{
13717 uint16_t cur_add_ie_len =
13718 wext_state->assocAddIE.length;
13719
13720 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13721 (wext_state->assocAddIE.length + len)) {
13722 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13723 QDF_ASSERT(0);
13724 return -ENOMEM;
13725 }
13726 memcpy(wext_state->assocAddIE.addIEdata +
13727 cur_add_ie_len, gen_ie, len);
13728 wext_state->assocAddIE.length += len;
13729
13730 wext_state->roamProfile.pAddIEAssoc =
13731 wext_state->assocAddIE.addIEdata;
13732 wext_state->roamProfile.nAddIEAssocLength =
13733 wext_state->assocAddIE.length;
13734 return 0;
13735}
13736
13737/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013738 * wlan_hdd_cfg80211_set_ie() - set IEs
13739 * @pAdapter: Pointer to adapter
13740 * @ie: Pointer ot ie
13741 * @ie: IE length
13742 *
13743 * Return: 0 for success, non-zero for failure
13744 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013745static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013746 size_t ie_len)
13747{
13748 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13749 const uint8_t *genie = ie;
13750 uint16_t remLen = ie_len;
13751#ifdef FEATURE_WLAN_WAPI
13752 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13753 u16 *tmp;
13754 uint16_t akmsuiteCount;
13755 int *akmlist;
13756#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013757 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013758
13759 /* clear previous assocAddIE */
13760 pWextState->assocAddIE.length = 0;
13761 pWextState->roamProfile.bWPSAssociation = false;
13762 pWextState->roamProfile.bOSENAssociation = false;
13763
13764 while (remLen >= 2) {
13765 uint16_t eLen = 0;
13766 uint8_t elementId;
13767 elementId = *genie++;
13768 eLen = *genie++;
13769 remLen -= 2;
13770
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013771 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013772
13773 switch (elementId) {
13774 case DOT11F_EID_WPA:
13775 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 -070013776 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013777 return -EINVAL;
13778 } else if (0 ==
13779 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13780 uint16_t curAddIELen =
13781 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013782 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013783
13784 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13785 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013786 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013787 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013788 return -ENOMEM;
13789 }
13790 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13791 memcpy(pWextState->assocAddIE.addIEdata +
13792 curAddIELen, genie - 2, eLen + 2);
13793 pWextState->assocAddIE.length += eLen + 2;
13794
13795 pWextState->roamProfile.bWPSAssociation = true;
13796 pWextState->roamProfile.pAddIEAssoc =
13797 pWextState->assocAddIE.addIEdata;
13798 pWextState->roamProfile.nAddIEAssocLength =
13799 pWextState->assocAddIE.length;
13800 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013801 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013802 memset(pWextState->WPARSNIE, 0,
13803 MAX_WPA_RSN_IE_LEN);
13804 memcpy(pWextState->WPARSNIE, genie - 2,
13805 (eLen + 2));
13806 pWextState->roamProfile.pWPAReqIE =
13807 pWextState->WPARSNIE;
13808 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13809 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13810 P2P_OUI_TYPE_SIZE))) {
13811 uint16_t curAddIELen =
13812 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013813 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013814
13815 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13816 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013817 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013818 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013819 return -ENOMEM;
13820 }
13821 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13822 memcpy(pWextState->assocAddIE.addIEdata +
13823 curAddIELen, genie - 2, eLen + 2);
13824 pWextState->assocAddIE.length += eLen + 2;
13825
13826 pWextState->roamProfile.pAddIEAssoc =
13827 pWextState->assocAddIE.addIEdata;
13828 pWextState->roamProfile.nAddIEAssocLength =
13829 pWextState->assocAddIE.length;
13830 }
13831#ifdef WLAN_FEATURE_WFD
13832 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13833 WFD_OUI_TYPE_SIZE)) &&
13834 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013835 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013836 pAdapter->device_mode)) {
13837 uint16_t curAddIELen =
13838 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013839 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013840
13841 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13842 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013843 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013844 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013845 return -ENOMEM;
13846 }
13847 /* WFD IE is saved to Additional IE ; it should
13848 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013849 * WFD IE
13850 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013851 memcpy(pWextState->assocAddIE.addIEdata +
13852 curAddIELen, genie - 2, eLen + 2);
13853 pWextState->assocAddIE.length += eLen + 2;
13854
13855 pWextState->roamProfile.pAddIEAssoc =
13856 pWextState->assocAddIE.addIEdata;
13857 pWextState->roamProfile.nAddIEAssocLength =
13858 pWextState->assocAddIE.length;
13859 }
13860#endif
13861 /* Appending HS 2.0 Indication Element in Assiciation Request */
13862 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13863 HS20_OUI_TYPE_SIZE))) {
13864 uint16_t curAddIELen =
13865 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013866 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013867
13868 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13869 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013870 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013871 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013872 return -ENOMEM;
13873 }
13874 memcpy(pWextState->assocAddIE.addIEdata +
13875 curAddIELen, genie - 2, eLen + 2);
13876 pWextState->assocAddIE.length += eLen + 2;
13877
13878 pWextState->roamProfile.pAddIEAssoc =
13879 pWextState->assocAddIE.addIEdata;
13880 pWextState->roamProfile.nAddIEAssocLength =
13881 pWextState->assocAddIE.length;
13882 }
13883 /* Appending OSEN Information Element in Assiciation Request */
13884 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13885 OSEN_OUI_TYPE_SIZE))) {
13886 uint16_t curAddIELen =
13887 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013888 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013889
13890 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13891 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013892 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013893 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013894 return -ENOMEM;
13895 }
13896 memcpy(pWextState->assocAddIE.addIEdata +
13897 curAddIELen, genie - 2, eLen + 2);
13898 pWextState->assocAddIE.length += eLen + 2;
13899
13900 pWextState->roamProfile.bOSENAssociation = true;
13901 pWextState->roamProfile.pAddIEAssoc =
13902 pWextState->assocAddIE.addIEdata;
13903 pWextState->roamProfile.nAddIEAssocLength =
13904 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013905 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13906 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013907 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013908 status = wlan_hdd_add_assoc_ie(pWextState,
13909 genie - 2, eLen + 2);
13910 if (status)
13911 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013912 } else {
13913 uint16_t add_ie_len =
13914 pWextState->assocAddIE.length;
13915
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013916 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013917
13918 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13919 (pWextState->assocAddIE.length + eLen)) {
13920 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013921 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013922 return -ENOMEM;
13923 }
13924
13925 memcpy(pWextState->assocAddIE.addIEdata +
13926 add_ie_len, genie - 2, eLen + 2);
13927 pWextState->assocAddIE.length += eLen + 2;
13928
13929 pWextState->roamProfile.pAddIEAssoc =
13930 pWextState->assocAddIE.addIEdata;
13931 pWextState->roamProfile.nAddIEAssocLength =
13932 pWextState->assocAddIE.length;
13933 }
13934 break;
13935 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013936 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013937 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13938 memcpy(pWextState->WPARSNIE, genie - 2,
13939 (eLen + 2));
13940 pWextState->roamProfile.pRSNReqIE =
13941 pWextState->WPARSNIE;
13942 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13943 break;
13944 /*
13945 * Appending Extended Capabilities with Interworking bit set
13946 * in Assoc Req.
13947 *
13948 * In assoc req this EXT Cap will only be taken into account if
13949 * interworkingService bit is set to 1. Currently
13950 * driver is only interested in interworkingService capability
13951 * from supplicant. If in future any other EXT Cap info is
13952 * required from supplicat, it needs to be handled while
13953 * sending Assoc Req in LIM.
13954 */
13955 case DOT11F_EID_EXTCAP:
13956 {
13957 uint16_t curAddIELen =
13958 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013959 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013960
13961 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13962 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013963 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013964 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013965 return -ENOMEM;
13966 }
13967 memcpy(pWextState->assocAddIE.addIEdata +
13968 curAddIELen, genie - 2, eLen + 2);
13969 pWextState->assocAddIE.length += eLen + 2;
13970
13971 pWextState->roamProfile.pAddIEAssoc =
13972 pWextState->assocAddIE.addIEdata;
13973 pWextState->roamProfile.nAddIEAssocLength =
13974 pWextState->assocAddIE.length;
13975 break;
13976 }
13977#ifdef FEATURE_WLAN_WAPI
13978 case WLAN_EID_WAPI:
13979 /* Setting WAPI Mode to ON=1 */
13980 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013981 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013982 tmp = (u16 *) ie;
13983 tmp = tmp + 2; /* Skip element Id and Len, Version */
13984 akmsuiteCount = WPA_GET_LE16(tmp);
13985 tmp = tmp + 1;
13986 akmlist = (int *)(tmp);
13987 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13988 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13989 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013990 hdd_err("Invalid akmSuite count: %u",
13991 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013992 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013993 return -EINVAL;
13994 }
13995
13996 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013997 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013998 pAdapter->wapi_info.wapiAuthMode =
13999 WAPI_AUTH_MODE_PSK;
14000 }
14001 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014002 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014003 pAdapter->wapi_info.wapiAuthMode =
14004 WAPI_AUTH_MODE_CERT;
14005 }
14006 break;
14007#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014008 case DOT11F_EID_SUPPOPERATINGCLASSES:
14009 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014010 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014011 status = wlan_hdd_add_assoc_ie(pWextState,
14012 genie - 2, eLen + 2);
14013 if (status)
14014 return status;
14015 break;
14016 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014017 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014018 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014019 /* when Unknown IE is received we break
14020 * and continue to the next IE in the buffer
14021 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014022 break;
14023 }
14024 genie += eLen;
14025 remLen -= eLen;
14026 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014027 return 0;
14028}
14029
14030/**
14031 * hdd_is_wpaie_present() - check for WPA ie
14032 * @ie: Pointer to ie
14033 * @ie_len: Ie length
14034 *
14035 * Parse the received IE to find the WPA IE
14036 *
14037 * Return: true if wpa ie is found else false
14038 */
14039static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
14040{
14041 uint8_t eLen = 0;
14042 uint16_t remLen = ie_len;
14043 uint8_t elementId = 0;
14044
14045 while (remLen >= 2) {
14046 elementId = *ie++;
14047 eLen = *ie++;
14048 remLen -= 2;
14049 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014050 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014051 return false;
14052 }
14053 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
14054 /* OUI - 0x00 0X50 0XF2
14055 * WPA Information Element - 0x01
14056 * WPA version - 0x01
14057 */
14058 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
14059 return true;
14060 }
14061 ie += eLen;
14062 remLen -= eLen;
14063 }
14064 return false;
14065}
14066
14067/**
14068 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
14069 * @pAdapter: Pointer to adapter
14070 * @req: Pointer to security parameters
14071 *
14072 * Return: 0 for success, non-zero for failure
14073 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014074static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
14075 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014076{
14077 int status = 0;
14078 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14079 ENTER();
14080
14081 /*set wpa version */
14082 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
14083
14084 if (req->crypto.wpa_versions) {
14085 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
14086 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
14087 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
14088 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14089 }
14090 }
14091
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014092 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014093
14094 /*set authentication type */
14095 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
14096
14097 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014098 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014099 return status;
14100 }
14101
14102 /*set key mgmt type */
14103 if (req->crypto.n_akm_suites) {
14104 status =
14105 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
14106 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014107 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014108 return status;
14109 }
14110 }
14111
14112 /*set pairwise cipher type */
14113 if (req->crypto.n_ciphers_pairwise) {
14114 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
14115 req->crypto.
14116 ciphers_pairwise[0],
14117 true);
14118 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014119 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014120 return status;
14121 }
14122 } else {
14123 /*Reset previous cipher suite to none */
14124 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
14125 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014126 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014127 return status;
14128 }
14129 }
14130
14131 /*set group cipher type */
14132 status =
14133 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
14134 false);
14135
14136 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014137 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014138 return status;
14139 }
14140#ifdef WLAN_FEATURE_11W
14141 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
14142#endif
14143
14144 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
14145 if (req->ie_len) {
14146 status =
14147 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
14148 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014149 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014150 return status;
14151 }
14152 }
14153
14154 /*incase of WEP set default key information */
14155 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080014156 u8 key_len = req->key_len;
14157 u8 key_idx = req->key_idx;
14158
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014159 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
14160 || (WLAN_CIPHER_SUITE_WEP104 ==
14161 req->crypto.ciphers_pairwise[0])
14162 ) {
14163 if (IW_AUTH_KEY_MGMT_802_1X
14164 ==
14165 (pWextState->
14166 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014167 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014168 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014169 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014170
Jeff Johnson68755312017-02-10 11:46:55 -080014171 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14172 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014173 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014174 key_idx, key_len);
14175 qdf_mem_copy(&pWextState->roamProfile.
14176 Keys.
14177 KeyMaterial[key_idx][0],
14178 req->key, key_len);
14179 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014180 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014181 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014182 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014183 }
14184 }
14185 }
14186
14187 return status;
14188}
14189
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014190int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014191{
14192 unsigned long rc;
14193 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014194 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014195 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014196
14197 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014198 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14199 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014200 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014201 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14202 }
14203 /*
14204 * If firmware has already started roaming process, driver
14205 * needs to defer the processing of this disconnect request.
14206 *
14207 */
14208 if (hdd_is_roaming_in_progress(pAdapter)) {
14209 /*
14210 * Defer the disconnect action until firmware roaming
14211 * result is received. If STA is in connected state after
14212 * that, send the disconnect command to CSR, otherwise
14213 * CSR would have already sent disconnect event to upper
14214 * layer.
14215 */
14216
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014217 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014218 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14219 pAdapter->cfg80211_disconnect_reason =
14220 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14221 return 0;
14222 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014223
Jeff Johnson9edf9572016-10-03 15:24:49 -070014224 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014225 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14226 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14227 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014228 hdd_conn_set_connection_state(pAdapter,
14229 eConnectionState_Disconnecting);
14230 /* Issue disconnect to CSR */
14231 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014232
14233 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14234 pAdapter->sessionId,
14235 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14236 /*
14237 * Wait here instead of returning directly, this will block the
14238 * next connect command and allow processing of the scan for
14239 * ssid and the previous connect command in CSR. Else we might
14240 * hit some race conditions leading to SME and HDD out of sync.
14241 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014242 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014243 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014244 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014245 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014246 (int)status);
14247 pHddStaCtx->staDebugState = status;
14248 result = -EINVAL;
14249 goto disconnected;
14250 }
14251
14252 rc = wait_for_completion_timeout(
14253 &pAdapter->disconnect_comp_var,
14254 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014255 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014256 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014257 pAdapter->sessionId, pHddStaCtx->staDebugState);
14258 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014259 }
14260 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014261 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014262 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014263 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014264 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014265 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014266 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014267 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014268 }
14269 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014270disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014271 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14272 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014273}
14274
14275/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014276 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14277 * @adapter: Pointer to the HDD adapter
14278 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014279 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014280 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014281 * This function will start reassociation if prev_bssid is set and bssid/
14282 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014283 *
Naveen Rawat07332902016-07-27 09:13:17 -070014284 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014285 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014286#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14287 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014288static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14289 struct cfg80211_connect_params *req,
14290 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014291{
Naveen Rawat07332902016-07-27 09:13:17 -070014292 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014293 const uint8_t *bssid = NULL;
14294 uint16_t channel = 0;
14295
14296 if (req->bssid)
14297 bssid = req->bssid;
14298 else if (req->bssid_hint)
14299 bssid = req->bssid_hint;
14300
14301 if (req->channel)
14302 channel = req->channel->hw_value;
14303 else if (req->channel_hint)
14304 channel = req->channel_hint->hw_value;
14305
14306 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014307 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014308 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014309 channel, MAC_ADDR_ARRAY(bssid));
14310 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014311 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014312 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014313 }
Naveen Rawat07332902016-07-27 09:13:17 -070014314 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014315}
14316#else
Naveen Rawat07332902016-07-27 09:13:17 -070014317static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14318 struct cfg80211_connect_params *req,
14319 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014320{
Naveen Rawat07332902016-07-27 09:13:17 -070014321 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014322}
14323#endif
14324
14325/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014326 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14327 * @wiphy: Pointer to wiphy
14328 * @dev: Pointer to network device
14329 * @req: Pointer to cfg80211 connect request
14330 *
14331 * This function is used to start the association process
14332 *
14333 * Return: 0 for success, non-zero for failure
14334 */
14335static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14336 struct net_device *ndev,
14337 struct cfg80211_connect_params *req)
14338{
14339 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014340 u16 channel;
14341#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14342 const u8 *bssid_hint = req->bssid_hint;
14343#else
14344 const u8 *bssid_hint = NULL;
14345#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014346 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14347 hdd_context_t *pHddCtx;
14348
14349 ENTER();
14350
Anurag Chouhan6d760662016-02-20 16:05:43 +053014351 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014352 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014353 return -EINVAL;
14354 }
14355
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014356 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14357 hdd_err("invalid session id: %d", pAdapter->sessionId);
14358 return -EINVAL;
14359 }
14360
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014361 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014362 TRACE_CODE_HDD_CFG80211_CONNECT,
14363 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014364 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014365 hdd_device_mode_to_string(pAdapter->device_mode),
14366 pAdapter->device_mode);
14367
Krunal Sonib4326f22016-03-10 13:05:51 -080014368 if (pAdapter->device_mode != QDF_STA_MODE &&
14369 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014370 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014371 hdd_device_mode_to_string(pAdapter->device_mode),
14372 pAdapter->device_mode);
14373 return -EINVAL;
14374 }
14375
14376 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14377 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014378 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014379 return -EINVAL;
14380 }
14381
14382 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014383 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014384 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014385
Naveen Rawat07332902016-07-27 09:13:17 -070014386 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014387 return status;
14388
Agrawal Ashishf156e942016-08-04 14:54:47 +053014389 /* Try disconnecting if already in connected state */
14390 status = wlan_hdd_try_disconnect(pAdapter);
14391 if (0 > status) {
14392 hdd_err("Failed to disconnect the existing connection");
14393 return -EALREADY;
14394 }
14395
14396 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014397 if (req->channel) {
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053014398 bool ok;
14399
14400 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
14401 pHddCtx->hdd_psoc,
14402 req->channel->hw_value,
14403 &ok)) {
14404 hdd_warn("Unable to get channel:%d eligibility for DNBS",
14405 req->channel->hw_value);
14406 return -EINVAL;
14407 }
14408 /**
14409 * Send connection timedout, so that Android framework does not
14410 * blacklist us.
14411 */
14412 if (!ok) {
14413 struct ieee80211_channel *chan =
14414 __ieee80211_get_channel(wiphy,
14415 wlan_chan_to_freq(req->channel->hw_value));
14416 struct cfg80211_bss *bss;
14417
14418 hdd_warn("Channel:%d not OK for DNBS",
14419 req->channel->hw_value);
14420 if (chan) {
14421 bss = hdd_cfg80211_get_bss(wiphy,
14422 chan,
14423 req->bssid, req->ssid,
14424 req->ssid_len);
14425 if (bss) {
14426 cfg80211_assoc_timeout(ndev, bss);
14427 return -ETIMEDOUT;
14428 }
14429 }
14430 return -EINVAL;
14431 }
14432
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014433 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14434 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014435 pAdapter->device_mode),
14436 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014437 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014438 return -ECONNREFUSED;
14439 }
14440 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014441 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14442 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014443 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014444 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014445 return -ECONNREFUSED;
14446 }
14447 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014448
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014449 /*initialise security parameters */
14450 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14451
14452 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014453 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014454 return status;
14455 }
14456
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014457 if (req->channel)
14458 channel = req->channel->hw_value;
14459 else
14460 channel = 0;
14461 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14462 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014463 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014464 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014465 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014466 return status;
14467 }
14468 EXIT();
14469 return status;
14470}
14471
14472/**
14473 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14474 * @wiphy: Pointer to wiphy
14475 * @dev: Pointer to network device
14476 * @req: Pointer to cfg80211 connect request
14477 *
14478 * Return: 0 for success, non-zero for failure
14479 */
14480static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14481 struct net_device *ndev,
14482 struct cfg80211_connect_params *req)
14483{
14484 int ret;
14485 cds_ssr_protect(__func__);
14486 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14487 cds_ssr_unprotect(__func__);
14488
14489 return ret;
14490}
14491
14492/**
14493 * wlan_hdd_disconnect() - hdd disconnect api
14494 * @pAdapter: Pointer to adapter
14495 * @reason: Disconnect reason code
14496 *
14497 * This function is used to issue a disconnect request to SME
14498 *
14499 * Return: 0 for success, non-zero for failure
14500 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014501static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014502{
14503 int status, result = 0;
14504 unsigned long rc;
14505 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14506 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014507 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014508 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014509
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014510 ENTER();
14511
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014512 status = wlan_hdd_validate_context(pHddCtx);
14513
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014514 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014515 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014516 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014517 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014518 status = sme_stop_roaming(hal, pAdapter->sessionId,
14519 eCsrHddIssued);
14520 }
14521 /*
14522 * If firmware has already started roaming process, driver
14523 * needs to defer the processing of this disconnect request.
14524 */
14525 if (hdd_is_roaming_in_progress(pAdapter)) {
14526 /*
14527 * Defer the disconnect action until firmware roaming
14528 * result is received. If STA is in connected state after
14529 * that, send the disconnect command to CSR, otherwise
14530 * CSR would have already sent disconnect event to upper
14531 * layer.
14532 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014533 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014534 pAdapter->defer_disconnect =
14535 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14536 pAdapter->cfg80211_disconnect_reason = reason;
14537 return 0;
14538 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014539
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014540 prev_conn_state = pHddStaCtx->conn_info.connState;
14541
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014542 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014543 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014544 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014545 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014546 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014547 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14548 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14549
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014550 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014551
14552 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14553 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014554 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14555 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014556 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014557 result = 0;
14558 goto disconnected;
14559 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14560 /*
14561 * Wait here instead of returning directly, this will block the
14562 * next connect command and allow processing of the scan for
14563 * ssid and the previous connect command in CSR. Else we might
14564 * hit some race conditions leading to SME and HDD out of sync.
14565 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014566 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014567 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014568 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014569 pHddStaCtx->staDebugState = status;
14570 result = -EINVAL;
14571 goto disconnected;
14572 }
14573 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14574 msecs_to_jiffies
14575 (WLAN_WAIT_TIME_DISCONNECT));
14576
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014577 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014578 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014579 result = -ETIMEDOUT;
14580 }
14581disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014582 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14583#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14584 /* Sending disconnect event to userspace for kernel version < 3.11
14585 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14586 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014587 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014588 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14589 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014590#endif
14591
14592 return result;
14593}
14594
14595/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014596 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14597 * @reason: ieee80211 reason code.
14598 *
14599 * This utility function helps log string conversion of reason code.
14600 *
14601 * Return: string conversion of reason code, if match found;
14602 * "Unknown" otherwise.
14603 */
14604static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14605{
14606 switch (reason) {
14607 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14608 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14609 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14610 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14611 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14612 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14613 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14614 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14615 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14616 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14617 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14618 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14619 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14620 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14621 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14622 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14623 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14624 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14625 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14626 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14627 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14628 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14629 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14630 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14631 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14632 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14633 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14634 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14635 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14636 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14637 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14638 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14639 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14640 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14641 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14642 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14643 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14644 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14645 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14646 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14647 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14648 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14649 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14650 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14651 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14652 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14653 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14654 default:
14655 return "Unknown";
14656 }
14657}
14658
14659/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014660 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14661 * @wiphy: Pointer to wiphy
14662 * @dev: Pointer to network device
14663 * @reason: Disconnect reason code
14664 *
14665 * This function is used to issue a disconnect request to SME
14666 *
14667 * Return: 0 for success, non-zero for failure
14668 */
14669static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14670 struct net_device *dev, u16 reason)
14671{
14672 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14673 int status;
14674 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14675 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14676#ifdef FEATURE_WLAN_TDLS
14677 uint8_t staIdx;
14678#endif
14679
14680 ENTER();
14681
Anurag Chouhan6d760662016-02-20 16:05:43 +053014682 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014683 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014684 return -EINVAL;
14685 }
14686
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014687 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014688 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014689 return -EINVAL;
14690 }
14691
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014692 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014693 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14694 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014695 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014696 hdd_device_mode_to_string(pAdapter->device_mode),
14697 pAdapter->device_mode, reason);
14698
14699 status = wlan_hdd_validate_context(pHddCtx);
14700
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014701 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014702 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014703
14704 /* Issue disconnect request to SME, if station is in connected state */
14705 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14706 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14707 eCsrRoamDisconnectReason reasonCode =
14708 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14709 hdd_scaninfo_t *pScanInfo;
14710
14711 switch (reason) {
14712 case WLAN_REASON_MIC_FAILURE:
14713 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14714 break;
14715
14716 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14717 case WLAN_REASON_DISASSOC_AP_BUSY:
14718 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14719 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14720 break;
14721
14722 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14723 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14724 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14725 break;
14726
14727 case WLAN_REASON_DEAUTH_LEAVING:
14728 reasonCode =
14729 pHddCtx->config->
14730 gEnableDeauthToDisassocMap ?
14731 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14732 eCSR_DISCONNECT_REASON_DEAUTH;
14733 break;
14734 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14735 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14736 break;
14737 default:
14738 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14739 break;
14740 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014741 pScanInfo = &pAdapter->scan_info;
14742 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014743 hdd_debug("Disconnect is in progress, Aborting Scan");
Abhishek Singh69ccb512017-04-25 11:58:16 +053014744 wlan_abort_scan(pHddCtx->hdd_pdev, INVAL_PDEV_ID,
14745 pAdapter->sessionId, INVALID_SCAN_ID, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014746 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014747 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014748#ifdef FEATURE_WLAN_TDLS
14749 /* First clean up the tdls peers if any */
14750 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14751 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14752 pAdapter->sessionId)
14753 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14754 uint8_t *mac;
14755 mac =
14756 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014757 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014758 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014759 pHddCtx->tdlsConnInfo[staIdx].staId,
14760 pAdapter->sessionId,
14761 MAC_ADDR_ARRAY(mac));
14762 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14763 (pAdapter),
14764 pAdapter->sessionId, mac);
14765 }
14766 }
Kabilan Kannanaad2f032017-05-08 13:25:37 -070014767 hdd_notify_sta_disconnect(pAdapter->sessionId,
14768 true, pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014769#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014770 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14771 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014772 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14773 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014774 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014775 return -EINVAL;
14776 }
14777 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014778 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014779 pHddStaCtx->conn_info.connState);
14780 }
14781
14782 return status;
14783}
14784
14785/**
14786 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14787 * @wiphy: Pointer to wiphy
14788 * @dev: Pointer to network device
14789 * @reason: Disconnect reason code
14790 *
14791 * Return: 0 for success, non-zero for failure
14792 */
14793static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14794 struct net_device *dev, u16 reason)
14795{
14796 int ret;
14797 cds_ssr_protect(__func__);
14798 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14799 cds_ssr_unprotect(__func__);
14800
14801 return ret;
14802}
14803
14804/**
14805 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14806 * @pAdapter: Pointer to adapter
14807 * @param: Pointer to IBSS parameters
14808 *
14809 * This function is used to initialize the security settings in IBSS mode
14810 *
14811 * Return: 0 for success, non-zero for failure
14812 */
14813static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14814 struct cfg80211_ibss_params
14815 *params)
14816{
14817 int status = 0;
14818 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14819 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14820 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14821
14822 ENTER();
14823
14824 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014825 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014826 pHddStaCtx->ibss_enc_key_installed = 0;
14827
14828 if (params->ie_len && (NULL != params->ie)) {
14829 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14830 params->ie_len, WLAN_EID_RSN)) {
14831 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14832 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14833 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14834 tDot11fIEWPA dot11WPAIE;
14835 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14836 u8 *ie;
14837
14838 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14839 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14840 params->ie_len,
14841 DOT11F_EID_WPA);
14842 if (NULL != ie) {
14843 pWextState->wpaVersion =
14844 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014845 /* Unpack the WPA IE
14846 * Skip past the EID byte and length byte
14847 * and four byte WiFi OUI
14848 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014849 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053014850 &ie[2 + 4], ie[1] - 4,
14851 &dot11WPAIE, false);
14852 /*
14853 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014854 * encType for unicast cipher for
14855 * wpa-none is none
14856 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014857 encryptionType =
14858 hdd_translate_wpa_to_csr_encryption_type
14859 (dot11WPAIE.multicast_cipher);
14860 }
14861 }
14862
14863 status =
14864 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14865 params->ie_len);
14866
14867 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014868 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014869 return status;
14870 }
14871 }
14872
14873 pWextState->roamProfile.AuthType.authType[0] =
14874 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14875
14876 if (params->privacy) {
14877 /* Security enabled IBSS, At this time there is no information
14878 * available about the security paramters, so initialise the
14879 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14880 * The correct security parameters will be updated later in
14881 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14882 * set inorder enable privacy bit in beacons
14883 */
14884
14885 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14886 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014887 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014888 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14889 pWextState->roamProfile.EncryptionType.numEntries = 1;
14890 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14891 encryptionType;
14892 return status;
14893}
14894
14895/**
14896 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14897 * @wiphy: Pointer to wiphy
14898 * @dev: Pointer to network device
14899 * @param: Pointer to IBSS join parameters
14900 *
14901 * This function is used to create/join an IBSS network
14902 *
14903 * Return: 0 for success, non-zero for failure
14904 */
14905static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14906 struct net_device *dev,
14907 struct cfg80211_ibss_params *params)
14908{
14909 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14910 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14911 tCsrRoamProfile *pRoamProfile;
14912 int status;
14913 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14914 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014915 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014916 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014917
14918 ENTER();
14919
Anurag Chouhan6d760662016-02-20 16:05:43 +053014920 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014921 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014922 return -EINVAL;
14923 }
14924
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014925 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014926 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014927 return -EINVAL;
14928 }
14929
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014930 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014931 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14932 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014933 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014934 hdd_device_mode_to_string(pAdapter->device_mode),
14935 pAdapter->device_mode);
14936
14937 status = wlan_hdd_validate_context(pHddCtx);
14938
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014939 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014940 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014941
14942 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014943 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014944 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14945 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14946 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14947 int indx;
14948
14949 /* Get channel number */
14950 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014951 params->
14952 chandef.
14953 chan->
14954 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014955
14956 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14957 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014958 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014959 return -EOPNOTSUPP;
14960 }
14961
14962 for (indx = 0; indx < numChans; indx++) {
14963 if (channelNum == validChan[indx]) {
14964 break;
14965 }
14966 }
14967 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014968 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014969 return -EINVAL;
14970 }
14971 }
14972
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014973 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14974 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014975 hdd_err("This concurrency combination is not allowed");
14976 return -ECONNREFUSED;
14977 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014978
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014979 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014980 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014981 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014982
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014983 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14984 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014985 SIR_UPDATE_REASON_JOIN_IBSS);
14986 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014987 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070014988 return -EINVAL;
14989 }
14990
14991 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014992 status = policy_mgr_wait_for_connection_update(
14993 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014994 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014995 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014996 return -EINVAL;
14997 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014998 }
14999
15000 /*Try disconnecting if already in connected state */
15001 status = wlan_hdd_try_disconnect(pAdapter);
15002 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015003 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015004 return -EALREADY;
15005 }
15006
15007 pRoamProfile = &pWextState->roamProfile;
15008
15009 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015010 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015011 return -EINVAL;
15012 }
15013
15014 /* enable selected protection checks in IBSS mode */
15015 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
15016
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015017 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015018 WNI_CFG_IBSS_ATIM_WIN_SIZE,
15019 pHddCtx->config->
15020 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015021 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015022 }
15023
15024 /* BSSID is provided by upper layers hence no need to AUTO generate */
15025 if (NULL != params->bssid) {
15026 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015027 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015028 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015029 return -EIO;
15030 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015031 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015032 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
15033 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015034 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015035 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015036 return -EIO;
15037 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053015038 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015039 }
15040 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
15041 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
15042 pRoamProfile->beaconInterval = params->beacon_interval;
15043 else {
15044 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015045 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015046 params->beacon_interval, pRoamProfile->beaconInterval);
15047 }
15048
15049 /* Set Channel */
15050 if (channelNum) {
15051 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015052 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015053 pRoamProfile->ChannelInfo.numOfChannels = 1;
15054 pHddStaCtx->conn_info.operationChannel = channelNum;
15055 pRoamProfile->ChannelInfo.ChannelList =
15056 &pHddStaCtx->conn_info.operationChannel;
15057 }
15058
15059 /* Initialize security parameters */
15060 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
15061 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015062 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015063 return status;
15064 }
15065
15066 /* Issue connect start */
15067 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
15068 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015069 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015070 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015071 operationChannel,
15072 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015073
15074 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015075 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015076 return status;
15077 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015078 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015079 return 0;
15080}
15081
15082/**
15083 * wlan_hdd_cfg80211_join_ibss() - join ibss
15084 * @wiphy: Pointer to wiphy
15085 * @dev: Pointer to network device
15086 * @param: Pointer to IBSS join parameters
15087 *
15088 * This function is used to create/join an IBSS network
15089 *
15090 * Return: 0 for success, non-zero for failure
15091 */
15092static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15093 struct net_device *dev,
15094 struct cfg80211_ibss_params *params)
15095{
15096 int ret = 0;
15097
15098 cds_ssr_protect(__func__);
15099 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
15100 cds_ssr_unprotect(__func__);
15101
15102 return ret;
15103}
15104
15105/**
15106 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
15107 * @wiphy: Pointer to wiphy
15108 * @dev: Pointer to network device
15109 *
15110 * This function is used to leave an IBSS network
15111 *
15112 * Return: 0 for success, non-zero for failure
15113 */
15114static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15115 struct net_device *dev)
15116{
15117 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15118 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15119 tCsrRoamProfile *pRoamProfile;
15120 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15121 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015122 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015123 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015124 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015125
15126 ENTER();
15127
Anurag Chouhan6d760662016-02-20 16:05:43 +053015128 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015129 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015130 return -EINVAL;
15131 }
15132
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015133 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015134 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015135 return -EINVAL;
15136 }
15137
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015138 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015139 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
15140 pAdapter->sessionId,
15141 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
15142 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015143 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015144 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015145
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015146 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015147 hdd_device_mode_to_string(pAdapter->device_mode),
15148 pAdapter->device_mode);
15149 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015150 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015151 return -EIO;
15152 }
15153
15154 pRoamProfile = &pWextState->roamProfile;
15155
15156 /* Issue disconnect only if interface type is set to IBSS */
15157 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015158 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015159 return -EINVAL;
15160 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015161 /* Clearing add IE of beacon */
15162 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
15163 sizeof(tSirMacAddr));
15164 updateIE.smeSessionId = pAdapter->sessionId;
15165 updateIE.ieBufferlength = 0;
15166 updateIE.pAdditionIEBuffer = NULL;
15167 updateIE.append = true;
15168 updateIE.notify = true;
15169 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
15170 &updateIE,
15171 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015172 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015173 }
15174
15175 /* Reset WNI_CFG_PROBE_RSP Flags */
15176 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015177
15178 /* Issue Disconnect request */
15179 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15180 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15181 pAdapter->sessionId,
15182 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015183 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015184 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015185 hal_status);
15186 return -EAGAIN;
15187 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015188
15189 /* wait for mc thread to cleanup and then return to upper stack
15190 * so by the time upper layer calls the change interface, we are
15191 * all set to proceed further
15192 */
15193 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15194 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
15195 if (!rc) {
15196 hdd_err("Failed to disconnect, timed out");
15197 return -ETIMEDOUT;
15198 }
15199
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015200 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015201 return 0;
15202}
15203
15204/**
15205 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15206 * @wiphy: Pointer to wiphy
15207 * @dev: Pointer to network device
15208 *
15209 * This function is used to leave an IBSS network
15210 *
15211 * Return: 0 for success, non-zero for failure
15212 */
15213static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15214 struct net_device *dev)
15215{
15216 int ret = 0;
15217
15218 cds_ssr_protect(__func__);
15219 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15220 cds_ssr_unprotect(__func__);
15221
15222 return ret;
15223}
15224
15225/**
15226 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15227 * @wiphy: Pointer to wiphy
15228 * @changed: Parameters changed
15229 *
15230 * This function is used to set the phy parameters. RTS Threshold/FRAG
15231 * Threshold/Retry Count etc.
15232 *
15233 * Return: 0 for success, non-zero for failure
15234 */
15235static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15236 u32 changed)
15237{
15238 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15239 tHalHandle hHal = pHddCtx->hHal;
15240 int status;
15241
15242 ENTER();
15243
Anurag Chouhan6d760662016-02-20 16:05:43 +053015244 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015245 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015246 return -EINVAL;
15247 }
15248
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015249 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015250 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15251 NO_SESSION, wiphy->rts_threshold));
15252 status = wlan_hdd_validate_context(pHddCtx);
15253
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015254 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015255 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015256
15257 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15258 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15259 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15260
15261 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15262 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015263 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015264 rts_threshold);
15265 return -EINVAL;
15266 }
15267
15268 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15269 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015270 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015271 rts_threshold);
15272 return -EIO;
15273 }
15274
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015275 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015276 }
15277
15278 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15279 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15280 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15281 wiphy->frag_threshold;
15282
15283 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15284 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015285 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015286 frag_threshold);
15287 return -EINVAL;
15288 }
15289
15290 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15291 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015292 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015293 frag_threshold);
15294 return -EIO;
15295 }
15296
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015297 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015298 }
15299
15300 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15301 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15302 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15303 wiphy->retry_short : wiphy->retry_long;
15304
15305 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15306 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015307 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015308 return -EINVAL;
15309 }
15310
15311 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15312 if (0 != sme_cfg_set_int(hHal,
15313 WNI_CFG_LONG_RETRY_LIMIT,
15314 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015315 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015316 retry_value);
15317 return -EIO;
15318 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015319 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015320 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15321 if (0 != sme_cfg_set_int(hHal,
15322 WNI_CFG_SHORT_RETRY_LIMIT,
15323 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015324 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015325 retry_value);
15326 return -EIO;
15327 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015328 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015329 }
15330 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015331 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015332 return 0;
15333}
15334
15335/**
15336 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15337 * @wiphy: Pointer to wiphy
15338 * @changed: Parameters changed
15339 *
15340 * Return: 0 for success, non-zero for failure
15341 */
15342static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15343{
15344 int ret;
15345
15346 cds_ssr_protect(__func__);
15347 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15348 cds_ssr_unprotect(__func__);
15349
15350 return ret;
15351}
15352
15353/**
15354 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15355 * key
15356 * @wiphy: Pointer to wiphy
15357 * @dev: Pointer to network device
15358 * @key_index: Key index
15359 *
15360 * Return: 0
15361 */
15362static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15363 struct net_device *netdev,
15364 u8 key_index)
15365{
15366 ENTER();
15367 return 0;
15368}
15369
15370/**
15371 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15372 * wlan_hdd_set_default_mgmt_key
15373 * @wiphy: pointer to wiphy
15374 * @netdev: pointer to net_device structure
15375 * @key_index: key index
15376 *
15377 * Return: 0 on success, error number on failure
15378 */
15379static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15380 struct net_device *netdev,
15381 u8 key_index)
15382{
15383 int ret;
15384
15385 cds_ssr_protect(__func__);
15386 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15387 cds_ssr_unprotect(__func__);
15388
15389 return ret;
15390}
15391
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015392/**
15393 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15394 * @wiphy: Pointer to wiphy
15395 * @dev: Pointer to network device
15396 * @params: Pointer to tx queue parameters
15397 *
15398 * Return: 0
15399 */
15400static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15401 struct net_device *dev,
15402 struct ieee80211_txq_params *params)
15403{
15404 ENTER();
15405 return 0;
15406}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015407
15408/**
15409 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15410 * @wiphy: pointer to wiphy
15411 * @netdev: pointer to net_device structure
15412 * @params: pointer to ieee80211_txq_params
15413 *
15414 * Return: 0 on success, error number on failure
15415 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015416static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15417 struct net_device *dev,
15418 struct ieee80211_txq_params *params)
15419{
15420 int ret;
15421
15422 cds_ssr_protect(__func__);
15423 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15424 cds_ssr_unprotect(__func__);
15425
15426 return ret;
15427}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015428
15429/**
15430 * __wlan_hdd_cfg80211_del_station() - delete station v2
15431 * @wiphy: Pointer to wiphy
15432 * @param: Pointer to delete station parameter
15433 *
15434 * Return: 0 for success, non-zero for failure
15435 */
15436static
15437int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15438 struct net_device *dev,
15439 struct tagCsrDelStaParams *pDelStaParams)
15440{
15441 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15442 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015443 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015444 hdd_hostapd_state_t *hapd_state;
15445 int status;
15446 uint8_t staId;
15447 uint8_t *mac;
15448
15449 ENTER();
15450
Anurag Chouhan6d760662016-02-20 16:05:43 +053015451 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015452 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015453 return -EINVAL;
15454 }
15455
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015456 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015457 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015458 return -EINVAL;
15459 }
15460
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015461 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015462 TRACE_CODE_HDD_CFG80211_DEL_STA,
15463 pAdapter->sessionId, pAdapter->device_mode));
15464
15465 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15466 status = wlan_hdd_validate_context(pHddCtx);
15467
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015468 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015469 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015470
15471 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15472
Krunal Sonib4326f22016-03-10 13:05:51 -080015473 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15474 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015475
15476 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15477 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015478 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015479 return 0;
15480 }
15481
Anurag Chouhanc5548422016-02-24 18:33:27 +053015482 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015483 uint16_t i;
15484 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15485 if ((pAdapter->aStaInfo[i].isUsed) &&
15486 (!pAdapter->aStaInfo[i].
15487 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015488 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015489 mac,
15490 pAdapter->aStaInfo[i].
15491 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015492 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015493 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15494 hdd_ipa_wlan_evt(pAdapter,
15495 pAdapter->
15496 aStaInfo[i].
15497 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015498 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015499 mac);
15500 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015501 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015502 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015503 MAC_ADDR_ARRAY(mac));
15504
15505 if (pHddCtx->dev_dfs_cac_status ==
15506 DFS_CAC_IN_PROGRESS)
15507 goto fn_end;
15508
Wei Song2f76f642016-11-18 16:32:53 +080015509 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015510 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015511 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015512 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015513 hdd_softap_sta_deauth(pAdapter,
15514 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015515 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015516 pAdapter->aStaInfo[i].
15517 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015518 qdf_status =
15519 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015520 &hapd_state->
15521 qdf_sta_disassoc_event,
15522 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015523 if (!QDF_IS_STATUS_SUCCESS(
15524 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015525 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015526 }
15527 }
15528 }
15529 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015530 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015531 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015532 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015533 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015534 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015535 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015536 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015537 MAC_ADDR_ARRAY(mac));
15538 return -ENOENT;
15539 }
15540
15541 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15542 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015543 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015544 }
15545
15546 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15547 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015548 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015549 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015550 MAC_ADDR_ARRAY(mac));
15551 return -ENOENT;
15552 }
15553
15554 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15555
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015556 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015557 MAC_ADDR_ARRAY(mac));
15558
15559 /* Case: SAP in ACS selected DFS ch and client connected
15560 * Now Radar detected. Then if random channel is another
15561 * DFS ch then new CAC is initiated and no TX allowed.
15562 * So do not send any mgmt frames as it will timeout
15563 * during CAC.
15564 */
15565
15566 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15567 goto fn_end;
15568
Wei Song2f76f642016-11-18 16:32:53 +080015569 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015570 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15571 (pAdapter), pAdapter->sessionId,
15572 (uint8_t *)&pDelStaParams->peerMacAddr,
15573 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015574 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015575 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015576 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015577 pAdapter->aStaInfo[staId].isDeauthInProgress =
15578 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015579 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015580 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015581 MAC_ADDR_ARRAY(mac));
15582 return -ENOENT;
15583 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015584 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015585 &hapd_state->
15586 qdf_sta_disassoc_event,
15587 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015588 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015589 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015590 }
15591 }
15592 }
15593
15594fn_end:
15595 EXIT();
15596 return 0;
15597}
15598
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015599#if defined(USE_CFG80211_DEL_STA_V2)
15600/**
15601 * wlan_hdd_del_station() - delete station wrapper
15602 * @adapter: pointer to the hdd adapter
15603 *
15604 * Return: None
15605 */
15606void wlan_hdd_del_station(hdd_adapter_t *adapter)
15607{
15608 struct station_del_parameters del_sta;
15609 del_sta.mac = NULL;
15610 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15611 del_sta.reason_code = eCsrForcedDeauthSta;
15612
15613 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15614 &del_sta);
15615}
15616#else
15617void wlan_hdd_del_station(hdd_adapter_t *adapter)
15618{
15619 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15620}
15621#endif
15622
15623#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015624/**
15625 * wlan_hdd_cfg80211_del_station() - delete station v2
15626 * @wiphy: Pointer to wiphy
15627 * @param: Pointer to delete station parameter
15628 *
15629 * Return: 0 for success, non-zero for failure
15630 */
15631int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15632 struct net_device *dev,
15633 struct station_del_parameters *param)
15634#else
15635/**
15636 * wlan_hdd_cfg80211_del_station() - delete station
15637 * @wiphy: Pointer to wiphy
15638 * @mac: Pointer to station mac address
15639 *
15640 * Return: 0 for success, non-zero for failure
15641 */
15642#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15643int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15644 struct net_device *dev,
15645 const uint8_t *mac)
15646#else
15647int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15648 struct net_device *dev,
15649 uint8_t *mac)
15650#endif
15651#endif
15652{
15653 int ret;
15654 struct tagCsrDelStaParams delStaParams;
15655
15656 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015657#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015658 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015659 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015660 return -EINVAL;
15661 }
15662 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15663 param->subtype, &delStaParams);
15664#else
15665 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15666 (SIR_MAC_MGMT_DEAUTH >> 4),
15667 &delStaParams);
15668#endif
15669 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15670 cds_ssr_unprotect(__func__);
15671
15672 return ret;
15673}
15674
15675/**
15676 * __wlan_hdd_cfg80211_add_station() - add station
15677 * @wiphy: Pointer to wiphy
15678 * @mac: Pointer to station mac address
15679 * @pmksa: Pointer to add station parameter
15680 *
15681 * Return: 0 for success, non-zero for failure
15682 */
15683static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15684 struct net_device *dev,
15685 const uint8_t *mac,
15686 struct station_parameters *params)
15687{
15688 int status = -EPERM;
15689#ifdef FEATURE_WLAN_TDLS
15690 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15691 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15692 u32 mask, set;
15693
15694 ENTER();
15695
Anurag Chouhan6d760662016-02-20 16:05:43 +053015696 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015697 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015698 return -EINVAL;
15699 }
15700
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015701 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015702 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015703 return -EINVAL;
15704 }
15705
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015706 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015707 TRACE_CODE_HDD_CFG80211_ADD_STA,
15708 pAdapter->sessionId, params->listen_interval));
15709
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015710 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015711 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015712
15713 mask = params->sta_flags_mask;
15714
15715 set = params->sta_flags_set;
15716
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015717 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015718 MAC_ADDR_ARRAY(mac));
15719
15720 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15721 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080015722#if defined(CONVERGED_TDLS_ENABLE)
15723 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
15724 dev, mac);
15725#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015726 status =
15727 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080015728#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015729 }
15730 }
15731#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015732 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015733 return status;
15734}
15735
15736/**
15737 * wlan_hdd_cfg80211_add_station() - add station
15738 * @wiphy: Pointer to wiphy
15739 * @mac: Pointer to station mac address
15740 * @pmksa: Pointer to add station parameter
15741 *
15742 * Return: 0 for success, non-zero for failure
15743 */
15744#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15745static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15746 struct net_device *dev,
15747 const uint8_t *mac,
15748 struct station_parameters *params)
15749#else
15750static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15751 struct net_device *dev, uint8_t *mac,
15752 struct station_parameters *params)
15753#endif
15754{
15755 int ret;
15756
15757 cds_ssr_protect(__func__);
15758 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15759 cds_ssr_unprotect(__func__);
15760
15761 return ret;
15762}
15763
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015764/**
15765 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15766 * @wiphy: Pointer to wiphy
15767 * @dev: Pointer to network device
15768 * @pmksa: Pointer to set pmksa parameter
15769 *
15770 * Return: 0 for success, non-zero for failure
15771 */
15772static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15773 struct net_device *dev,
15774 struct cfg80211_pmksa *pmksa)
15775{
15776 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15777 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15778 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015779 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015780 int status;
15781 tPmkidCacheInfo pmk_id;
15782
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015783 ENTER();
15784
Anurag Chouhan6d760662016-02-20 16:05:43 +053015785 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015786 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015787 return -EINVAL;
15788 }
15789
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015790 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015791 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015792 return -EINVAL;
15793 }
15794
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015795 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015796 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015797 return -EINVAL;
15798 }
15799
15800 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015801 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015802 pmksa->bssid, pmksa->pmkid);
15803 return -EINVAL;
15804 }
15805
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015806 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015807 MAC_ADDR_ARRAY(pmksa->bssid));
15808
15809 status = wlan_hdd_validate_context(pHddCtx);
15810
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015811 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015812 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015813
15814 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15815
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015816 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15817 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015818
15819 /* Add to the PMKSA ID Cache in CSR */
15820 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15821 &pmk_id, 1, false);
15822
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015823 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015824 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15825 pAdapter->sessionId, result));
15826
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015827 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015828 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015829}
15830
15831/**
15832 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15833 * @wiphy: Pointer to wiphy
15834 * @dev: Pointer to network device
15835 * @pmksa: Pointer to set pmksa parameter
15836 *
15837 * Return: 0 for success, non-zero for failure
15838 */
15839static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15840 struct net_device *dev,
15841 struct cfg80211_pmksa *pmksa)
15842{
15843 int ret;
15844
15845 cds_ssr_protect(__func__);
15846 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15847 cds_ssr_unprotect(__func__);
15848
15849 return ret;
15850}
15851
15852/**
15853 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15854 * @wiphy: Pointer to wiphy
15855 * @dev: Pointer to network device
15856 * @pmksa: Pointer to pmksa parameter
15857 *
15858 * Return: 0 for success, non-zero for failure
15859 */
15860static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15861 struct net_device *dev,
15862 struct cfg80211_pmksa *pmksa)
15863{
15864 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15865 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15866 tHalHandle halHandle;
15867 int status = 0;
15868
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015869 ENTER();
15870
Anurag Chouhan6d760662016-02-20 16:05:43 +053015871 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015872 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015873 return -EINVAL;
15874 }
15875
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015876 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15877 hdd_err("invalid session id: %d", pAdapter->sessionId);
15878 return -EINVAL;
15879 }
15880
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015881 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015882 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015883 return -EINVAL;
15884 }
15885
15886 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015887 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015888 return -EINVAL;
15889 }
15890
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015891 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015892 MAC_ADDR_ARRAY(pmksa->bssid));
15893
15894 status = wlan_hdd_validate_context(pHddCtx);
15895
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015896 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015897 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015898
15899 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15900
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015901 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015902 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15903 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015904 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015905 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015906 sme_roam_del_pmkid_from_cache(halHandle,
15907 pAdapter->sessionId, pmksa->bssid,
15908 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015909 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015910 MAC_ADDR_ARRAY(pmksa->bssid));
15911 status = -EINVAL;
15912 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015913 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015914 return status;
15915}
15916
15917/**
15918 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15919 * @wiphy: Pointer to wiphy
15920 * @dev: Pointer to network device
15921 * @pmksa: Pointer to pmksa parameter
15922 *
15923 * Return: 0 for success, non-zero for failure
15924 */
15925static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15926 struct net_device *dev,
15927 struct cfg80211_pmksa *pmksa)
15928{
15929 int ret;
15930
15931 cds_ssr_protect(__func__);
15932 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15933 cds_ssr_unprotect(__func__);
15934
15935 return ret;
15936
15937}
15938
15939/**
15940 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15941 * @wiphy: Pointer to wiphy
15942 * @dev: Pointer to network device
15943 *
15944 * Return: 0 for success, non-zero for failure
15945 */
15946static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15947 struct net_device *dev)
15948{
15949 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15950 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15951 tHalHandle halHandle;
15952 int status = 0;
15953
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015954 ENTER();
15955
Anurag Chouhan6d760662016-02-20 16:05:43 +053015956 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015957 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015958 return -EINVAL;
15959 }
15960
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015961 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15962 hdd_err("invalid session id: %d", pAdapter->sessionId);
15963 return -EINVAL;
15964 }
15965
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015966 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015967
15968 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15969 status = wlan_hdd_validate_context(pHddCtx);
15970
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015971 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015972 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015973
15974 /* Retrieve halHandle */
15975 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15976
15977 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015978 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015979 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15980 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015981 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015982 status = -EINVAL;
15983 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015984 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015985 return status;
15986}
15987
15988/**
15989 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15990 * @wiphy: Pointer to wiphy
15991 * @dev: Pointer to network device
15992 *
15993 * Return: 0 for success, non-zero for failure
15994 */
15995static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15996 struct net_device *dev)
15997{
15998 int ret;
15999
16000 cds_ssr_protect(__func__);
16001 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
16002 cds_ssr_unprotect(__func__);
16003
16004 return ret;
16005}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016006
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016007#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016008/**
16009 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16010 * @wiphy: Pointer to wiphy
16011 * @dev: Pointer to network device
16012 * @ftie: Pointer to fast transition ie parameter
16013 *
16014 * Return: 0 for success, non-zero for failure
16015 */
16016static int
16017__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16018 struct net_device *dev,
16019 struct cfg80211_update_ft_ies_params *ftie)
16020{
16021 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16022 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16023 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
16024 int status;
16025
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016026 ENTER();
16027
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016028 status = wlan_hdd_validate_context(hdd_ctx);
16029 if (status)
16030 return status;
16031
Anurag Chouhan6d760662016-02-20 16:05:43 +053016032 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016033 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016034 return -EINVAL;
16035 }
16036
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016037 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16038 hdd_err("invalid session id: %d", pAdapter->sessionId);
16039 return -EINVAL;
16040 }
16041
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016042 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016043 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
16044 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
16045 /* Added for debug on reception of Re-assoc Req. */
16046 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016047 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016048 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016049 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016050 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016051 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016052 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016053
16054 /* Pass the received FT IEs to SME */
16055 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
16056 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016057 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016058 return 0;
16059}
16060
16061/**
16062 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16063 * @wiphy: Pointer to wiphy
16064 * @dev: Pointer to network device
16065 * @ftie: Pointer to fast transition ie parameter
16066 *
16067 * Return: 0 for success, non-zero for failure
16068 */
16069static int
16070wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16071 struct net_device *dev,
16072 struct cfg80211_update_ft_ies_params *ftie)
16073{
16074 int ret;
16075
16076 cds_ssr_protect(__func__);
16077 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
16078 cds_ssr_unprotect(__func__);
16079
16080 return ret;
16081}
16082#endif
16083
Mukul Sharma3d36c392017-01-18 18:39:12 +053016084void wlan_hdd_cfg80211_update_replay_counter_callback(
16085 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
16086
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016087{
Mukul Sharma3d36c392017-01-18 18:39:12 +053016088 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
16089 uint8_t temp_replay_counter[8];
16090 int i;
16091 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016092
16093 ENTER();
16094
Mukul Sharma3d36c392017-01-18 18:39:12 +053016095 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016096 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016097 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016098 }
16099
Mukul Sharma3d36c392017-01-18 18:39:12 +053016100 if (!gtk_rsp_param) {
16101 hdd_err("gtk_rsp_param is Null");
16102 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016103 }
16104
Mukul Sharma3d36c392017-01-18 18:39:12 +053016105 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016106 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016107 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016108 }
16109
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016110 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016111 gtk_rsp_param->replay_counter);
16112 /* convert little to big endian since supplicant works on big endian */
16113 p = (uint8_t *)&gtk_rsp_param->replay_counter;
16114 for (i = 0; i < 8; i++)
16115 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016116
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016117 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016118 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080016119 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016120 gtk_rsp_param->bssid.bytes,
16121 temp_replay_counter, GFP_KERNEL);
16122out:
16123 EXIT();
16124
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016125}
16126
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016127static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016128int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016129 struct net_device *dev,
16130 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016131{
16132 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016133 int result, i;
16134 struct pmo_gtk_req *gtk_req = NULL;
16135 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
16136 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016137 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016138
16139 ENTER();
16140
Anurag Chouhan6d760662016-02-20 16:05:43 +053016141 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016142 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016143 result = -EINVAL;
16144 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016145 }
16146
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016147 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16148 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016149 result = -EINVAL;
16150 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016151 }
16152
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016153 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016154 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
16155 pAdapter->sessionId, pAdapter->device_mode));
16156
Mukul Sharma3d36c392017-01-18 18:39:12 +053016157 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016158 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053016159 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016160
Mukul Sharma3d36c392017-01-18 18:39:12 +053016161 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
16162 if (!gtk_req) {
16163 hdd_err("cannot allocate gtk_req");
16164 result = -ENOMEM;
16165 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016166 }
16167
Mukul Sharma3d36c392017-01-18 18:39:12 +053016168 /* convert big to little endian since driver work on little endian */
16169 buf = (uint8_t *)&gtk_req->replay_counter;
16170 for (i = 0; i < 8; i++)
16171 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016172
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016173 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016174 gtk_req->replay_counter);
16175 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
16176 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
16177 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
16178 if (status != QDF_STATUS_SUCCESS) {
16179 hdd_err("Failed to cache GTK Offload");
16180 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016181 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053016182out:
16183 if (gtk_req)
16184 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016185 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053016186
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016187 return result;
16188}
16189
16190/**
16191 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
16192 * @wiphy: Pointer to wiphy
16193 * @dev: Pointer to network device
16194 * @data: Pointer to rekey data
16195 *
16196 * This function is used to offload GTK rekeying job to the firmware.
16197 *
16198 * Return: 0 for success, non-zero for failure
16199 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016200static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016201int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16202 struct net_device *dev,
16203 struct cfg80211_gtk_rekey_data *data)
16204{
16205 int ret;
16206
16207 cds_ssr_protect(__func__);
16208 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16209 cds_ssr_unprotect(__func__);
16210
16211 return ret;
16212}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016213
16214/**
16215 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16216 * @wiphy: Pointer to wiphy
16217 * @dev: Pointer to network device
16218 * @param: Pointer to access control parameter
16219 *
16220 * Return: 0 for success, non-zero for failure
16221 */
16222static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16223 struct net_device *dev,
16224 const struct cfg80211_acl_data *params)
16225{
16226 int i;
16227 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16228 hdd_hostapd_state_t *pHostapdState;
16229 tsap_Config_t *pConfig;
16230 v_CONTEXT_t p_cds_context = NULL;
16231 hdd_context_t *pHddCtx;
16232 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016233 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016234
16235 ENTER();
16236
Anurag Chouhan6d760662016-02-20 16:05:43 +053016237 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016238 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016239 return -EINVAL;
16240 }
16241
16242 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016243 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016244 return -EINVAL;
16245 }
16246
16247 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16248 status = wlan_hdd_validate_context(pHddCtx);
16249
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016250 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016251 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016252
16253 p_cds_context = pHddCtx->pcds_context;
16254 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16255
16256 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016257 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016258 return -EINVAL;
16259 }
16260
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016261 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016262 params->n_acl_entries);
16263
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016264 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016265 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16266 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016267 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016268 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16269
16270 /* default value */
16271 pConfig->num_accept_mac = 0;
16272 pConfig->num_deny_mac = 0;
16273
16274 /**
16275 * access control policy
16276 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16277 * listed in hostapd.deny file.
16278 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16279 * listed in hostapd.accept file.
16280 */
16281 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16282 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16283 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16284 params->acl_policy) {
16285 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16286 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016287 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016288 params->acl_policy);
16289 return -ENOTSUPP;
16290 }
16291
16292 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16293 pConfig->num_accept_mac = params->n_acl_entries;
16294 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016295 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016296 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016297 MAC_ADDR_ARRAY(
16298 params->mac_addrs[i].addr));
16299
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016300 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016301 params->mac_addrs[i].addr,
16302 sizeof(qcmacaddr));
16303 }
16304 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16305 pConfig->num_deny_mac = params->n_acl_entries;
16306 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016307 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016308 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016309 MAC_ADDR_ARRAY(
16310 params->mac_addrs[i].addr));
16311
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016312 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016313 params->mac_addrs[i].addr,
16314 sizeof(qcmacaddr));
16315 }
16316 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016317 qdf_status = wlansap_set_mac_acl(
16318 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016319 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016320 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016321 return -EINVAL;
16322 }
16323 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016324 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016325 hdd_device_mode_to_string(pAdapter->device_mode),
16326 pAdapter->device_mode);
16327 return -EINVAL;
16328 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016329 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016330 return 0;
16331}
16332
16333/**
16334 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16335 * __wlan_hdd_cfg80211_set_mac_acl
16336 * @wiphy: pointer to wiphy structure
16337 * @dev: pointer to net_device
16338 * @params: pointer to cfg80211_acl_data
16339 *
16340 * Return; 0 on success, error number otherwise
16341 */
16342static int
16343wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16344 struct net_device *dev,
16345 const struct cfg80211_acl_data *params)
16346{
16347 int ret;
16348
16349 cds_ssr_protect(__func__);
16350 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16351 cds_ssr_unprotect(__func__);
16352
16353 return ret;
16354}
16355
16356#ifdef WLAN_NL80211_TESTMODE
16357#ifdef FEATURE_WLAN_LPHB
16358/**
16359 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16360 * @pHddCtx: Pointer to hdd context
16361 * @lphbInd: Pointer to low power heart beat indication parameter
16362 *
16363 * Return: none
16364 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016365static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016366 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016367{
16368 struct sk_buff *skb;
16369
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016370 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016371
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016372 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016373 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016374
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016375 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016376 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016377 return;
16378 }
16379
16380 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016381 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016382 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016383 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016384 return;
16385 }
16386
16387 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016388 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016389 goto nla_put_failure;
16390 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016391 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016392 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016393 goto nla_put_failure;
16394 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016395 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16396 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016397 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016398 goto nla_put_failure;
16399 }
16400 cfg80211_testmode_event(skb, GFP_ATOMIC);
16401 return;
16402
16403nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016404 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016405 kfree_skb(skb);
16406
16407 return;
16408}
16409#endif /* FEATURE_WLAN_LPHB */
16410
16411/**
16412 * __wlan_hdd_cfg80211_testmode() - test mode
16413 * @wiphy: Pointer to wiphy
16414 * @data: Data pointer
16415 * @len: Data length
16416 *
16417 * Return: 0 for success, non-zero for failure
16418 */
16419static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16420 void *data, int len)
16421{
16422 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16423 int err;
16424 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16425
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016426 ENTER();
16427
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016428 err = wlan_hdd_validate_context(pHddCtx);
16429 if (err)
16430 return err;
16431
16432 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16433 len, wlan_hdd_tm_policy);
16434 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016435 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016436 return err;
16437 }
16438
16439 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016440 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016441 return -EINVAL;
16442 }
16443
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016444 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016445 TRACE_CODE_HDD_CFG80211_TESTMODE,
16446 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016447 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16448#ifdef FEATURE_WLAN_LPHB
16449 /* Low Power Heartbeat configuration request */
16450 case WLAN_HDD_TM_CMD_WLAN_HB:
16451 {
16452 int buf_len;
16453 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016454 struct pmo_lphb_req *hb_params = NULL;
16455 struct pmo_lphb_req *hb_params_temp = NULL;
16456 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016457
16458 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016459 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016460 return -EINVAL;
16461 }
16462
16463 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16464 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16465
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016466 hb_params_temp = (struct pmo_lphb_req *) buf;
16467 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16468 && (hb_params_temp->params.lphb_tcp_params.
16469 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016470 return -EINVAL;
16471
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016472 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16473 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016474 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016475 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016476 return -ENOMEM;
16477 }
16478
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016479 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016480 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16481 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016482 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016483 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016484 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016485
16486 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016487 return 0;
16488 }
16489#endif /* FEATURE_WLAN_LPHB */
16490
16491#if defined(QCA_WIFI_FTM)
16492 case WLAN_HDD_TM_CMD_WLAN_FTM:
16493 {
16494 int buf_len;
16495 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016496 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016497 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016498 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016499 return -EINVAL;
16500 }
16501
16502 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16503 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16504
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016505 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016506
16507 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16508
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016509 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016510 err = -EBUSY;
16511 break;
16512 }
16513#endif
16514
16515 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016516 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016517 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16518 return -EOPNOTSUPP;
16519 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016520 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016521 return err;
16522}
16523
16524/**
16525 * wlan_hdd_cfg80211_testmode() - test mode
16526 * @wiphy: Pointer to wiphy
16527 * @dev: Pointer to network device
16528 * @data: Data pointer
16529 * @len: Data length
16530 *
16531 * Return: 0 for success, non-zero for failure
16532 */
16533static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16534#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16535 struct wireless_dev *wdev,
16536#endif
16537 void *data, int len)
16538{
16539 int ret;
16540
16541 cds_ssr_protect(__func__);
16542 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16543 cds_ssr_unprotect(__func__);
16544
16545 return ret;
16546}
16547
16548#if defined(QCA_WIFI_FTM)
16549/**
16550 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16551 * @buf: Pointer to buffer
16552 * @buf_len: Buffer length
16553 *
16554 * Return: none
16555 */
16556void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16557{
16558 struct sk_buff *skb;
16559 hdd_context_t *hdd_ctx;
16560
16561 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016562 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016563 return;
16564 }
16565
Anurag Chouhan6d760662016-02-20 16:05:43 +053016566 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016567 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016568 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016569 return;
16570 }
16571
16572 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16573 buf_len, GFP_KERNEL);
16574 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016575 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016576 return;
16577 }
16578
16579 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16580 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16581 goto nla_put_failure;
16582
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016583 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016584
16585 cfg80211_testmode_event(skb, GFP_KERNEL);
16586 return;
16587
16588nla_put_failure:
16589 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016590 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016591}
16592#endif
16593#endif /* CONFIG_NL80211_TESTMODE */
16594
16595#ifdef QCA_HT_2040_COEX
16596/**
16597 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16598 * @wiphy: Pointer to wiphy
16599 * @dev: Pointer to network device
16600 * @chandef: Pointer to channel definition parameter
16601 *
16602 * Return: 0 for success, non-zero for failure
16603 */
16604static int
16605__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16606 struct net_device *dev,
16607 struct cfg80211_chan_def *chandef)
16608{
16609 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16610 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016611 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016612 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016613 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016614
Anurag Chouhan6d760662016-02-20 16:05:43 +053016615 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016616 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016617 return -EINVAL;
16618 }
16619
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016620 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16621 hdd_err("invalid session id: %d", pAdapter->sessionId);
16622 return -EINVAL;
16623 }
16624
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016625 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16626 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016627 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016628 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016629
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016630 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016631 sme_get_config_param(pHddCtx->hHal, &sme_config);
16632 switch (chandef->width) {
16633 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053016634 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016635 if (sme_config.csrConfig.channelBondingMode24GHz !=
16636 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16637 sme_config.csrConfig.channelBondingMode24GHz =
16638 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16639 sme_update_config(pHddCtx->hHal, &sme_config);
16640 cbModeChange = true;
16641 }
16642 break;
16643
16644 case NL80211_CHAN_WIDTH_40:
16645 if (sme_config.csrConfig.channelBondingMode24GHz ==
16646 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16647 if (NL80211_CHAN_HT40MINUS ==
16648 cfg80211_get_chandef_type(chandef))
16649 sme_config.csrConfig.channelBondingMode24GHz =
16650 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16651 else
16652 sme_config.csrConfig.channelBondingMode24GHz =
16653 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16654 sme_update_config(pHddCtx->hHal, &sme_config);
16655 cbModeChange = true;
16656 }
16657 break;
16658
16659 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016660 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016661 return -EINVAL;
16662 }
16663
16664 if (!cbModeChange)
16665 return 0;
16666
Krunal Sonib4326f22016-03-10 13:05:51 -080016667 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016668 return 0;
16669
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016670 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016671 sme_config.csrConfig.channelBondingMode24GHz);
16672
16673 /* Change SAP ht2040 mode */
16674 status = hdd_set_sap_ht2040_mode(pAdapter,
16675 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016676 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016677 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016678 return -EINVAL;
16679 }
16680
16681 return 0;
16682}
16683
16684/**
16685 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16686 * @wiphy: Pointer to wiphy
16687 * @dev: Pointer to network device
16688 * @chandef: Pointer to channel definition parameter
16689 *
16690 * Return: 0 for success, non-zero for failure
16691 */
16692static int
16693wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16694 struct net_device *dev,
16695 struct cfg80211_chan_def *chandef)
16696{
16697 int ret;
16698
16699 cds_ssr_protect(__func__);
16700 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16701 cds_ssr_unprotect(__func__);
16702
16703 return ret;
16704}
16705#endif
16706
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016707#ifdef CHANNEL_SWITCH_SUPPORTED
16708/**
16709 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16710 * channel in SAP/GO
16711 * @wiphy: wiphy pointer
16712 * @dev: dev pointer.
16713 * @csa_params: Change channel params
16714 *
16715 * This function is called to switch channel in SAP/GO
16716 *
16717 * Return: 0 if success else return non zero
16718 */
16719static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16720 struct net_device *dev,
16721 struct cfg80211_csa_settings *csa_params)
16722{
16723 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16724 hdd_context_t *hdd_ctx;
16725 uint8_t channel;
16726 uint16_t freq;
16727 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016728 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016729
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016730 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016731 csa_params->chandef.chan->center_freq);
16732
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016733 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16734 hdd_err("invalid session id: %d", adapter->sessionId);
16735 return -EINVAL;
16736 }
16737
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016738 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16739 ret = wlan_hdd_validate_context(hdd_ctx);
16740
16741 if (0 != ret)
16742 return ret;
16743
Krunal Sonib4326f22016-03-10 13:05:51 -080016744 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16745 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016746 return -ENOTSUPP;
16747
16748 freq = csa_params->chandef.chan->center_freq;
16749 channel = cds_freq_to_chan(freq);
16750
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016751 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16752
16753 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016754 return ret;
16755}
16756
16757/**
16758 * wlan_hdd_cfg80211_channel_switch()- function to switch
16759 * channel in SAP/GO
16760 * @wiphy: wiphy pointer
16761 * @dev: dev pointer.
16762 * @csa_params: Change channel params
16763 *
16764 * This function is called to switch channel in SAP/GO
16765 *
16766 * Return: 0 if success else return non zero
16767 */
16768static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16769 struct net_device *dev,
16770 struct cfg80211_csa_settings *csa_params)
16771{
16772 int ret;
16773
16774 cds_ssr_protect(__func__);
16775 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16776 cds_ssr_unprotect(__func__);
16777 return ret;
16778}
16779#endif
16780
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016781/**
16782 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16783 * translation from NL to policy manager type
16784 * @type: Generic connection mode type defined in NL
16785 *
16786 *
16787 * This function provides the type translation
16788 *
16789 * Return: cds_con_mode enum
16790 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016791enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016792 enum nl80211_iftype type)
16793{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016794 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016795 switch (type) {
16796 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016797 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016798 break;
16799 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016800 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016801 break;
16802 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016803 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016804 break;
16805 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016806 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016807 break;
16808 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016809 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016810 break;
16811 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016812 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016813 }
16814 return mode;
16815}
16816
16817/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016818 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16819 * @wiphy: Handle to struct wiphy to get handle to module context.
16820 * @chandef: Contains information about the capture channel to be set.
16821 *
16822 * This interface is called if and only if monitor mode interface alone is
16823 * active.
16824 *
16825 * Return: 0 success or error code on failure.
16826 */
16827static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16828 struct cfg80211_chan_def *chandef)
16829{
16830 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16831 hdd_adapter_t *adapter;
16832 hdd_station_ctx_t *sta_ctx;
16833 struct hdd_mon_set_ch_info *ch_info;
16834 QDF_STATUS status;
16835 tHalHandle hal_hdl;
16836 struct qdf_mac_addr bssid;
16837 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080016838 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016839 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016840 int ret;
16841 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16842
16843 ENTER();
16844
16845 ret = wlan_hdd_validate_context(hdd_ctx);
16846 if (ret)
16847 return ret;
16848
16849 hal_hdl = hdd_ctx->hHal;
16850
16851 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16852 if (!adapter)
16853 return -EIO;
16854
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016855 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016856 adapter->dev->name, chan_num, chandef->chan->center_freq);
16857
16858 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16859 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016860 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16861 roam_profile.ChannelInfo.numOfChannels = 1;
16862 roam_profile.phyMode = ch_info->phy_mode;
16863 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016864 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016865
16866 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16867 QDF_MAC_ADDR_SIZE);
16868
16869 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016870 /*
16871 * CDS api expects secondary channel for calculating
16872 * the channel params
16873 */
16874 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016875 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016876 if (chan_num >= 1 && chan_num <= 5)
16877 sec_ch = chan_num + 4;
16878 else if (chan_num >= 6 && chan_num <= 13)
16879 sec_ch = chan_num - 4;
16880 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016881 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
16882 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016883 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16884 &roam_profile);
16885 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016886 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016887 status);
16888 ret = qdf_status_to_os_return(status);
16889 return ret;
16890 }
16891 EXIT();
16892 return 0;
16893}
16894
16895/**
16896 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16897 * @wiphy: Handle to struct wiphy to get handle to module context.
16898 * @chandef: Contains information about the capture channel to be set.
16899 *
16900 * This interface is called if and only if monitor mode interface alone is
16901 * active.
16902 *
16903 * Return: 0 success or error code on failure.
16904 */
16905static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16906 struct cfg80211_chan_def *chandef)
16907{
16908 int ret;
16909
16910 cds_ssr_protect(__func__);
16911 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16912 cds_ssr_unprotect(__func__);
16913 return ret;
16914}
16915
16916/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016917 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16918 * @adapter: pointer to adapter
16919 *
16920 * Wrapper function to clear link layer stats.
16921 * return - void
16922 */
16923void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16924{
16925 tSirLLStatsClearReq link_layer_stats_clear_req;
16926 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16927
Mukul Sharma491021c2016-09-29 21:39:19 +053016928 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16929 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016930 link_layer_stats_clear_req.stopReq = 0;
16931 link_layer_stats_clear_req.reqId = 1;
16932 link_layer_stats_clear_req.staId = adapter->sessionId;
16933 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16934
16935 return;
16936}
16937
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016938/**
16939 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16940 * @adapter: HDD Adapter
16941 *
16942 * If roaming is in progress and there is a request to
16943 * disconnect the session, then it is deferred. Once
16944 * roaming is complete/aborted, then this routine is
16945 * used to resume the disconnect that was deferred
16946 *
16947 * Return: None
16948 */
16949void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16950{
16951 switch (adapter->defer_disconnect) {
16952 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16953 adapter->defer_disconnect = 0;
16954 wlan_hdd_disconnect(adapter,
16955 adapter->cfg80211_disconnect_reason);
16956 break;
16957 case DEFER_DISCONNECT_TRY_DISCONNECT:
16958 wlan_hdd_try_disconnect(adapter);
16959 adapter->defer_disconnect = 0;
16960 break;
16961 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016962 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016963 adapter->defer_disconnect);
16964 break;
16965 }
16966}
16967
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016968#define CNT_DIFF(cur, prev) \
16969 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16970#define MAX_COUNT 0xffffffff
16971static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16972 struct scan_chan_info *chan,
16973 struct scan_chan_info *info, uint32_t cmd_flag)
16974{
16975 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16976 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16977 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16978
16979 mutex_lock(&hdd_ctx->chan_info_lock);
16980
16981 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16982 qdf_mem_zero(chan, sizeof(*chan));
16983
16984 chan->freq = info->freq;
16985 chan->noise_floor = info->noise_floor;
16986 chan->clock_freq = info->clock_freq;
16987 chan->cmd_flag = info->cmd_flag;
16988 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16989
16990 chan->rx_clear_count =
16991 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16992
16993 chan->tx_frame_count =
16994 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16995
16996 mutex_unlock(&hdd_ctx->chan_info_lock);
16997
16998}
16999#undef CNT_DIFF
17000#undef MAX_COUNT
17001
17002/**
17003 * wlan_hdd_chan_info_cb() - channel info callback
17004 * @chan_info: struct scan_chan_info
17005 *
17006 * Store channel info into HDD context
17007 *
17008 * Return: None.
17009 */
17010static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
17011{
17012 hdd_context_t *hdd_ctx;
17013 struct scan_chan_info *chan;
17014 uint8_t idx;
17015
17016 ENTER();
17017
17018 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17019 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
17020 hdd_err("hdd_ctx is invalid");
17021 return;
17022 }
17023
17024 if (!hdd_ctx->chan_info) {
17025 hdd_err("chan_info is NULL");
17026 return;
17027 }
17028
17029 chan = hdd_ctx->chan_info;
17030 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
17031 if (chan[idx].freq == info->freq) {
17032 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
17033 info->cmd_flag);
17034 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
17035 chan[idx].cmd_flag, chan[idx].freq,
17036 chan[idx].noise_floor,
17037 chan[idx].cycle_count, chan[idx].rx_clear_count,
17038 chan[idx].clock_freq, chan[idx].cmd_flag,
17039 chan[idx].tx_frame_count, idx);
17040 if (chan[idx].freq == 0)
17041 break;
17042
17043 }
17044 }
17045
17046 EXIT();
17047}
17048
17049/**
17050 * wlan_hdd_init_chan_info() - init chan info in hdd context
17051 * @hdd_ctx: HDD context pointer
17052 *
17053 * Return: none
17054 */
17055void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
17056{
17057 uint8_t num_2g, num_5g, index = 0;
17058
17059 if (!hdd_ctx->config->fEnableSNRMonitoring) {
17060 hdd_info("SNR monitoring is disabled");
17061 return;
17062 }
17063
17064 hdd_ctx->chan_info =
17065 qdf_mem_malloc(sizeof(struct scan_chan_info)
17066 * QDF_MAX_NUM_CHAN);
17067 if (hdd_ctx->chan_info == NULL) {
17068 hdd_err("Failed to malloc for chan info");
17069 return;
17070 }
17071 mutex_init(&hdd_ctx->chan_info_lock);
17072
17073 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
17074 for (; index < num_2g; index++) {
17075 hdd_ctx->chan_info[index].freq =
17076 hdd_channels_2_4_ghz[index].center_freq;
17077 }
17078
17079 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
17080 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017081 if (WLAN_REG_IS_11P_CH(
17082 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017083 continue;
17084 hdd_ctx->chan_info[index].freq =
17085 hdd_channels_5_ghz[index - num_2g].center_freq;
17086 }
17087 sme_set_chan_info_callback(hdd_ctx->hHal,
17088 &wlan_hdd_chan_info_cb);
17089}
17090
17091/**
17092 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
17093 * @hdd_ctx: hdd context pointer
17094 *
17095 * Return: none
17096 */
17097void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
17098{
17099 struct scan_chan_info *chan;
17100
17101 chan = hdd_ctx->chan_info;
17102 hdd_ctx->chan_info = NULL;
17103 if (chan)
17104 qdf_mem_free(chan);
17105}
17106
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017107/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017108 * struct cfg80211_ops - cfg80211_ops
17109 *
17110 * @add_virtual_intf: Add virtual interface
17111 * @del_virtual_intf: Delete virtual interface
17112 * @change_virtual_intf: Change virtual interface
17113 * @change_station: Change station
17114 * @add_beacon: Add beacon in sap mode
17115 * @del_beacon: Delete beacon in sap mode
17116 * @set_beacon: Set beacon in sap mode
17117 * @start_ap: Start ap
17118 * @change_beacon: Change beacon
17119 * @stop_ap: Stop ap
17120 * @change_bss: Change bss
17121 * @add_key: Add key
17122 * @get_key: Get key
17123 * @del_key: Delete key
17124 * @set_default_key: Set default key
17125 * @set_channel: Set channel
17126 * @scan: Scan
17127 * @connect: Connect
17128 * @disconnect: Disconnect
17129 * @join_ibss = Join ibss
17130 * @leave_ibss = Leave ibss
17131 * @set_wiphy_params = Set wiphy params
17132 * @set_tx_power = Set tx power
17133 * @get_tx_power = get tx power
17134 * @remain_on_channel = Remain on channel
17135 * @cancel_remain_on_channel = Cancel remain on channel
17136 * @mgmt_tx = Tx management frame
17137 * @mgmt_tx_cancel_wait = Cancel management tx wait
17138 * @set_default_mgmt_key = Set default management key
17139 * @set_txq_params = Set tx queue parameters
17140 * @get_station = Get station
17141 * @set_power_mgmt = Set power management
17142 * @del_station = Delete station
17143 * @add_station = Add station
17144 * @set_pmksa = Set pmksa
17145 * @del_pmksa = Delete pmksa
17146 * @flush_pmksa = Flush pmksa
17147 * @update_ft_ies = Update FT IEs
17148 * @tdls_mgmt = Tdls management
17149 * @tdls_oper = Tdls operation
17150 * @set_rekey_data = Set rekey data
17151 * @sched_scan_start = Scheduled scan start
17152 * @sched_scan_stop = Scheduled scan stop
17153 * @resume = Resume wlan
17154 * @suspend = Suspend wlan
17155 * @set_mac_acl = Set mac acl
17156 * @testmode_cmd = Test mode command
17157 * @set_ap_chanwidth = Set AP channel bandwidth
17158 * @dump_survey = Dump survey
17159 * @key_mgmt_set_pmk = Set pmk key management
17160 */
17161static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
17162 .add_virtual_intf = wlan_hdd_add_virtual_intf,
17163 .del_virtual_intf = wlan_hdd_del_virtual_intf,
17164 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
17165 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017166 .start_ap = wlan_hdd_cfg80211_start_ap,
17167 .change_beacon = wlan_hdd_cfg80211_change_beacon,
17168 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017169 .change_bss = wlan_hdd_cfg80211_change_bss,
17170 .add_key = wlan_hdd_cfg80211_add_key,
17171 .get_key = wlan_hdd_cfg80211_get_key,
17172 .del_key = wlan_hdd_cfg80211_del_key,
17173 .set_default_key = wlan_hdd_cfg80211_set_default_key,
17174 .scan = wlan_hdd_cfg80211_scan,
17175 .connect = wlan_hdd_cfg80211_connect,
17176 .disconnect = wlan_hdd_cfg80211_disconnect,
17177 .join_ibss = wlan_hdd_cfg80211_join_ibss,
17178 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
17179 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
17180 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
17181 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
17182 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
17183 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
17184 .mgmt_tx = wlan_hdd_mgmt_tx,
17185 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
17186 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
17187 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053017188 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017189 .get_station = wlan_hdd_cfg80211_get_station,
17190 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
17191 .del_station = wlan_hdd_cfg80211_del_station,
17192 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017193 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
17194 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
17195 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080017196#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017197 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
17198#endif
17199#ifdef FEATURE_WLAN_TDLS
17200 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17201 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17202#endif
17203#ifdef WLAN_FEATURE_GTK_OFFLOAD
17204 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17205#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17206#ifdef FEATURE_WLAN_SCAN_PNO
17207 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17208 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17209#endif /*FEATURE_WLAN_SCAN_PNO */
17210 .resume = wlan_hdd_cfg80211_resume_wlan,
17211 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17212 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17213#ifdef WLAN_NL80211_TESTMODE
17214 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17215#endif
17216#ifdef QCA_HT_2040_COEX
17217 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17218#endif
17219 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017220#ifdef CHANNEL_SWITCH_SUPPORTED
17221 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17222#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017223 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017224#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17225 defined(CFG80211_ABORT_SCAN)
17226 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17227#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017228};