blob: 87c9046ce490c2c8f348dfe48eb7218beb0f0a54 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhang3a210c52016-12-08 10:18:12 +08002 * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053069#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070#include "wlan_hdd_misc.h"
71#include "wlan_hdd_nan.h"
72#include <wlan_hdd_ipa.h>
73#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053074#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053075#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053076#include "pld_common.h"
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070077
Paul Zhang3a210c52016-12-08 10:18:12 +080078#ifdef WLAN_UMAC_CONVERGENCE
79#include "wlan_cfg80211.h"
80#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080081#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080082#include <wlan_cfg80211_scan.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083
84#ifdef FEATURE_WLAN_EXTSCAN
85#include "wlan_hdd_ext_scan.h"
86#endif
87
88#ifdef WLAN_FEATURE_LINK_LAYER_STATS
89#include "wlan_hdd_stats.h"
90#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080091#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080092#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093#include "qwlan_version.h"
94#include "wlan_hdd_memdump.h"
95
96#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070097#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098
Ravi Joshideb5a8d2015-11-09 19:11:43 -080099#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +0530100#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700101#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700102#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530103#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800104#include "wlan_hdd_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -0800105#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800106
Leo Changfdb45c32016-10-28 11:09:23 -0700107#include <cdp_txrx_cmn.h>
108#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800109#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530110#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800111#include "os_if_wifi_pos.h"
Ajit Pal Singh90a45a42017-04-18 18:53:46 +0530112#include "wlan_utility.h"
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -0700113#include "wlan_reg_ucfg_api.h"
Leo Changfdb45c32016-10-28 11:09:23 -0700114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800115#define g_mode_rates_size (12)
116#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800117#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
118 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
119
120/*
121 * Android CTS verifier needs atleast this much wait time (in msec)
122 */
123#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
124
125/*
126 * Refer @tCfgProtection structure for definition of the bit map.
127 * below value is obtained by setting the following bit-fields.
128 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
129 */
130#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
131
132#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700133 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800134 .center_freq = (freq), \
135 .hw_value = (chan), \
136 .flags = (flag), \
137 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800138 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800139}
140
141#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700142 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143 .center_freq = (freq), \
144 .hw_value = (chan), \
145 .flags = (flag), \
146 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800147 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148}
149
150#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
151 { \
152 .bitrate = rate, \
153 .hw_value = rate_id, \
154 .flags = flag, \
155 }
156
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
158#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159
160#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800161
Agrawal Ashish65634612016-08-18 13:24:32 +0530162#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
163 mode <= DFS_MODE_DEPRIORITIZE))
164#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
165 || (channel >= 36 && channel <= 184))
166
Peng Xu4d67c8f2015-10-16 16:02:26 -0700167#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530168#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700169
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170static const u32 hdd_cipher_suites[] = {
171 WLAN_CIPHER_SUITE_WEP40,
172 WLAN_CIPHER_SUITE_WEP104,
173 WLAN_CIPHER_SUITE_TKIP,
174#ifdef FEATURE_WLAN_ESE
175#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
176#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
177 WLAN_CIPHER_SUITE_BTK,
178 WLAN_CIPHER_SUITE_KRK,
179 WLAN_CIPHER_SUITE_CCMP,
180#else
181 WLAN_CIPHER_SUITE_CCMP,
182#endif
183#ifdef FEATURE_WLAN_WAPI
184 WLAN_CIPHER_SUITE_SMS4,
185#endif
186#ifdef WLAN_FEATURE_11W
187 WLAN_CIPHER_SUITE_AES_CMAC,
188#endif
189};
190
Abhishek Singhf512bf32016-05-04 16:47:46 +0530191static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192 HDD2GHZCHAN(2412, 1, 0),
193 HDD2GHZCHAN(2417, 2, 0),
194 HDD2GHZCHAN(2422, 3, 0),
195 HDD2GHZCHAN(2427, 4, 0),
196 HDD2GHZCHAN(2432, 5, 0),
197 HDD2GHZCHAN(2437, 6, 0),
198 HDD2GHZCHAN(2442, 7, 0),
199 HDD2GHZCHAN(2447, 8, 0),
200 HDD2GHZCHAN(2452, 9, 0),
201 HDD2GHZCHAN(2457, 10, 0),
202 HDD2GHZCHAN(2462, 11, 0),
203 HDD2GHZCHAN(2467, 12, 0),
204 HDD2GHZCHAN(2472, 13, 0),
205 HDD2GHZCHAN(2484, 14, 0),
206};
207
Abhishek Singhf512bf32016-05-04 16:47:46 +0530208static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209 HDD5GHZCHAN(5180, 36, 0),
210 HDD5GHZCHAN(5200, 40, 0),
211 HDD5GHZCHAN(5220, 44, 0),
212 HDD5GHZCHAN(5240, 48, 0),
213 HDD5GHZCHAN(5260, 52, 0),
214 HDD5GHZCHAN(5280, 56, 0),
215 HDD5GHZCHAN(5300, 60, 0),
216 HDD5GHZCHAN(5320, 64, 0),
217 HDD5GHZCHAN(5500, 100, 0),
218 HDD5GHZCHAN(5520, 104, 0),
219 HDD5GHZCHAN(5540, 108, 0),
220 HDD5GHZCHAN(5560, 112, 0),
221 HDD5GHZCHAN(5580, 116, 0),
222 HDD5GHZCHAN(5600, 120, 0),
223 HDD5GHZCHAN(5620, 124, 0),
224 HDD5GHZCHAN(5640, 128, 0),
225 HDD5GHZCHAN(5660, 132, 0),
226 HDD5GHZCHAN(5680, 136, 0),
227 HDD5GHZCHAN(5700, 140, 0),
228 HDD5GHZCHAN(5720, 144, 0),
229 HDD5GHZCHAN(5745, 149, 0),
230 HDD5GHZCHAN(5765, 153, 0),
231 HDD5GHZCHAN(5785, 157, 0),
232 HDD5GHZCHAN(5805, 161, 0),
233 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800234 HDD5GHZCHAN(5852, 170, 0),
235 HDD5GHZCHAN(5855, 171, 0),
236 HDD5GHZCHAN(5860, 172, 0),
237 HDD5GHZCHAN(5865, 173, 0),
238 HDD5GHZCHAN(5870, 174, 0),
239 HDD5GHZCHAN(5875, 175, 0),
240 HDD5GHZCHAN(5880, 176, 0),
241 HDD5GHZCHAN(5885, 177, 0),
242 HDD5GHZCHAN(5890, 178, 0),
243 HDD5GHZCHAN(5895, 179, 0),
244 HDD5GHZCHAN(5900, 180, 0),
245 HDD5GHZCHAN(5905, 181, 0),
246 HDD5GHZCHAN(5910, 182, 0),
247 HDD5GHZCHAN(5915, 183, 0),
248 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800249};
250
251static struct ieee80211_rate g_mode_rates[] = {
252 HDD_G_MODE_RATETAB(10, 0x1, 0),
253 HDD_G_MODE_RATETAB(20, 0x2, 0),
254 HDD_G_MODE_RATETAB(55, 0x4, 0),
255 HDD_G_MODE_RATETAB(110, 0x8, 0),
256 HDD_G_MODE_RATETAB(60, 0x10, 0),
257 HDD_G_MODE_RATETAB(90, 0x20, 0),
258 HDD_G_MODE_RATETAB(120, 0x40, 0),
259 HDD_G_MODE_RATETAB(180, 0x80, 0),
260 HDD_G_MODE_RATETAB(240, 0x100, 0),
261 HDD_G_MODE_RATETAB(360, 0x200, 0),
262 HDD_G_MODE_RATETAB(480, 0x400, 0),
263 HDD_G_MODE_RATETAB(540, 0x800, 0),
264};
265
266static struct ieee80211_rate a_mode_rates[] = {
267 HDD_G_MODE_RATETAB(60, 0x10, 0),
268 HDD_G_MODE_RATETAB(90, 0x20, 0),
269 HDD_G_MODE_RATETAB(120, 0x40, 0),
270 HDD_G_MODE_RATETAB(180, 0x80, 0),
271 HDD_G_MODE_RATETAB(240, 0x100, 0),
272 HDD_G_MODE_RATETAB(360, 0x200, 0),
273 HDD_G_MODE_RATETAB(480, 0x400, 0),
274 HDD_G_MODE_RATETAB(540, 0x800, 0),
275};
276
277static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530278 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700280 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800281 .bitrates = g_mode_rates,
282 .n_bitrates = g_mode_rates_size,
283 .ht_cap.ht_supported = 1,
284 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
285 | IEEE80211_HT_CAP_GRN_FLD
286 | IEEE80211_HT_CAP_DSSSCCK40
287 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
288 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
289 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
290 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
291 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
292 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
293 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
294};
295
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530297 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800298 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700299 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800300 .bitrates = a_mode_rates,
301 .n_bitrates = a_mode_rates_size,
302 .ht_cap.ht_supported = 1,
303 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
304 | IEEE80211_HT_CAP_GRN_FLD
305 | IEEE80211_HT_CAP_DSSSCCK40
306 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
307 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
308 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
309 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
310 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
311 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
312 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
313 .vht_cap.vht_supported = 1,
314};
315
316/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800317 * TX/RX direction for each kind of interface
318 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319static const struct ieee80211_txrx_stypes
320 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
321 [NL80211_IFTYPE_STATION] = {
322 .tx = 0xffff,
323 .rx = BIT(SIR_MAC_MGMT_ACTION) |
324 BIT(SIR_MAC_MGMT_PROBE_REQ),
325 },
326 [NL80211_IFTYPE_AP] = {
327 .tx = 0xffff,
328 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_PROBE_REQ) |
331 BIT(SIR_MAC_MGMT_DISASSOC) |
332 BIT(SIR_MAC_MGMT_AUTH) |
333 BIT(SIR_MAC_MGMT_DEAUTH) |
334 BIT(SIR_MAC_MGMT_ACTION),
335 },
336 [NL80211_IFTYPE_ADHOC] = {
337 .tx = 0xffff,
338 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
339 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
340 BIT(SIR_MAC_MGMT_PROBE_REQ) |
341 BIT(SIR_MAC_MGMT_DISASSOC) |
342 BIT(SIR_MAC_MGMT_AUTH) |
343 BIT(SIR_MAC_MGMT_DEAUTH) |
344 BIT(SIR_MAC_MGMT_ACTION),
345 },
346 [NL80211_IFTYPE_P2P_CLIENT] = {
347 .tx = 0xffff,
348 .rx = BIT(SIR_MAC_MGMT_ACTION) |
349 BIT(SIR_MAC_MGMT_PROBE_REQ),
350 },
351 [NL80211_IFTYPE_P2P_GO] = {
352 /* This is also same as for SoftAP */
353 .tx = 0xffff,
354 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
355 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
356 BIT(SIR_MAC_MGMT_PROBE_REQ) |
357 BIT(SIR_MAC_MGMT_DISASSOC) |
358 BIT(SIR_MAC_MGMT_AUTH) |
359 BIT(SIR_MAC_MGMT_DEAUTH) |
360 BIT(SIR_MAC_MGMT_ACTION),
361 },
362};
363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800364/* Interface limits and combinations registered by the driver */
365
366/* STA ( + STA ) combination */
367static const struct ieee80211_iface_limit
368 wlan_hdd_sta_iface_limit[] = {
369 {
370 .max = 3, /* p2p0 is a STA as well */
371 .types = BIT(NL80211_IFTYPE_STATION),
372 },
373};
374
375/* ADHOC (IBSS) limit */
376static const struct ieee80211_iface_limit
377 wlan_hdd_adhoc_iface_limit[] = {
378 {
379 .max = 1,
380 .types = BIT(NL80211_IFTYPE_STATION),
381 },
382 {
383 .max = 1,
384 .types = BIT(NL80211_IFTYPE_ADHOC),
385 },
386};
387
388/* AP ( + AP ) combination */
389static const struct ieee80211_iface_limit
390 wlan_hdd_ap_iface_limit[] = {
391 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530392 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393 .types = BIT(NL80211_IFTYPE_AP),
394 },
395};
396
397/* P2P limit */
398static const struct ieee80211_iface_limit
399 wlan_hdd_p2p_iface_limit[] = {
400 {
401 .max = 1,
402 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
403 },
404 {
405 .max = 1,
406 .types = BIT(NL80211_IFTYPE_P2P_GO),
407 },
408};
409
410static const struct ieee80211_iface_limit
411 wlan_hdd_sta_ap_iface_limit[] = {
412 {
413 /* We need 1 extra STA interface for OBSS scan when SAP starts
414 * with HT40 in STA+SAP concurrency mode
415 */
416 .max = (1 + SAP_MAX_OBSS_STA_CNT),
417 .types = BIT(NL80211_IFTYPE_STATION),
418 },
419 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530420 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421 .types = BIT(NL80211_IFTYPE_AP),
422 },
423};
424
425/* STA + P2P combination */
426static const struct ieee80211_iface_limit
427 wlan_hdd_sta_p2p_iface_limit[] = {
428 {
429 /* One reserved for dedicated P2PDEV usage */
430 .max = 2,
431 .types = BIT(NL80211_IFTYPE_STATION)
432 },
433 {
434 /* Support for two identical (GO + GO or CLI + CLI)
435 * or dissimilar (GO + CLI) P2P interfaces
436 */
437 .max = 2,
438 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
439 },
440};
441
442/* STA + AP + P2PGO combination */
443static const struct ieee80211_iface_limit
444wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
445 /* Support for AP+P2PGO interfaces */
446 {
447 .max = 2,
448 .types = BIT(NL80211_IFTYPE_STATION)
449 },
450 {
451 .max = 1,
452 .types = BIT(NL80211_IFTYPE_P2P_GO)
453 },
454 {
455 .max = 1,
456 .types = BIT(NL80211_IFTYPE_AP)
457 }
458};
459
460/* SAP + P2P combination */
461static const struct ieee80211_iface_limit
462wlan_hdd_sap_p2p_iface_limit[] = {
463 {
464 /* 1 dedicated for p2p0 which is a STA type */
465 .max = 1,
466 .types = BIT(NL80211_IFTYPE_STATION)
467 },
468 {
469 /* The p2p interface in SAP+P2P can be GO/CLI.
470 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
471 */
472 .max = 1,
473 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
474 },
475 {
476 /* SAP+GO to support only one SAP interface */
477 .max = 1,
478 .types = BIT(NL80211_IFTYPE_AP)
479 }
480};
481
482/* P2P + P2P combination */
483static const struct ieee80211_iface_limit
484wlan_hdd_p2p_p2p_iface_limit[] = {
485 {
486 /* 1 dedicated for p2p0 which is a STA type */
487 .max = 1,
488 .types = BIT(NL80211_IFTYPE_STATION)
489 },
490 {
491 /* The p2p interface in P2P+P2P can be GO/CLI.
492 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
493 */
494 .max = 2,
495 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
496 },
497};
498
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700499static const struct ieee80211_iface_limit
500 wlan_hdd_mon_iface_limit[] = {
501 {
502 .max = 3, /* Monitor interface */
503 .types = BIT(NL80211_IFTYPE_MONITOR),
504 },
505};
506
507static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508 wlan_hdd_iface_combination[] = {
509 /* STA */
510 {
511 .limits = wlan_hdd_sta_iface_limit,
512 .num_different_channels = 2,
513 .max_interfaces = 3,
514 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
515 },
516 /* ADHOC */
517 {
518 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700519 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 .max_interfaces = 2,
521 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
522 },
523 /* AP */
524 {
525 .limits = wlan_hdd_ap_iface_limit,
526 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530527 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
529 },
530 /* P2P */
531 {
532 .limits = wlan_hdd_p2p_iface_limit,
533 .num_different_channels = 2,
534 .max_interfaces = 2,
535 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
536 },
537 /* STA + AP */
538 {
539 .limits = wlan_hdd_sta_ap_iface_limit,
540 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530541 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
543 .beacon_int_infra_match = true,
544 },
545 /* STA + P2P */
546 {
547 .limits = wlan_hdd_sta_p2p_iface_limit,
548 .num_different_channels = 2,
549 /* one interface reserved for P2PDEV dedicated usage */
550 .max_interfaces = 4,
551 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
552 .beacon_int_infra_match = true,
553 },
554 /* STA + P2P GO + SAP */
555 {
556 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
557 /* we can allow 3 channels for three different persona
558 * but due to firmware limitation, allow max 2 concrnt channels.
559 */
560 .num_different_channels = 2,
561 /* one interface reserved for P2PDEV dedicated usage */
562 .max_interfaces = 4,
563 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
564 .beacon_int_infra_match = true,
565 },
566 /* SAP + P2P */
567 {
568 .limits = wlan_hdd_sap_p2p_iface_limit,
569 .num_different_channels = 2,
570 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
571 .max_interfaces = 3,
572 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
573 .beacon_int_infra_match = true,
574 },
575 /* P2P + P2P */
576 {
577 .limits = wlan_hdd_p2p_p2p_iface_limit,
578 .num_different_channels = 2,
579 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
580 .max_interfaces = 3,
581 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
582 .beacon_int_infra_match = true,
583 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530584 /* Monitor */
585 {
586 .limits = wlan_hdd_mon_iface_limit,
587 .max_interfaces = 3,
588 .num_different_channels = 2,
589 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
590 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800592
593static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800594
595#ifdef WLAN_NL80211_TESTMODE
596enum wlan_hdd_tm_attr {
597 WLAN_HDD_TM_ATTR_INVALID = 0,
598 WLAN_HDD_TM_ATTR_CMD = 1,
599 WLAN_HDD_TM_ATTR_DATA = 2,
600 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
601 WLAN_HDD_TM_ATTR_TYPE = 4,
602 /* keep last */
603 WLAN_HDD_TM_ATTR_AFTER_LAST,
604 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
605};
606
607enum wlan_hdd_tm_cmd {
608 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
609 WLAN_HDD_TM_CMD_WLAN_HB = 1,
610};
611
612#define WLAN_HDD_TM_DATA_MAX_LEN 5000
613
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530614enum wlan_hdd_vendor_ie_access_policy {
615 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
616 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
617};
618
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800619static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
620 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
621 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
622 .len = WLAN_HDD_TM_DATA_MAX_LEN},
623};
624#endif /* WLAN_NL80211_TESTMODE */
625
626#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
627static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
628 .flags = WIPHY_WOWLAN_MAGIC_PKT,
629 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
630 .pattern_min_len = 1,
631 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
632};
633#endif
634
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530636 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
637 * @flags: Pointer to the flags to Add channel switch flag.
638 *
639 * This Function adds Channel Switch support flag, if channel switch is
640 * supported by kernel.
641 * Return: void.
642 */
643#ifdef CHANNEL_SWITCH_SUPPORTED
644static inline void hdd_add_channel_switch_support(uint32_t *flags)
645{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800646 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530647 return;
648}
649#else
650static inline void hdd_add_channel_switch_support(uint32_t *flags)
651{
652 return;
653}
654#endif
655
Manikandan Mohan22b83722015-12-15 15:03:23 -0800656#ifdef FEATURE_WLAN_TDLS
657
658/* TDLS capabilities params */
659#define PARAM_MAX_TDLS_SESSION \
660 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
661#define PARAM_TDLS_FEATURE_SUPPORT \
662 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
663
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530664/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800665 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
666 * @wiphy: WIPHY structure pointer
667 * @wdev: Wireless device structure pointer
668 * @data: Pointer to the data received
669 * @data_len: Length of the data received
670 *
671 * This function provides TDLS capabilities
672 *
673 * Return: 0 on success and errno on failure
674 */
675static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
676 struct wireless_dev *wdev,
677 const void *data,
678 int data_len)
679{
680 int status;
681 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
682 struct sk_buff *skb;
683 uint32_t set = 0;
684
Jeff Johnson1f61b612016-02-12 16:28:33 -0800685 ENTER_DEV(wdev->netdev);
686
Anurag Chouhan6d760662016-02-20 16:05:43 +0530687 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 hdd_err("Command not allowed in FTM mode");
689 return -EPERM;
690 }
691
692 status = wlan_hdd_validate_context(hdd_ctx);
693 if (status)
694 return status;
695
696 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
697 NLMSG_HDRLEN);
698 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700699 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700 goto fail;
701 }
702
703 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800704 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
706 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700707 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 goto fail;
709 }
710 } else {
711 set = set | WIFI_TDLS_SUPPORT;
712 set = set | (hdd_ctx->config->fTDLSExternalControl ?
713 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
714 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
715 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800716 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800717 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
718 hdd_ctx->max_num_tdls_sta) ||
719 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
720 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700721 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 goto fail;
723 }
724 }
725 return cfg80211_vendor_cmd_reply(skb);
726fail:
727 if (skb)
728 kfree_skb(skb);
729 return -EINVAL;
730}
731
732/**
733 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
734 * @wiphy: WIPHY structure pointer
735 * @wdev: Wireless device structure pointer
736 * @data: Pointer to the data received
737 * @data_len: Length of the data received
738 *
739 * This function provides TDLS capabilities
740 *
741 * Return: 0 on success and errno on failure
742 */
743static int
744wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
745 struct wireless_dev *wdev,
746 const void *data,
747 int data_len)
748{
749 int ret;
750
751 cds_ssr_protect(__func__);
752 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
753 data, data_len);
754 cds_ssr_unprotect(__func__);
755
756 return ret;
757}
758#endif
759
760#ifdef QCA_HT_2040_COEX
761static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
762#endif
763
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530764int wlan_hdd_merge_avoid_freqs(tHddAvoidFreqList *destFreqList,
765 tHddAvoidFreqList *srcFreqList)
766{
767 int i;
768 tHddAvoidFreqRange *avoidRange =
769 &destFreqList->avoidFreqRange[destFreqList->avoidFreqRangeCount];
770
771 destFreqList->avoidFreqRangeCount += srcFreqList->avoidFreqRangeCount;
772 if (destFreqList->avoidFreqRangeCount > HDD_MAX_AVOID_FREQ_RANGES) {
773 hdd_err("avoid freq overflow");
774 return -EINVAL;
775 }
776
777 for (i = 0; i < srcFreqList->avoidFreqRangeCount; i++) {
778 avoidRange->startFreq =
779 srcFreqList->avoidFreqRange[i].startFreq;
780 avoidRange->endFreq = srcFreqList->avoidFreqRange[i].endFreq;
781 avoidRange++;
782 }
783 return 0;
784}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785/*
786 * FUNCTION: wlan_hdd_send_avoid_freq_event
787 * This is called when wlan driver needs to send vendor specific
788 * avoid frequency range event to userspace
789 */
790int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
791 tHddAvoidFreqList *pAvoidFreqList)
792{
793 struct sk_buff *vendor_event;
794
795 ENTER();
796
797 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700798 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799 return -EINVAL;
800 }
801
802 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700803 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804 return -EINVAL;
805 }
806
807 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
808 NULL,
809 sizeof(tHddAvoidFreqList),
810 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
811 GFP_KERNEL);
812 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700813 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814 return -EINVAL;
815 }
816
817 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
818 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
819
820 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
821
822 EXIT();
823 return 0;
824}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530826/**
827 * wlan_hdd_get_adjacent_chan(): Gets next/previous channel
828 * with respect to the channel passed.
829 * @chan: Channel
830 * @upper: If "true" then next channel is returned or else
831 * previous channel is returned.
832 *
833 * This function returns the next/previous adjacent-channel to
834 * the channel passed. If "upper = true" then next channel is
835 * returned else previous is returned.
836 */
837int wlan_hdd_get_adjacent_chan(uint8_t chan, bool upper)
838{
839 enum channel_enum ch_idx = reg_get_chan_enum(chan);
840
841 if (ch_idx == INVALID_CHANNEL)
842 return -EINVAL;
843
844 if (upper && (ch_idx < (NUM_CHANNELS - 1)))
845 ch_idx++;
846 else if (!upper && (ch_idx > CHAN_ENUM_1))
847 ch_idx--;
848 else
849 return -EINVAL;
850
851 return WLAN_REG_CH_NUM(ch_idx);
852}
853
854/**
855 * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
856 * avoided when Do_Not_Break_Stream is active.
857 * @pHddCtx: HDD Context
858 * @op_chan: AP/P2P-GO operating channel
859 *
860 * This function sends list of frequencies to be avoided when
861 * Do_Not_Break_Stream is active.
862 * To clear the avoid_frequency_list in the application,
863 * op_chan = 0 can be passed.
864 *
865 * Return: 0 on success and errno on failure
866 */
867int wlan_hdd_send_avoid_freq_for_dnbs(hdd_context_t *pHddCtx, uint8_t op_chan)
868{
869 tHddAvoidFreqList p2p_avoid_freq_list;
870 uint8_t min_chan, max_chan;
871 int ret;
872 int chan;
873
874 ENTER();
875
876 if (!pHddCtx) {
877 hdd_err("invalid param");
878 return -EINVAL;
879 }
880
881 qdf_mem_zero(&p2p_avoid_freq_list, sizeof(tHddAvoidFreqList));
882 /*
883 * If channel passed is zero, clear the avoid_freq list in application.
884 */
885 if (!op_chan) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530886#ifdef FEATURE_WLAN_CH_AVOID
887 mutex_lock(&pHddCtx->avoid_freq_lock);
888 qdf_mem_zero(&pHddCtx->dnbs_avoid_freq_list,
889 sizeof(tHddAvoidFreqList));
890 if (pHddCtx->coex_avoid_freq_list.avoidFreqRangeCount)
891 memcpy(&p2p_avoid_freq_list,
892 &pHddCtx->coex_avoid_freq_list,
893 sizeof(tHddAvoidFreqList));
894 mutex_unlock(&pHddCtx->avoid_freq_lock);
895#endif
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530896 ret = wlan_hdd_send_avoid_freq_event(pHddCtx,
897 &p2p_avoid_freq_list);
898 if (ret)
899 hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
900 ret);
901
902 return ret;
903 }
904
905 if (WLAN_REG_IS_24GHZ_CH(op_chan)) {
906 min_chan = REG_MIN_24GHZ_CH_NUM;
907 max_chan = REG_MAX_24GHZ_CH_NUM;
908 } else if WLAN_REG_IS_5GHZ_CH(op_chan) {
909 min_chan = REG_MIN_5GHZ_CH_NUM;
910 max_chan = REG_MAX_5GHZ_CH_NUM;
911 } else {
912 hdd_err("invalid channel:%d", op_chan);
913 return -EINVAL;
914 }
915
916 if ((op_chan > min_chan) && (op_chan < max_chan)) {
917 p2p_avoid_freq_list.avoidFreqRangeCount = 2;
918 p2p_avoid_freq_list.avoidFreqRange[0].startFreq =
919 wlan_chan_to_freq(min_chan);
920
921 /* Get channel before the op_chan */
922 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
923 if (chan < 0)
924 return -EINVAL;
925 p2p_avoid_freq_list.avoidFreqRange[0].endFreq =
926 wlan_chan_to_freq(chan);
927
928 /* Get channel next to the op_chan */
929 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
930 if (chan < 0)
931 return -EINVAL;
932 p2p_avoid_freq_list.avoidFreqRange[1].startFreq =
933 wlan_chan_to_freq(chan);
934
935 p2p_avoid_freq_list.avoidFreqRange[1].endFreq =
936 wlan_chan_to_freq(max_chan);
937 } else if (op_chan == min_chan) {
938 p2p_avoid_freq_list.avoidFreqRangeCount = 1;
939
940 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
941 if (chan < 0)
942 return -EINVAL;
943 p2p_avoid_freq_list.avoidFreqRange[0].startFreq =
944 wlan_chan_to_freq(chan);
945
946 p2p_avoid_freq_list.avoidFreqRange[0].endFreq =
947 wlan_chan_to_freq(max_chan);
948 } else {
949 p2p_avoid_freq_list.avoidFreqRangeCount = 1;
950 p2p_avoid_freq_list.avoidFreqRange[0].startFreq =
951 wlan_chan_to_freq(min_chan);
952
953 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
954 if (chan < 0)
955 return -EINVAL;
956 p2p_avoid_freq_list.avoidFreqRange[0].endFreq =
957 wlan_chan_to_freq(chan);
958 }
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530959#ifdef FEATURE_WLAN_CH_AVOID
960 mutex_lock(&pHddCtx->avoid_freq_lock);
961 pHddCtx->dnbs_avoid_freq_list = p2p_avoid_freq_list;
962 if (pHddCtx->coex_avoid_freq_list.avoidFreqRangeCount) {
963 ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list,
964 &pHddCtx->coex_avoid_freq_list);
965 if (ret) {
966 mutex_unlock(&pHddCtx->avoid_freq_lock);
967 hdd_err("avoid freq merge failed");
968 return ret;
969 }
970 }
971 mutex_unlock(&pHddCtx->avoid_freq_lock);
972#endif
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530973 ret = wlan_hdd_send_avoid_freq_event(pHddCtx, &p2p_avoid_freq_list);
974 if (ret)
975 hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
976
977 return ret;
978}
979
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800980/* vendor specific events */
981static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800982 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
983 .vendor_id =
984 QCA_NL80211_VENDOR_ID,
985 .subcmd =
986 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
987 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800988
989#ifdef WLAN_FEATURE_NAN
990 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
991 .vendor_id =
992 QCA_NL80211_VENDOR_ID,
993 .subcmd =
994 QCA_NL80211_VENDOR_SUBCMD_NAN
995 },
996#endif
997
998#ifdef WLAN_FEATURE_STATS_EXT
999 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
1000 .vendor_id =
1001 QCA_NL80211_VENDOR_ID,
1002 .subcmd =
1003 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
1004 },
1005#endif /* WLAN_FEATURE_STATS_EXT */
1006#ifdef FEATURE_WLAN_EXTSCAN
1007 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
1020 .
1021 vendor_id
1022 =
1023 QCA_NL80211_VENDOR_ID,
1024 .subcmd =
1025 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
1026 },
1027 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
1028 .
1029 vendor_id
1030 =
1031 QCA_NL80211_VENDOR_ID,
1032 .
1033 subcmd =
1034 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
1035 },
1036 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
1037 .
1038 vendor_id
1039 =
1040 QCA_NL80211_VENDOR_ID,
1041 .
1042 subcmd
1043 =
1044 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1045 },
1046 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1047 .
1048 vendor_id
1049 =
1050 QCA_NL80211_VENDOR_ID,
1051 .subcmd =
1052 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1053 },
1054 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1055 .vendor_id =
1056 QCA_NL80211_VENDOR_ID,
1057 .subcmd =
1058 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1059 },
1060 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1061 .
1062 vendor_id
1063 =
1064 QCA_NL80211_VENDOR_ID,
1065 .subcmd =
1066 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1067 },
1068 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1069 .
1070 vendor_id
1071 =
1072 QCA_NL80211_VENDOR_ID,
1073 .subcmd =
1074 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1075 },
1076 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1077 .
1078 vendor_id
1079 =
1080 QCA_NL80211_VENDOR_ID,
1081 .
1082 subcmd
1083 =
1084 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1085 },
1086 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1087 .
1088 vendor_id
1089 =
1090 QCA_NL80211_VENDOR_ID,
1091 .
1092 subcmd =
1093 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1094 },
1095 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1096 .
1097 vendor_id
1098 =
1099 QCA_NL80211_VENDOR_ID,
1100 .
1101 subcmd
1102 =
1103 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
1104 },
1105 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
1106 .
1107 vendor_id
1108 =
1109 QCA_NL80211_VENDOR_ID,
1110 .
1111 subcmd
1112 =
1113 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
1114 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001115#endif /* FEATURE_WLAN_EXTSCAN */
1116
1117#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1118 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
1119 .vendor_id =
1120 QCA_NL80211_VENDOR_ID,
1121 .subcmd =
1122 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
1123 },
1124 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
1125 .vendor_id =
1126 QCA_NL80211_VENDOR_ID,
1127 .subcmd =
1128 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
1129 },
1130 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
1131 .vendor_id =
1132 QCA_NL80211_VENDOR_ID,
1133 .subcmd =
1134 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
1135 },
1136 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
1137 .vendor_id =
1138 QCA_NL80211_VENDOR_ID,
1139 .subcmd =
1140 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
1141 },
1142 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
1143 .vendor_id =
1144 QCA_NL80211_VENDOR_ID,
1145 .subcmd =
1146 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
1147 },
1148 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
1149 .vendor_id =
1150 QCA_NL80211_VENDOR_ID,
1151 .subcmd =
1152 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
1153 },
Zhang Qianca38fb12016-12-23 11:10:48 +08001154 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
1155 .vendor_id =
1156 QCA_NL80211_VENDOR_ID,
1157 .subcmd =
1158 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
1159 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001160#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1161 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1162 .vendor_id =
1163 QCA_NL80211_VENDOR_ID,
1164 .subcmd =
1165 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1166 },
1167 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1168 .vendor_id = QCA_NL80211_VENDOR_ID,
1169 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1170 },
1171#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1172 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1173 .vendor_id =
1174 QCA_NL80211_VENDOR_ID,
1175 .subcmd =
1176 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1177 },
1178#endif
1179 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1180 .vendor_id =
1181 QCA_NL80211_VENDOR_ID,
1182 .subcmd =
1183 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1184 },
1185 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1186 .vendor_id =
1187 QCA_NL80211_VENDOR_ID,
1188 .subcmd =
1189 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1190 },
1191 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1192 .vendor_id =
1193 QCA_NL80211_VENDOR_ID,
1194 .subcmd =
1195 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1196 },
1197 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1198 .vendor_id =
1199 QCA_NL80211_VENDOR_ID,
1200 .subcmd =
1201 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1202 },
1203 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1204 .vendor_id =
1205 QCA_NL80211_VENDOR_ID,
1206 .subcmd =
1207 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1208 },
1209#ifdef FEATURE_WLAN_EXTSCAN
1210 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1211 .vendor_id = QCA_NL80211_VENDOR_ID,
1212 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1213 },
1214 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1215 .vendor_id = QCA_NL80211_VENDOR_ID,
1216 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1217 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001218 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1219 .vendor_id = QCA_NL80211_VENDOR_ID,
1220 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1221 },
1222#endif /* FEATURE_WLAN_EXTSCAN */
1223 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1224 .vendor_id = QCA_NL80211_VENDOR_ID,
1225 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1226 },
1227#ifdef WLAN_FEATURE_MEMDUMP
1228 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1229 .vendor_id = QCA_NL80211_VENDOR_ID,
1230 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1231 },
1232#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001233#ifdef WLAN_FEATURE_TSF
1234 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1235 .vendor_id = QCA_NL80211_VENDOR_ID,
1236 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1237 },
1238#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1240 .vendor_id = QCA_NL80211_VENDOR_ID,
1241 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1242 },
1243 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1244 .vendor_id = QCA_NL80211_VENDOR_ID,
1245 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1246 },
1247 /* OCB events */
1248 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1249 .vendor_id = QCA_NL80211_VENDOR_ID,
1250 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1251 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001252#ifdef FEATURE_LFR_SUBNET_DETECTION
1253 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1254 .vendor_id = QCA_NL80211_VENDOR_ID,
1255 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1256 },
1257#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001258
1259#ifdef WLAN_FEATURE_NAN_DATAPATH
1260 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1261 .vendor_id = QCA_NL80211_VENDOR_ID,
1262 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1263 },
1264#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001265
1266 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1267 .vendor_id = QCA_NL80211_VENDOR_ID,
1268 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1269 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301270 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1271 .vendor_id = QCA_NL80211_VENDOR_ID,
1272 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1273 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301274 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1275 .vendor_id = QCA_NL80211_VENDOR_ID,
1276 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1277 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001278#ifdef WLAN_UMAC_CONVERGENCE
1279 COMMON_VENDOR_EVENTS
1280#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001281};
1282
1283/**
1284 * __is_driver_dfs_capable() - get driver DFS capability
1285 * @wiphy: pointer to wireless wiphy structure.
1286 * @wdev: pointer to wireless_dev structure.
1287 * @data: Pointer to the data to be passed via vendor interface
1288 * @data_len:Length of the data to be passed
1289 *
1290 * This function is called by userspace to indicate whether or not
1291 * the driver supports DFS offload.
1292 *
1293 * Return: 0 on success, negative errno on failure
1294 */
1295static int __is_driver_dfs_capable(struct wiphy *wiphy,
1296 struct wireless_dev *wdev,
1297 const void *data,
1298 int data_len)
1299{
1300 u32 dfs_capability = 0;
1301 struct sk_buff *temp_skbuff;
1302 int ret_val;
1303 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1304
Jeff Johnson1f61b612016-02-12 16:28:33 -08001305 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001306
1307 ret_val = wlan_hdd_validate_context(hdd_ctx);
1308 if (ret_val)
1309 return ret_val;
1310
Anurag Chouhan6d760662016-02-20 16:05:43 +05301311 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001312 hdd_err("Command not allowed in FTM mode");
1313 return -EPERM;
1314 }
1315
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001316 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001317
1318 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1319 NLMSG_HDRLEN);
1320
1321 if (temp_skbuff != NULL) {
1322 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1323 dfs_capability);
1324 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001325 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001326 kfree_skb(temp_skbuff);
1327
1328 return ret_val;
1329 }
1330
1331 return cfg80211_vendor_cmd_reply(temp_skbuff);
1332 }
1333
Jeff Johnson020db452016-06-29 14:37:26 -07001334 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001335 return -ENOMEM;
1336}
1337
1338/**
1339 * is_driver_dfs_capable() - get driver DFS capability
1340 * @wiphy: pointer to wireless wiphy structure.
1341 * @wdev: pointer to wireless_dev structure.
1342 * @data: Pointer to the data to be passed via vendor interface
1343 * @data_len:Length of the data to be passed
1344 *
1345 * This function is called by userspace to indicate whether or not
1346 * the driver supports DFS offload. This is an SSR-protected
1347 * wrapper function.
1348 *
1349 * Return: 0 on success, negative errno on failure
1350 */
1351static int is_driver_dfs_capable(struct wiphy *wiphy,
1352 struct wireless_dev *wdev,
1353 const void *data,
1354 int data_len)
1355{
1356 int ret;
1357
1358 cds_ssr_protect(__func__);
1359 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1360 cds_ssr_unprotect(__func__);
1361
1362 return ret;
1363}
1364
1365/**
1366 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1367 *
1368 * @adapter: SAP adapter pointer
1369 *
1370 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1371 * radio. So in case of DFS MCC scenario override current SAP given config
1372 * to follow concurrent SAP DFS config
1373 *
1374 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1375 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1377{
1378 hdd_adapter_t *con_sap_adapter;
1379 tsap_Config_t *sap_config, *con_sap_config;
1380 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001381 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001383 if (!hdd_ctx) {
1384 hdd_err("hdd context is NULL");
1385 return 0;
1386 }
1387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 /*
1389 * Check if AP+AP case, once primary AP chooses a DFS
1390 * channel secondary AP should always follow primary APs channel
1391 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001392 if (!policy_mgr_concurrent_beaconing_sessions_running(
1393 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394 return 0;
1395
1396 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1397 if (!con_sap_adapter)
1398 return 0;
1399
1400 sap_config = &adapter->sessionCtx.ap.sapConfig;
1401 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1402 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1403
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001404 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001405 return 0;
1406
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001407 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001408 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001409 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001410 sap_config->channel = con_ch;
1411
1412 if (con_sap_config->acs_cfg.acs_mode == true) {
1413 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1414 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001415 hdd_err("Primary AP channel config error");
1416 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001417 con_ch, con_sap_config->acs_cfg.pri_ch,
1418 con_sap_config->acs_cfg.ht_sec_ch);
1419 return -EINVAL;
1420 }
1421 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1422 * MCC restriction. So free ch list allocated in do_acs
1423 * func for Sec AP and realloc for Pri AP ch list size
1424 */
1425 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301426 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001427
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301428 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001429 &con_sap_config->acs_cfg,
1430 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301431 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001432 sizeof(uint8_t) *
1433 con_sap_config->acs_cfg.ch_list_count);
1434 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001435 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001436 return -ENOMEM;
1437 }
1438
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301439 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001440 con_sap_config->acs_cfg.ch_list,
1441 con_sap_config->acs_cfg.ch_list_count);
1442
1443 } else {
1444 sap_config->acs_cfg.pri_ch = con_ch;
1445 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1446 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1447 }
1448
1449 return con_ch;
1450}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001451
1452/**
1453 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1454 * @sap_cfg: pointer to SAP config struct
1455 *
1456 * This function sets the default ACS start and end channel for the given band
1457 * and also parses the given ACS channel list.
1458 *
1459 * Return: None
1460 */
1461
1462static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1463 bool vht_enabled)
1464{
1465 int i;
1466 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1467 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001468 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1469 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001470 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1471 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001472 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1473 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001474 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1475 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001476 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1477 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001478 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1479 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001480 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1481 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001482 }
1483
1484 if (ht_enabled)
1485 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1486
1487 if (vht_enabled)
1488 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1489
1490
1491 /* Parse ACS Chan list from hostapd */
1492 if (!sap_cfg->acs_cfg.ch_list)
1493 return;
1494
1495 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1496 sap_cfg->acs_cfg.end_ch =
1497 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1498 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301499 /* avoid channel as start channel */
1500 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1501 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001502 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1503 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1504 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1505 }
1506}
1507
1508
1509static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1510
1511/**
1512 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1513 * @adapter: pointer to SAP adapter struct
1514 *
1515 * This function starts the ACS procedure if there are no
1516 * constraints like MBSSID DFS restrictions.
1517 *
1518 * Return: Status of ACS Start procedure
1519 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301520int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001521{
1522
1523 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1524 tsap_Config_t *sap_config;
1525 tpWLAN_SAPEventCB acs_event_callback;
1526 int status;
1527
1528 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301529 if (hdd_ctx->acs_policy.acs_channel)
1530 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1531 else
1532 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533
1534 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001535 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001536 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001537
1538 if (status > 0) {
1539 /*notify hostapd about channel override */
1540 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1541 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1542 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001543 }
Jeff Johnson68755312017-02-10 11:46:55 -08001544
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1546 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001547 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001548 return -EINVAL;
1549 }
1550
1551 acs_event_callback = hdd_hostapd_sap_event_cb;
1552
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301553 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301554 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301555 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001556 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001557 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558 acs_event_callback, sap_config, adapter->dev);
1559
1560
1561 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001562 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563 return -EINVAL;
1564 }
bings394afdd2017-01-09 11:22:38 +08001565 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1566 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001567 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1568
1569 return 0;
1570}
1571
1572/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301573 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1574 * @ap_adapter: AP adapter
1575 * @nol: Non-occupancy list
1576 * @nol_len: Length of NOL
1577 *
1578 * Get the NOL for SAP
1579 *
1580 * Return: Zero on success, non-zero on failure
1581 */
1582static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1583 uint32_t *nol_len)
1584{
1585 QDF_STATUS ret;
1586
1587 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1588 nol, nol_len);
1589 if (QDF_IS_STATUS_ERROR(ret))
1590 return -EINVAL;
1591
1592 return 0;
1593}
1594
1595/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301596 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1597 * @hdd_ctx: hdd context
1598 * @acs_chan_params: external acs channel params
1599 * @sap_config: SAP config
1600 *
1601 * This API provides unsorted pcl list.
1602 * this list is a subset of the valid channel list given by hostapd.
1603 * if channel is not present in pcl, weightage will be given as zero
1604 *
1605 * Return: Zero on success, non-zero on failure
1606 */
1607static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1608 struct hdd_vendor_acs_chan_params *acs_chan_params,
1609 tsap_Config_t *sap_config)
1610{
1611 int i, j;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301612 /*
1613 * PCL shall contain only the preferred channels from the
1614 * application. If those channels are not present in the
1615 * driver PCL, then set the weight to zero
1616 */
1617 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1618 acs_chan_params->vendor_pcl_list[i] =
1619 sap_config->acs_cfg.ch_list[i];
1620 acs_chan_params->vendor_weight_list[i] = 0;
1621 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1622 if (sap_config->acs_cfg.ch_list[i] ==
1623 sap_config->acs_cfg.pcl_channels[j]) {
1624 acs_chan_params->vendor_weight_list[i] =
1625 sap_config->
1626 acs_cfg.pcl_channels_weight_list[j];
1627 break;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301628 }
1629 }
1630 }
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301631 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301632}
1633
1634/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301635 * hdd_update_reg_chan_info : This API contructs channel info
1636 * for all the given channel
1637 * @adapter: pointer to SAP adapter struct
1638 * @channel_count: channel count
1639 * @channel_list: channel list
1640 *
1641 * Return: Status of of channel information updation
1642 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301643static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301644 uint32_t channel_count,
1645 uint8_t *channel_list)
1646{
1647 int i;
1648 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001649 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301650 uint8_t bw_offset = 0, chan = 0;
1651 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1652 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1653
1654 /* memory allocation */
1655 sap_config->channel_info = qdf_mem_malloc(
1656 sizeof(struct hdd_channel_info) *
1657 channel_count);
1658 if (!sap_config->channel_info) {
1659 hdd_err("memory allocation failed");
1660 return -ENOMEM;
1661
1662 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301663 sap_config->channel_info_count = channel_count;
Kapil Gupta086c6202016-12-11 18:17:06 +05301664 for (i = 0; i < channel_count; i++) {
1665 icv = &sap_config->channel_info[i];
1666 chan = channel_list[i];
1667
1668 if (chan == 0)
1669 continue;
1670
1671 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1672 bw_offset = 1 << BW_40_OFFSET_BIT;
1673 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1674 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001675 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301676 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001677 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1678 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301679
1680 /* filling demo values */
1681 icv->max_radio_power = HDD_MAX_TX_POWER;
1682 icv->min_radio_power = HDD_MIN_TX_POWER;
1683 /* not supported in current driver */
1684 icv->max_antenna_gain = 0;
1685
1686 icv->reg_class_id = wlan_hdd_find_opclass(
1687 WLAN_HDD_GET_HAL_CTX(adapter),
1688 chan, bw_offset);
1689
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001690 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301691 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001692 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1693 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301694 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1695 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1696 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001697
Kapil Gupta086c6202016-12-11 18:17:06 +05301698 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001699 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301700 sap_config->acs_cfg.ch_width,
1701 sap_config->acs_cfg.is_ht_enabled,
1702 sap_config->acs_cfg.is_vht_enabled,
1703 hdd_ctx->config->enable_sub_20_channel_width);
1704
1705 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1706 icv->freq, icv->flags,
1707 icv->flagext, icv->ieee_chan_number,
1708 icv->max_reg_power, icv->max_radio_power,
1709 icv->min_radio_power, icv->reg_class_id,
1710 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1711 icv->vht_center_freq_seg1);
1712 }
1713 return 0;
1714}
1715
1716/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1717#define CHAN_INFO_ATTR_FLAGS \
1718 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1719#define CHAN_INFO_ATTR_FLAG_EXT \
1720 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1721#define CHAN_INFO_ATTR_FREQ \
1722 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1723#define CHAN_INFO_ATTR_MAX_REG_POWER \
1724 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1725#define CHAN_INFO_ATTR_MAX_POWER \
1726 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1727#define CHAN_INFO_ATTR_MIN_POWER \
1728 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1729#define CHAN_INFO_ATTR_REG_CLASS_ID \
1730 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1731#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1732 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1733#define CHAN_INFO_ATTR_VHT_SEG_0 \
1734 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1735#define CHAN_INFO_ATTR_VHT_SEG_1 \
1736 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1737
1738/**
1739 * hdd_cfg80211_update_channel_info() - add channel info attributes
1740 * @skb: pointer to sk buff
1741 * @hdd_ctx: pointer to hdd station context
1742 * @idx: attribute index
1743 *
1744 * Return: Success(0) or reason code for failure
1745 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301746static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301747hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1748 tsap_Config_t *sap_config, int idx)
1749{
1750 struct nlattr *nla_attr, *channel;
1751 struct hdd_channel_info *icv;
1752 int i;
1753
1754 nla_attr = nla_nest_start(skb, idx);
1755 if (!nla_attr)
1756 goto fail;
1757
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301758 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301759 channel = nla_nest_start(skb, i);
1760 if (!channel)
1761 goto fail;
1762
1763 icv = &sap_config->channel_info[i];
1764 if (!icv) {
1765 hdd_err("channel info not found");
1766 goto fail;
1767 }
1768 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1769 icv->freq) ||
1770 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1771 icv->flags) ||
1772 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1773 icv->flagext) ||
1774 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1775 icv->max_reg_power) ||
1776 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1777 icv->max_radio_power) ||
1778 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1779 icv->min_radio_power) ||
1780 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1781 icv->reg_class_id) ||
1782 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1783 icv->max_antenna_gain) ||
1784 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1785 icv->vht_center_freq_seg0) ||
1786 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1787 icv->vht_center_freq_seg1)) {
1788 hdd_err("put fail");
1789 goto fail;
1790 }
1791 nla_nest_end(skb, channel);
1792 }
1793 nla_nest_end(skb, nla_attr);
1794 return 0;
1795fail:
1796 hdd_err("nl channel update failed");
1797 return -EINVAL;
1798}
1799#undef CHAN_INFO_ATTR_FLAGS
1800#undef CHAN_INFO_ATTR_FLAG_EXT
1801#undef CHAN_INFO_ATTR_FREQ
1802#undef CHAN_INFO_ATTR_MAX_REG_POWER
1803#undef CHAN_INFO_ATTR_MAX_POWER
1804#undef CHAN_INFO_ATTR_MIN_POWER
1805#undef CHAN_INFO_ATTR_REG_CLASS_ID
1806#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1807#undef CHAN_INFO_ATTR_VHT_SEG_0
1808#undef CHAN_INFO_ATTR_VHT_SEG_1
1809
1810/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301811 * hdd_cfg80211_update_pcl() - add pcl info attributes
1812 * @skb: pointer to sk buff
1813 * @hdd_ctx: pointer to hdd station context
1814 * @idx: attribute index
1815 * @vendor_pcl_list: PCL list
1816 * @vendor_weight_list: PCL weights
1817 *
1818 * Return: Success(0) or reason code for failure
1819 */
1820static int32_t
1821hdd_cfg80211_update_pcl(struct sk_buff *skb,
1822 uint8_t ch_list_count, int idx,
1823 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1824{
1825 struct nlattr *nla_attr, *channel;
1826 int i;
1827
1828 nla_attr = nla_nest_start(skb, idx);
1829
1830 if (!nla_attr)
1831 goto fail;
1832
1833 for (i = 0; i < ch_list_count; i++) {
1834 channel = nla_nest_start(skb, i);
1835 if (!channel)
1836 goto fail;
1837 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1838 vendor_pcl_list[i]) ||
1839 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1840 vendor_weight_list[i])) {
1841 hdd_err("put fail");
1842 goto fail;
1843 }
1844 nla_nest_end(skb, channel);
1845 }
1846 nla_nest_end(skb, nla_attr);
1847
1848 return 0;
1849fail:
1850 hdd_err("updating pcl list failed");
1851 return -EINVAL;
1852}
1853
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301854static void hdd_get_scan_band(hdd_context_t *hdd_ctx,
1855 tsap_Config_t *sap_config,
1856 eCsrBand *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301857{
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301858 int i, temp_count = 0;
1859 int acs_list_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301860 /* Get scan band */
1861 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1862 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1863 *band = eCSR_BAND_24;
1864 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1865 *band = eCSR_BAND_5G;
1866 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1867 *band = eCSR_BAND_ALL;
1868 }
1869 /* Auto is not supported currently */
1870 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1871 hdd_err("invalid band");
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301872 if (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ ==
1873 hdd_ctx->config->external_acs_freq_band)
1874 *band = eCSR_BAND_24;
1875 else
1876 *band = eCSR_BAND_5G;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301877 for (i = 0; i < acs_list_count; i++) {
1878 if (eCSR_BAND_24 == *band) {
1879 if (WLAN_REG_IS_24GHZ_CH(
1880 sap_config->acs_cfg.ch_list[i])) {
1881 sap_config->acs_cfg.ch_list[
1882 temp_count] =
1883 sap_config->acs_cfg.ch_list[i];
1884 temp_count++;
1885 }
1886 } else if (eCSR_BAND_5G == *band) {
1887 if (WLAN_REG_IS_5GHZ_CH(
1888 sap_config->acs_cfg.ch_list[i])) {
1889 sap_config->acs_cfg.ch_list[
1890 temp_count] =
1891 sap_config->acs_cfg.ch_list[i];
1892 temp_count++;
1893 }
1894 }
1895 }
1896 sap_config->acs_cfg.ch_list_count = temp_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301897 }
1898}
1899
1900void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1901 uint8_t reason)
1902{
1903 struct sk_buff *skb;
1904 tsap_Config_t *sap_config;
1905 uint32_t channel_count = 0, status;
1906 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1907 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1908 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1909 struct hdd_vendor_acs_chan_params acs_chan_params;
1910 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1911 eCsrBand band = eCSR_BAND_24;
1912 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301913 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
1914 uint32_t i;
1915
Kapil Gupta8878ad92017-02-13 11:56:04 +05301916
1917 if (!hdd_ctx) {
1918 hdd_err("HDD context is NULL");
1919 return;
1920 }
1921
1922 ENTER();
1923 sap_config = &adapter->sessionCtx.ap.sapConfig;
1924
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301925 hdd_get_scan_band(hdd_ctx, &adapter->sessionCtx.ap.sapConfig, &band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301926 /* Get valid channels for SAP */
1927 wlan_hdd_sap_get_valid_channellist(adapter,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301928 &channel_count,
1929 channel_list,
1930 band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301931
1932 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05301933 /* Get phymode */
1934 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1935
1936 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1937 &(adapter->wdev),
1938 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1939 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1940 GFP_KERNEL);
1941
1942 if (!skb) {
1943 hdd_err("cfg80211_vendor_event_alloc failed");
1944 return;
1945 }
1946 /*
1947 * Application expects pcl to be a subset of channel list
1948 * Remove all channels which are not in channel list from pcl
1949 * and add weight as zero
1950 */
1951 acs_chan_params.channel_count = channel_count;
1952 acs_chan_params.channel_list = channel_list;
1953 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1954 acs_chan_params.vendor_weight_list = vendor_weight_list;
1955
1956 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1957 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301958
1959 if (acs_chan_params.channel_count) {
1960 hdd_debug("ACS channel list: len: %d",
1961 acs_chan_params.channel_count);
1962 for (i = 0; i < acs_chan_params.channel_count; i++)
1963 hdd_debug("%d ", acs_chan_params.channel_list[i]);
1964 }
1965
1966 if (acs_chan_params.pcl_count) {
1967 hdd_debug("ACS PCL list: len: %d",
1968 acs_chan_params.pcl_count);
1969 for (i = 0; i < acs_chan_params.pcl_count; i++)
1970 hdd_debug("channel:%d, weight:%d ",
1971 acs_chan_params.
1972 vendor_pcl_list[i],
1973 acs_chan_params.
1974 vendor_weight_list[i]);
1975 }
1976
1977 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
1978 hdd_ctx->config->external_acs_policy) {
1979 acs_policy =
1980 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
1981 } else {
1982 acs_policy =
1983 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
1984 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301985 /* Update values in NL buffer */
1986 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1987 reason) ||
1988 nla_put_u8(skb,
1989 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1990 false) ||
1991 nla_put_u8(skb,
1992 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1993 true) ||
1994 nla_put_u8(skb,
1995 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1996 true) ||
1997 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1998 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05301999 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
2000 band) ||
2001 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
2002 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05302003 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302004 channel_count, channel_list)) {
2005 hdd_err("nla put fail");
2006 goto fail;
2007 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302008 status =
2009 hdd_cfg80211_update_pcl(skb,
2010 acs_chan_params.
2011 pcl_count,
2012 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
2013 vendor_pcl_list,
2014 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302015
2016 if (status != 0)
2017 goto fail;
2018
2019 status = hdd_cfg80211_update_channel_info(skb, sap_config,
2020 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
2021
2022 if (status != 0)
2023 goto fail;
2024
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302025 status = nla_put_u32(skb,
2026 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
2027 acs_policy);
2028
2029 if (status != 0)
2030 goto fail;
2031
Kapil Gupta8878ad92017-02-13 11:56:04 +05302032 cfg80211_vendor_event(skb, GFP_KERNEL);
2033 return;
2034fail:
2035 if (skb)
2036 kfree_skb(skb);
2037}
2038
2039static int hdd_create_acs_timer(hdd_adapter_t *adapter)
2040{
2041 struct hdd_external_acs_timer_context *timer_context;
2042
2043 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
2044 return 0;
2045
2046 hdd_notice("Starting vendor app based ACS");
2047 timer_context = qdf_mem_malloc(sizeof(*timer_context));
2048 timer_context->adapter = adapter;
2049
2050 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
2051 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
2052 QDF_TIMER_TYPE_SW,
2053 hdd_acs_response_timeout_handler, timer_context);
2054 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
2055 return 0;
2056}
2057
2058/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002059 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2060 * @wiphy: Linux wiphy struct pointer
2061 * @wdev: Linux wireless device struct pointer
2062 * @data: ACS information from hostapd
2063 * @data_len: ACS information length
2064 *
2065 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2066 * and starts ACS procedure.
2067 *
2068 * Return: ACS procedure start status
2069 */
2070
2071static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2072 struct wireless_dev *wdev,
2073 const void *data, int data_len)
2074{
2075 struct net_device *ndev = wdev->netdev;
2076 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
2077 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2078 tsap_Config_t *sap_config;
2079 struct sk_buff *temp_skbuff;
2080 int status = -EINVAL, i = 0;
2081 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
2082 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302083 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084
2085 /* ***Note*** Donot set SME config related to ACS operation here because
2086 * ACS operation is not synchronouse and ACS for Second AP may come when
2087 * ACS operation for first AP is going on. So only do_acs is split to
2088 * seperate start_acs routine. Also SME-PMAC struct that is used to
2089 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
2090 * config shall be set only from start_acs.
2091 */
2092
2093 /* nla_policy Policy template. Policy not applied as some attributes are
2094 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
2095 *
2096 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
2097 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
2098 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
2099 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
2100 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
2101 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
2102 */
2103
Jeff Johnson1f61b612016-02-12 16:28:33 -08002104 ENTER_DEV(ndev);
2105
Anurag Chouhan6d760662016-02-20 16:05:43 +05302106 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002107 hdd_err("Command not allowed in FTM mode");
2108 return -EPERM;
2109 }
2110
Kapil Gupta8878ad92017-02-13 11:56:04 +05302111 if (hdd_ctx->config->force_sap_acs &&
2112 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07002113 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002114 return -EPERM;
2115 }
2116
2117 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302118 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002119 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302120
Naveen Rawat64e477e2016-05-20 10:34:56 -07002121 if (cds_is_sub_20_mhz_enabled()) {
2122 hdd_err("ACS not supported in sub 20 MHz ch wd.");
2123 status = -EINVAL;
2124 goto out;
2125 }
2126
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302128 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002129
2130 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
2131 NULL);
2132 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07002133 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002134 goto out;
2135 }
2136
2137 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002138 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002139 goto out;
2140 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302141 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
2142 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002143
2144 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
2145 ht_enabled =
2146 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2147 else
2148 ht_enabled = 0;
2149
2150 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2151 ht40_enabled =
2152 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2153 else
2154 ht40_enabled = 0;
2155
2156 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2157 vht_enabled =
2158 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2159 else
2160 vht_enabled = 0;
2161
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302162 if (hdd_ctx->config->sap_force_11n_for_11ac) {
2163 vht_enabled = 0;
2164 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
2165 }
2166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002167 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2168 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2169 } else {
2170 if (ht_enabled && ht40_enabled)
2171 ch_width = 40;
2172 else
2173 ch_width = 20;
2174 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302175
2176 /* this may be possible, when sap_force_11n_for_11ac is set */
2177 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2178 if (ht_enabled && ht40_enabled)
2179 ch_width = 40;
2180 else
2181 ch_width = 20;
2182 }
2183
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184 if (ch_width == 80)
2185 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2186 else if (ch_width == 40)
2187 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2188 else
2189 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2190
2191 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2192 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2193 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2194 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2195 * since it contains the frequency values of the channels in
2196 * the channel list.
2197 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2198 * is present
2199 */
2200 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2201 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2202 sap_config->acs_cfg.ch_list_count = nla_len(
2203 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2204 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302205 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002206 sizeof(uint8_t) *
2207 sap_config->acs_cfg.ch_list_count);
2208 if (sap_config->acs_cfg.ch_list == NULL)
2209 goto out;
2210
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302211 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 sap_config->acs_cfg.ch_list_count);
2213 }
2214 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2215 uint32_t *freq =
2216 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2217 sap_config->acs_cfg.ch_list_count = nla_len(
2218 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2219 sizeof(uint32_t);
2220 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302221 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002222 sap_config->acs_cfg.ch_list_count);
2223 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07002224 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002225 status = -ENOMEM;
2226 goto out;
2227 }
2228
2229 /* convert frequency to channel */
2230 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2231 sap_config->acs_cfg.ch_list[i] =
2232 ieee80211_frequency_to_channel(freq[i]);
2233 }
2234 }
2235
2236 hdd_debug("get pcl for DO_ACS vendor command");
2237
2238 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002239 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302240 sap_config->acs_cfg.pcl_channels,
2241 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302242 sap_config->acs_cfg.pcl_channels_weight_list,
2243 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302244 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002245 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002246
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302247 if (sap_config->acs_cfg.pcl_ch_count) {
2248 hdd_debug("ACS config PCL: len: %d",
2249 sap_config->acs_cfg.pcl_ch_count);
2250 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2251 hdd_debug("channel:%d, weight:%d ",
2252 sap_config->acs_cfg.
2253 pcl_channels[i],
2254 sap_config->acs_cfg.
2255 pcl_channels_weight_list[i]);
2256 }
2257
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002258 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302259 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2260 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002261 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002262 vht_enabled = 1;
2263 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2264 sap_config->acs_cfg.ch_width =
2265 hdd_ctx->config->vhtChannelWidth;
2266 /* No VHT80 in 2.4G so perform ACS accordingly */
2267 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302268 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002269 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302270 ch_width = 40;
2271 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002272 }
2273
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302274 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2275
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002276 hdd_debug("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002277 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2278 ch_width, ht_enabled, vht_enabled,
2279 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2280
Kapil Gupta8878ad92017-02-13 11:56:04 +05302281 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2282 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2283
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002284 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002285 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002286 sap_config->acs_cfg.ch_list_count);
2287 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002288 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002289 }
2290 sap_config->acs_cfg.acs_mode = true;
2291 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002292 /* ***Note*** Completion variable usage is not allowed
2293 * here since ACS scan operation may take max 2.2 sec
2294 * for 5G band:
2295 * 9 Active channel X 40 ms active scan time +
2296 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002297 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2298 * for this long. So we split up the scanning part.
2299 */
2300 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002301 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302 status = 0;
2303 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302304 /* Check if vendor specific acs is enabled */
2305 if (hdd_ctx->config->vendor_acs_support) {
2306 sap_config->acs_cfg.hw_mode = hw_mode;
2307 hdd_create_acs_timer(adapter);
2308 hdd_update_acs_timer_reason(adapter,
2309 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2310 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2311 wlan_sap_set_vendor_acs(
2312 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2313 true);
2314 else
2315 wlan_sap_set_vendor_acs(
2316 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2317 false);
2318
2319 } else
2320 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002321 }
2322
2323out:
2324 if (0 == status) {
2325 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2326 NLMSG_HDRLEN);
2327 if (temp_skbuff != NULL)
2328 return cfg80211_vendor_cmd_reply(temp_skbuff);
2329 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002330 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002331 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2332
2333 return status;
2334}
2335
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002336/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002337 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2338 * @wiphy: Linux wiphy struct pointer
2339 * @wdev: Linux wireless device struct pointer
2340 * @data: ACS information from hostapd
2341 * @data_len: ACS information len
2342 *
2343 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2344 * and starts ACS procedure.
2345 *
2346 * Return: ACS procedure start status
2347 */
2348
2349static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2350 struct wireless_dev *wdev,
2351 const void *data, int data_len)
2352{
2353 int ret;
2354
2355 cds_ssr_protect(__func__);
2356 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2357 cds_ssr_unprotect(__func__);
2358
2359 return ret;
2360}
2361
2362/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002363 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2364 * @adapter: Pointer to adapter struct
2365 *
2366 * This function handle cleanup of what was done in DO_ACS, including free
2367 * memory.
2368 *
2369 * Return: void
2370 */
2371
2372void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2373{
2374 if (adapter == NULL)
2375 return;
2376 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2377 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2378 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2379 }
2380}
2381
2382/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2384 * @work: Linux workqueue struct pointer for ACS work
2385 *
2386 * This function starts the ACS procedure which was marked pending when an ACS
2387 * procedure was in progress for a concurrent SAP interface.
2388 *
2389 * Return: None
2390 */
2391
2392static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2393{
2394 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2395 acs_pending_work.work);
2396 wlan_hdd_cfg80211_start_acs(adapter);
2397}
2398
2399/**
2400 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2401 * @adapter: Pointer to SAP adapter struct
2402 * @pri_channel: SAP ACS procedure selected Primary channel
2403 * @sec_channel: SAP ACS procedure selected secondary channel
2404 *
2405 * This is a callback function from SAP module on ACS procedure is completed.
2406 * This function send the ACS selected channel information to hostapd
2407 *
2408 * Return: None
2409 */
2410
2411void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2412{
2413 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2414 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2415 struct sk_buff *vendor_event;
2416 int ret_val;
2417 hdd_adapter_t *con_sap_adapter;
2418 uint16_t ch_width;
2419
2420 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002421 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002422 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2423 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2424 GFP_KERNEL);
2425
2426 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002427 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428 return;
2429 }
2430
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002431 ret_val = nla_put_u8(vendor_event,
2432 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2433 sap_cfg->acs_cfg.pri_ch);
2434 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002435 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002436 kfree_skb(vendor_event);
2437 return;
2438 }
2439
2440 ret_val = nla_put_u8(vendor_event,
2441 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2442 sap_cfg->acs_cfg.ht_sec_ch);
2443 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002444 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 kfree_skb(vendor_event);
2446 return;
2447 }
2448
2449 ret_val = nla_put_u8(vendor_event,
2450 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2451 sap_cfg->acs_cfg.vht_seg0_center_ch);
2452 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002453 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 kfree_skb(vendor_event);
2455 return;
2456 }
2457
2458 ret_val = nla_put_u8(vendor_event,
2459 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2460 sap_cfg->acs_cfg.vht_seg1_center_ch);
2461 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002462 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 kfree_skb(vendor_event);
2464 return;
2465 }
2466
2467 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2468 ch_width = 80;
2469 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2470 ch_width = 40;
2471 else
2472 ch_width = 20;
2473
2474 ret_val = nla_put_u16(vendor_event,
2475 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2476 ch_width);
2477 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002478 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 kfree_skb(vendor_event);
2480 return;
2481 }
2482 if (sap_cfg->acs_cfg.pri_ch > 14)
2483 ret_val = nla_put_u8(vendor_event,
2484 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2485 QCA_ACS_MODE_IEEE80211A);
2486 else
2487 ret_val = nla_put_u8(vendor_event,
2488 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2489 QCA_ACS_MODE_IEEE80211G);
2490
2491 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002492 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002493 kfree_skb(vendor_event);
2494 return;
2495 }
2496
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002497 hdd_debug("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002498 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2499 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2500 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2501
2502 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2503 /* ***Note*** As already mentioned Completion variable usage is not
2504 * allowed here since ACS scan operation may take max 2.2 sec.
2505 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2506 * operation.
2507 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2508 * when Primary AP ACS is complete and secondary AP ACS is started here
2509 * immediately, Primary AP start_bss may come inbetween ACS operation
2510 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2511 * delay. This path and below constraint will be removed on sessionizing
2512 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2513 * As per design constraint user space control application must take
2514 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2515 * this code path. Sec AP hostapd should be started after Primary AP
2516 * start beaconing which can be confirmed by getchannel iwpriv command
2517 */
2518
2519 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2520 if (con_sap_adapter &&
2521 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2523 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 /* Lets give 500ms for OBSS + START_BSS to complete */
2525 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2526 msecs_to_jiffies(500));
2527 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2528 }
2529
2530 return;
2531}
2532
2533static int
2534__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2535 struct wireless_dev *wdev,
2536 const void *data,
2537 int data_len)
2538{
2539 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2540 struct sk_buff *skb = NULL;
2541 uint32_t fset = 0;
2542 int ret;
2543
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002544 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302545
Anurag Chouhan6d760662016-02-20 16:05:43 +05302546 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 hdd_err("Command not allowed in FTM mode");
2548 return -EPERM;
2549 }
2550
2551 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302552 if (ret)
2553 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554
2555 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002556 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 fset |= WIFI_FEATURE_INFRA;
2558 }
2559 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002560 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002561 fset |= WIFI_FEATURE_INFRA_5G;
2562 }
2563#ifdef WLAN_FEATURE_P2P
2564 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2565 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002566 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002567 fset |= WIFI_FEATURE_P2P;
2568 }
2569#endif
2570 fset |= WIFI_FEATURE_SOFT_AP;
2571
2572 /* HOTSPOT is a supplicant feature, enable it by default */
2573 fset |= WIFI_FEATURE_HOTSPOT;
2574
2575#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302576 if (pHddCtx->config->extscan_enabled &&
2577 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002578 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2580 }
2581#endif
2582 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002583 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002584 fset |= WIFI_FEATURE_NAN;
2585 }
2586 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002587 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002588 fset |= WIFI_FEATURE_D2D_RTT;
2589 fset |= WIFI_FEATURE_D2AP_RTT;
2590 }
2591#ifdef FEATURE_WLAN_SCAN_PNO
2592 if (pHddCtx->config->configPNOScanSupport &&
2593 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002594 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595 fset |= WIFI_FEATURE_PNO;
2596 }
2597#endif
2598 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2599#ifdef FEATURE_WLAN_TDLS
2600 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2601 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002602 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603 fset |= WIFI_FEATURE_TDLS;
2604 }
2605 if (sme_is_feature_supported_by_fw(TDLS) &&
2606 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2607 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002608 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2610 }
2611#endif
2612#ifdef WLAN_AP_STA_CONCURRENCY
2613 fset |= WIFI_FEATURE_AP_STA;
2614#endif
2615 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002616 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002617
2618 if (hdd_link_layer_stats_supported())
2619 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2620
2621 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2622 NLMSG_HDRLEN);
2623 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002624 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625 return -EINVAL;
2626 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002627 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002629 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002630 goto nla_put_failure;
2631 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302632 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302633 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002634nla_put_failure:
2635 kfree_skb(skb);
2636 return -EINVAL;
2637}
2638
2639/**
2640 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2641 * @wiphy: pointer to wireless wiphy structure.
2642 * @wdev: pointer to wireless_dev structure.
2643 * @data: Pointer to the data to be passed via vendor interface
2644 * @data_len:Length of the data to be passed
2645 *
2646 * Return: Return the Success or Failure code.
2647 */
2648static int
2649wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2650 struct wireless_dev *wdev,
2651 const void *data, int data_len)
2652{
2653 int ret = 0;
2654
2655 cds_ssr_protect(__func__);
2656 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2657 data, data_len);
2658 cds_ssr_unprotect(__func__);
2659
2660 return ret;
2661}
2662
2663/**
2664 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2665 * @wiphy: pointer to wireless wiphy structure.
2666 * @wdev: pointer to wireless_dev structure.
2667 * @data: Pointer to the data to be passed via vendor interface
2668 * @data_len:Length of the data to be passed
2669 *
2670 * Set the MAC address that is to be used for scanning.
2671 *
2672 * Return: Return the Success or Failure code.
2673 */
2674static int
2675__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2676 struct wireless_dev *wdev,
2677 const void *data,
2678 int data_len)
2679{
2680 tpSirScanMacOui pReqMsg = NULL;
2681 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2682 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302683 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684 int ret;
2685
Jeff Johnson1f61b612016-02-12 16:28:33 -08002686 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002687
Anurag Chouhan6d760662016-02-20 16:05:43 +05302688 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689 hdd_err("Command not allowed in FTM mode");
2690 return -EPERM;
2691 }
2692
2693 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302694 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002695 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696
2697 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002698 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699 return -ENOTSUPP;
2700 }
2701
2702 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2703 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002704 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 return -EINVAL;
2706 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302707 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002708 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002709 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002710 return -ENOMEM;
2711 }
2712 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002713 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714 goto fail;
2715 }
2716 nla_memcpy(&pReqMsg->oui[0],
2717 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2718 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002719 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720 pReqMsg->oui[1], pReqMsg->oui[2]);
2721 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302722 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002723 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002724 goto fail;
2725 }
2726 return 0;
2727fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302728 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002729 return -EINVAL;
2730}
2731
2732/**
2733 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2734 * @wiphy: pointer to wireless wiphy structure.
2735 * @wdev: pointer to wireless_dev structure.
2736 * @data: Pointer to the data to be passed via vendor interface
2737 * @data_len:Length of the data to be passed
2738 *
2739 * Set the MAC address that is to be used for scanning. This is an
2740 * SSR-protecting wrapper function.
2741 *
2742 * Return: Return the Success or Failure code.
2743 */
2744static int
2745wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2746 struct wireless_dev *wdev,
2747 const void *data,
2748 int data_len)
2749{
2750 int ret;
2751
2752 cds_ssr_protect(__func__);
2753 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2754 data, data_len);
2755 cds_ssr_unprotect(__func__);
2756
2757 return ret;
2758}
2759
2760/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302761 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2762 * @wiphy: pointer phy adapter
2763 * @wdev: pointer to wireless device structure
2764 * @data: pointer to data buffer
2765 * @data_len: length of data
2766 *
2767 * This routine will give concurrency matrix
2768 *
2769 * Return: int status code
2770 */
2771static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2772 struct wireless_dev *wdev,
2773 const void *data,
2774 int data_len)
2775{
2776 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2777 uint8_t i, feature_sets, max_feature_sets;
2778 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2779 struct sk_buff *reply_skb;
2780 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2781 int ret;
2782
2783 ENTER_DEV(wdev->netdev);
2784
2785 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2786 hdd_err("Command not allowed in FTM mode");
2787 return -EPERM;
2788 }
2789
2790 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302791 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302792 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302793
2794 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2795 data, data_len, NULL)) {
2796 hdd_err("Invalid ATTR");
2797 return -EINVAL;
2798 }
2799
2800 /* Parse and fetch max feature set */
2801 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2802 hdd_err("Attr max feature set size failed");
2803 return -EINVAL;
2804 }
2805 max_feature_sets = nla_get_u32(tb[
2806 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002807 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302808
2809 /* Fill feature combination matrix */
2810 feature_sets = 0;
2811 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002812 WIFI_FEATURE_P2P;
2813 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2814 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302815 /* Add more feature combinations here */
2816
2817 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002818 hdd_debug("Number of feature sets: %d", feature_sets);
2819 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302820 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002821 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302822
2823 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2824 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2825 if (!reply_skb) {
2826 hdd_err("Feature set matrix: buffer alloc fail");
2827 return -ENOMEM;
2828 }
2829
2830 if (nla_put_u32(reply_skb,
2831 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2832 feature_sets) ||
2833 nla_put(reply_skb,
2834 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2835 sizeof(u32) * feature_sets,
2836 feature_set_matrix)) {
2837 hdd_err("nla put fail");
2838 kfree_skb(reply_skb);
2839 return -EINVAL;
2840 }
2841 return cfg80211_vendor_cmd_reply(reply_skb);
2842}
2843
2844/**
2845 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2846 * @wiphy: pointer to wireless wiphy structure.
2847 * @wdev: pointer to wireless_dev structure.
2848 * @data: Pointer to the data to be passed via vendor interface
2849 * @data_len:Length of the data to be passed
2850 *
2851 * Retrieves the concurrency feature set matrix
2852 *
2853 * Return: 0 on success, negative errno on failure
2854 */
2855static int
2856wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2857 struct wireless_dev *wdev,
2858 const void *data,
2859 int data_len)
2860{
2861 int ret;
2862
2863 cds_ssr_protect(__func__);
2864 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2865 data, data_len);
2866 cds_ssr_unprotect(__func__);
2867
2868 return ret;
2869}
2870
2871/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002872 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2873 * @feature_flags: pointer to the byte array of features.
2874 * @feature: Feature to be turned ON in the byte array.
2875 *
2876 * Return: None
2877 *
2878 * This is called to turn ON or SET the feature flag for the requested feature.
2879 **/
2880#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002881static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2882 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883{
2884 uint32_t index;
2885 uint8_t bit_mask;
2886
2887 index = feature / NUM_BITS_IN_BYTE;
2888 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2889 feature_flags[index] |= bit_mask;
2890}
2891
2892/**
2893 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2894 * @wiphy: pointer to wireless wiphy structure.
2895 * @wdev: pointer to wireless_dev structure.
2896 * @data: Pointer to the data to be passed via vendor interface
2897 * @data_len:Length of the data to be passed
2898 *
2899 * This is called when wlan driver needs to send supported feature set to
2900 * supplicant upon a request/query from the supplicant.
2901 *
2902 * Return: Return the Success or Failure code.
2903 **/
2904#define MAX_CONCURRENT_CHAN_ON_24G 2
2905#define MAX_CONCURRENT_CHAN_ON_5G 2
2906static int
2907__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2908 struct wireless_dev *wdev,
2909 const void *data, int data_len)
2910{
2911 struct sk_buff *skb = NULL;
2912 uint32_t dbs_capability = 0;
2913 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302914 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002915 int ret_val;
2916
2917 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2918 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2919
Jeff Johnson1f61b612016-02-12 16:28:33 -08002920 ENTER_DEV(wdev->netdev);
2921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2923 if (ret_val)
2924 return ret_val;
2925
Anurag Chouhan6d760662016-02-20 16:05:43 +05302926 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927 hdd_err("Command not allowed in FTM mode");
2928 return -EPERM;
2929 }
2930
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002931 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002932 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002933 wlan_hdd_cfg80211_set_feature(feature_flags,
2934 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2935 }
2936
2937 wlan_hdd_cfg80211_set_feature(feature_flags,
2938 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002939 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 wlan_hdd_cfg80211_set_feature(feature_flags,
2941 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002942
2943 if (wma_is_p2p_lo_capable())
2944 wlan_hdd_cfg80211_set_feature(feature_flags,
2945 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2946
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2948 NLMSG_HDRLEN);
2949
2950 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002951 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952 return -ENOMEM;
2953 }
2954
2955 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2956 sizeof(feature_flags), feature_flags))
2957 goto nla_put_failure;
2958
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002959 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2960 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302961 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002962 if (one_by_one_dbs)
2963 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2964
2965 if (two_by_two_dbs)
2966 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2967
2968 if (!one_by_one_dbs && !two_by_two_dbs)
2969 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2970 } else {
2971 hdd_err("wma_get_dbs_hw_mode failed");
2972 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2973 }
2974
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002975 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002976
2977 if (nla_put_u32(skb,
2978 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2979 MAX_CONCURRENT_CHAN_ON_24G))
2980 goto nla_put_failure;
2981
2982 if (nla_put_u32(skb,
2983 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2984 MAX_CONCURRENT_CHAN_ON_5G))
2985 goto nla_put_failure;
2986
2987 return cfg80211_vendor_cmd_reply(skb);
2988
2989nla_put_failure:
2990 kfree_skb(skb);
2991 return -EINVAL;
2992}
2993
2994/**
2995 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2996 * @wiphy: pointer to wireless wiphy structure.
2997 * @wdev: pointer to wireless_dev structure.
2998 * @data: Pointer to the data to be passed via vendor interface
2999 * @data_len:Length of the data to be passed
3000 *
3001 * This is called when wlan driver needs to send supported feature set to
3002 * supplicant upon a request/query from the supplicant.
3003 *
3004 * Return: Return the Success or Failure code.
3005 */
3006static int
3007wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3008 struct wireless_dev *wdev,
3009 const void *data, int data_len)
3010{
3011 int ret;
3012
3013 cds_ssr_protect(__func__);
3014 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
3015 data, data_len);
3016 cds_ssr_unprotect(__func__);
3017
3018 return ret;
3019}
3020
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303021#define PARAM_NUM_NW \
3022 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
3023#define PARAM_SET_BSSID \
3024 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
3025#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
3026#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027
3028/**
3029 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
3030 * @wiphy: The wiphy structure
3031 * @wdev: The wireless device
3032 * @data: Data passed by framework
3033 * @data_len: Parameters to be configured passed as data
3034 *
3035 * The roaming related parameters are configured by the framework
3036 * using this interface.
3037 *
3038 * Return: Return either success or failure code.
3039 */
3040static int
3041__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3042 struct wireless_dev *wdev, const void *data, int data_len)
3043{
3044 struct net_device *dev = wdev->netdev;
3045 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3046 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3047 uint8_t session_id;
3048 struct roam_ext_params roam_params;
3049 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303050 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003051 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
3052 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
3053 int rem, i;
3054 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08003055 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 int ret;
3057
Jeff Johnson1f61b612016-02-12 16:28:33 -08003058 ENTER_DEV(dev);
3059
Anurag Chouhan6d760662016-02-20 16:05:43 +05303060 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003061 hdd_err("Command not allowed in FTM mode");
3062 return -EPERM;
3063 }
3064
3065 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303066 if (ret)
3067 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003068
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05303069 if (pHddCtx->driver_status == DRIVER_MODULES_CLOSED) {
3070 hdd_err("Driver Modules are closed");
3071 return -EINVAL;
3072 }
3073
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003074 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3075 data, data_len,
3076 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003077 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003078 return -EINVAL;
3079 }
3080 /* Parse and fetch Command Type*/
3081 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003082 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003083 goto fail;
3084 }
3085 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303086 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003087 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
3088 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003089 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003090 goto fail;
3091 }
3092 req_id = nla_get_u32(
3093 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07003094 hdd_debug("Req Id (%d)", req_id);
3095 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003096 switch (cmd_type) {
3097 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
3098 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303099 if (tb[PARAM_NUM_NW]) {
3100 count = nla_get_u32(
3101 tb[PARAM_NUM_NW]);
3102 } else {
3103 hdd_err("Number of networks is not provided");
3104 goto fail;
3105 }
3106
3107 if (count &&
3108 tb[PRAM_SSID_LIST]) {
3109 nla_for_each_nested(curr_attr,
3110 tb[PRAM_SSID_LIST], rem) {
3111 if (nla_parse(tb2,
3112 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
3113 nla_data(curr_attr), nla_len(curr_attr),
3114 NULL)) {
3115 hdd_err("nla_parse failed");
3116 goto fail;
3117 }
3118 /* Parse and Fetch allowed SSID list*/
3119 if (!tb2[PARAM_LIST_SSID]) {
3120 hdd_err("attr allowed ssid failed");
3121 goto fail;
3122 }
3123 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
3124 /*
3125 * Upper Layers include a null termination
3126 * character. Check for the actual permissible
3127 * length of SSID and also ensure not to copy
3128 * the NULL termination character to the driver
3129 * buffer.
3130 */
3131 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
3132 ((buf_len - 1) <=
3133 SIR_MAC_MAX_SSID_LENGTH)) {
3134 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003135 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303136 tb2[PARAM_LIST_SSID], buf_len - 1);
3137 roam_params.ssid_allowed_list[i].length
3138 = buf_len - 1;
3139 hdd_debug("SSID[%d]: %.*s,length = %d",
3140 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141 roam_params.ssid_allowed_list[i].length,
3142 roam_params.ssid_allowed_list[i].ssId,
3143 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303144 i++;
3145 } else {
3146 hdd_err("Invalid buffer length");
3147 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003148 }
3149 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303150 if (i != count) {
3151 hdd_err("Invalid number of SSIDs i = %d, count = %d",
3152 i, count);
3153 goto fail;
3154 }
3155
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003156 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07003157 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158 roam_params.num_ssid_allowed_list);
3159 sme_update_roam_params(pHddCtx->hHal, session_id,
3160 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3161 break;
3162 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
3163 /* Parse and fetch 5G Boost Threshold */
3164 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003165 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 goto fail;
3167 }
3168 roam_params.raise_rssi_thresh_5g = nla_get_s32(
3169 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003170 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003171 roam_params.raise_rssi_thresh_5g);
3172 /* Parse and fetch 5G Penalty Threshold */
3173 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003174 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175 goto fail;
3176 }
3177 roam_params.drop_rssi_thresh_5g = nla_get_s32(
3178 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07003179 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180 roam_params.drop_rssi_thresh_5g);
3181 /* Parse and fetch 5G Boost Factor */
3182 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003183 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003184 goto fail;
3185 }
3186 roam_params.raise_factor_5g = nla_get_u32(
3187 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003188 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003189 roam_params.raise_factor_5g);
3190 /* Parse and fetch 5G Penalty factor */
3191 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003192 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003193 goto fail;
3194 }
3195 roam_params.drop_factor_5g = nla_get_u32(
3196 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07003197 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198 roam_params.drop_factor_5g);
3199 /* Parse and fetch 5G Max Boost */
3200 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003201 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202 goto fail;
3203 }
3204 roam_params.max_raise_rssi_5g = nla_get_u32(
3205 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07003206 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003207 roam_params.max_raise_rssi_5g);
3208 /* Parse and fetch Rssi Diff */
3209 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003210 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 goto fail;
3212 }
3213 roam_params.rssi_diff = nla_get_s32(
3214 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07003215 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003216 roam_params.rssi_diff);
3217 /* Parse and fetch Alert Rssi Threshold */
3218 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003219 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003220 goto fail;
3221 }
3222 roam_params.alert_rssi_threshold = nla_get_u32(
3223 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003224 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 roam_params.alert_rssi_threshold);
3226 sme_update_roam_params(pHddCtx->hHal, session_id,
3227 roam_params,
3228 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
3229 break;
3230 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
3231 /* Parse and fetch Activate Good Rssi Roam */
3232 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003233 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234 goto fail;
3235 }
3236 roam_params.good_rssi_roam = nla_get_s32(
3237 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07003238 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003239 roam_params.good_rssi_roam);
3240 sme_update_roam_params(pHddCtx->hHal, session_id,
3241 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
3242 break;
3243 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
3244 /* Parse and fetch number of preferred BSSID */
3245 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003246 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247 goto fail;
3248 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003249 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003250 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003251 if (count > MAX_BSSID_FAVORED) {
3252 hdd_err("Preferred BSSID count %u exceeds max %u",
3253 count, MAX_BSSID_FAVORED);
3254 goto fail;
3255 }
3256 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003257 i = 0;
3258 nla_for_each_nested(curr_attr,
3259 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3260 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003261
3262 if (i == count) {
3263 hdd_warn("Ignoring excess Preferred BSSID");
3264 break;
3265 }
3266
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267 if (nla_parse(tb2,
3268 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3269 nla_data(curr_attr), nla_len(curr_attr),
3270 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003271 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 goto fail;
3273 }
3274 /* Parse and fetch MAC address */
3275 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003276 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003277 goto fail;
3278 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003279 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003280 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303281 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003282 hdd_debug(MAC_ADDRESS_STR,
3283 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 /* Parse and fetch preference factor*/
3285 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003286 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003287 goto fail;
3288 }
3289 roam_params.bssid_favored_factor[i] = nla_get_u32(
3290 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003291 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003292 roam_params.bssid_favored_factor[i]);
3293 i++;
3294 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003295 if (i < count)
3296 hdd_warn("Num Preferred BSSID %u less than expected %u",
3297 i, count);
3298 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299 sme_update_roam_params(pHddCtx->hHal, session_id,
3300 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3301 break;
3302 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3303 /* Parse and fetch number of blacklist BSSID */
3304 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003305 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003306 goto fail;
3307 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003308 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003309 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003310 if (count > MAX_BSSID_AVOID_LIST) {
3311 hdd_err("Blacklist BSSID count %u exceeds max %u",
3312 count, MAX_BSSID_AVOID_LIST);
3313 goto fail;
3314 }
3315 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003316 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303317
3318 if (count &&
3319 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3320 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003321 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3322 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003323
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303324 if (i == count) {
3325 hdd_warn("Ignoring excess Blacklist BSSID");
3326 break;
3327 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003328
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303329 if (nla_parse(tb2,
3330 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3331 nla_data(curr_attr), nla_len(curr_attr),
3332 NULL)) {
3333 hdd_err("nla_parse failed");
3334 goto fail;
3335 }
3336 /* Parse and fetch MAC address */
3337 if (!tb2[PARAM_SET_BSSID]) {
3338 hdd_err("attr blacklist addr failed");
3339 goto fail;
3340 }
3341 nla_memcpy(
3342 roam_params.bssid_avoid_list[i].bytes,
3343 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3344 hdd_debug(MAC_ADDRESS_STR,
3345 MAC_ADDR_ARRAY(
3346 roam_params.bssid_avoid_list[i].bytes));
3347 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003348 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003349 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003350 if (i < count)
3351 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3352 i, count);
3353 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003354 sme_update_roam_params(pHddCtx->hHal, session_id,
3355 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3356 break;
3357 }
3358 return 0;
3359fail:
3360 return -EINVAL;
3361}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303362#undef PARAM_NUM_NW
3363#undef PARAM_SET_BSSID
3364#undef PRAM_SSID_LIST
3365#undef PARAM_LIST_SSID
3366
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003367
3368/**
3369 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3370 * @wiphy: pointer to wireless wiphy structure.
3371 * @wdev: pointer to wireless_dev structure.
3372 * @data: Pointer to the data to be passed via vendor interface
3373 * @data_len:Length of the data to be passed
3374 *
3375 * Return: Return the Success or Failure code.
3376 */
3377static int
3378wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3379 struct wireless_dev *wdev,
3380 const void *data,
3381 int data_len)
3382{
3383 int ret;
3384
3385 cds_ssr_protect(__func__);
3386 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3387 data, data_len);
3388 cds_ssr_unprotect(__func__);
3389
3390 return ret;
3391}
3392
3393static const struct nla_policy
3394wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3395 +1] = {
3396 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3397};
3398
3399/**
3400 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3401 * @hdd_ctx: HDD context
3402 * @device_mode: device mode
3403 * Return: bool
3404 */
3405static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003406 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003407{
3408 hdd_adapter_t *adapter;
3409 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3410 hdd_ap_ctx_t *ap_ctx;
3411 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303412 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003413
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303414 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003416 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303417 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003418 adapter = adapter_node->pAdapter;
3419
3420 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003421 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003422 ap_ctx =
3423 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3424
3425 /*
3426 * if there is SAP already running on DFS channel,
3427 * do not disable scan on dfs channels. Note that
3428 * with SAP on DFS, there cannot be conurrency on
3429 * single radio. But then we can have multiple
3430 * radios !!
3431 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003432 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3433 hdd_ctx->hdd_pdev,
3434 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003435 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003436 return true;
3437 }
3438 }
3439
3440 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003441 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003442 sta_ctx =
3443 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3444
3445 /*
3446 * if STA is already connected on DFS channel,
3447 * do not disable scan on dfs channels
3448 */
3449 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003450 (CHANNEL_STATE_DFS ==
3451 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3452 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003453 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003454 return true;
3455 }
3456 }
3457
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303458 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003459 adapter_node,
3460 &next);
3461 adapter_node = next;
3462 }
3463
3464 return false;
3465}
3466
3467/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003468 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003469 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003470 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003471 *
3472 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003473 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003474 * Fails the disable request if any device is active on a DFS channel.
3475 *
3476 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003477 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003478
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003479int wlan_hdd_enable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3480 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303482 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003483 bool err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003484
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003485 if (enable_dfs_channels == hdd_ctx->config->enableDFSChnlScan) {
3486 hdd_info("DFS channels are already %s",
3487 enable_dfs_channels ? "enabled" : "disabled");
3488 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003489 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003490
3491 if (!enable_dfs_channels) {
3492 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3493 QDF_STA_MODE);
3494 if (err)
3495 return -EOPNOTSUPP;
3496
3497 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
3498 QDF_SAP_MODE);
3499 if (err)
3500 return -EOPNOTSUPP;
3501 }
3502
3503 hdd_ctx->config->enableDFSChnlScan = enable_dfs_channels;
3504
3505 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3506
3507 /* pass dfs channel status to regulatory component */
3508 status = ucfg_reg_enable_dfs_channels(hdd_ctx->hdd_pdev,
3509 enable_dfs_channels);
3510
3511 if (QDF_IS_STATUS_ERROR(status))
3512 hdd_err("Failed to %s DFS channels",
3513 enable_dfs_channels ? "enable" : "disable");
3514
3515 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003516}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003517
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003518/**
3519 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3520 * @wiphy: corestack handler
3521 * @wdev: wireless device
3522 * @data: data
3523 * @data_len: data length
3524 * Return: success(0) or reason code for failure
3525 */
3526static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3527 struct wireless_dev *wdev,
3528 const void *data,
3529 int data_len)
3530{
3531 struct net_device *dev = wdev->netdev;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003532 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3533 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3534 int ret_val;
3535 uint32_t no_dfs_flag = 0;
3536
Jeff Johnson1f61b612016-02-12 16:28:33 -08003537 ENTER_DEV(dev);
3538
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003539 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303540 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003541 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003542
3543 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3544 data, data_len,
3545 wlan_hdd_set_no_dfs_flag_config_policy)) {
3546 hdd_err("invalid attr");
3547 return -EINVAL;
3548 }
3549
3550 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3551 hdd_err("attr dfs flag failed");
3552 return -EINVAL;
3553 }
3554
3555 no_dfs_flag = nla_get_u32(
3556 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3557
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003558 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003559
3560 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003561 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003562 return -EINVAL;
3563 }
3564
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07003565 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003566 return ret_val;
3567}
3568
3569/**
3570 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3571 *
3572 * @wiphy: wiphy device pointer
3573 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003574 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003575 * @data_len: Buffer length
3576 *
3577 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3578 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3579 *
3580 * Return: EOK or other error codes.
3581 */
3582
3583static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3584 struct wireless_dev *wdev,
3585 const void *data,
3586 int data_len)
3587{
3588 int ret;
3589
3590 cds_ssr_protect(__func__);
3591 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3592 data, data_len);
3593 cds_ssr_unprotect(__func__);
3594
3595 return ret;
3596}
3597
Manikandan Mohan80dea792016-04-28 16:36:48 -07003598static const struct nla_policy
3599wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3600 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3601};
3602
3603/**
3604 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3605 * @wiphy: wiphy device pointer
3606 * @wdev: wireless device pointer
3607 * @data: Vendor command data buffer
3608 * @data_len: Buffer length
3609 *
3610 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3611 * setup WISA Mode features.
3612 *
3613 * Return: Success(0) or reason code for failure
3614 */
3615static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3616 struct wireless_dev *wdev, const void *data, int data_len)
3617{
3618 struct net_device *dev = wdev->netdev;
3619 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3620 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3621 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3622 struct sir_wisa_params wisa;
3623 int ret_val;
3624 QDF_STATUS status;
3625 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003626 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3627 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003628
3629 ENTER_DEV(dev);
3630 ret_val = wlan_hdd_validate_context(hdd_ctx);
3631 if (ret_val)
3632 goto err;
3633
3634 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3635 hdd_err("Command not allowed in FTM mode");
3636 return -EPERM;
3637 }
3638
3639 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3640 wlan_hdd_wisa_cmd_policy)) {
3641 hdd_err("Invalid WISA cmd attributes");
3642 ret_val = -EINVAL;
3643 goto err;
3644 }
3645 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3646 hdd_err("Invalid WISA mode");
3647 ret_val = -EINVAL;
3648 goto err;
3649 }
3650
3651 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003652 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003653 wisa.mode = wisa_mode;
3654 wisa.vdev_id = adapter->sessionId;
3655 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003656 if (!QDF_IS_STATUS_SUCCESS(status)) {
3657 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003658 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003659 }
3660 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003661 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003662 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3663 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003664 adapter->sessionId),
3665 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003666err:
3667 EXIT();
3668 return ret_val;
3669}
3670
3671/**
3672 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3673 * @wiphy: corestack handler
3674 * @wdev: wireless device
3675 * @data: data
3676 * @data_len: data length
3677 *
3678 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3679 * setup WISA mode features.
3680 *
3681 * Return: Success(0) or reason code for failure
3682 */
3683static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3684 struct wireless_dev *wdev,
3685 const void *data,
3686 int data_len)
3687{
3688 int ret;
3689
3690 cds_ssr_protect(__func__);
3691 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3692 cds_ssr_unprotect(__func__);
3693
3694 return ret;
3695}
3696
Anurag Chouhan96919482016-07-13 16:36:57 +05303697/*
3698 * define short names for the global vendor params
3699 * used by __wlan_hdd_cfg80211_get_station_cmd()
3700 */
3701#define STATION_INVALID \
3702 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3703#define STATION_INFO \
3704 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3705#define STATION_ASSOC_FAIL_REASON \
3706 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3707#define STATION_MAX \
3708 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3709
3710static const struct nla_policy
3711hdd_get_station_policy[STATION_MAX + 1] = {
3712 [STATION_INFO] = {.type = NLA_FLAG},
3713 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3714};
3715
3716/**
3717 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3718 * @hdd_ctx: HDD context within host driver
3719 * @wdev: wireless device
3720 *
3721 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3722 * Validate cmd attributes and send the station info to upper layers.
3723 *
3724 * Return: Success(0) or reason code for failure
3725 */
3726static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3727 hdd_adapter_t *adapter)
3728{
3729 struct sk_buff *skb = NULL;
3730 uint32_t nl_buf_len;
3731 hdd_station_ctx_t *hdd_sta_ctx;
3732
3733 nl_buf_len = NLMSG_HDRLEN;
3734 nl_buf_len += sizeof(uint32_t);
3735 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3736
3737 if (!skb) {
3738 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3739 return -ENOMEM;
3740 }
3741
3742 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3743
3744 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3745 hdd_sta_ctx->conn_info.assoc_status_code)) {
3746 hdd_err("put fail");
3747 goto fail;
3748 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303749
3750 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
3751 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
3752 hdd_sta_ctx->conn_info.cca)) {
3753 hdd_err("put fail");
3754 goto fail;
3755 }
3756
Anurag Chouhan96919482016-07-13 16:36:57 +05303757 return cfg80211_vendor_cmd_reply(skb);
3758fail:
3759 if (skb)
3760 kfree_skb(skb);
3761 return -EINVAL;
3762}
3763
3764/**
3765 * hdd_map_auth_type() - transform auth type specific to
3766 * vendor command
3767 * @auth_type: csr auth type
3768 *
3769 * Return: Success(0) or reason code for failure
3770 */
3771static int hdd_convert_auth_type(uint32_t auth_type)
3772{
3773 uint32_t ret_val;
3774
3775 switch (auth_type) {
3776 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3777 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3778 break;
3779 case eCSR_AUTH_TYPE_SHARED_KEY:
3780 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3781 break;
3782 case eCSR_AUTH_TYPE_WPA:
3783 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3784 break;
3785 case eCSR_AUTH_TYPE_WPA_PSK:
3786 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3787 break;
3788 case eCSR_AUTH_TYPE_AUTOSWITCH:
3789 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3790 break;
3791 case eCSR_AUTH_TYPE_WPA_NONE:
3792 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3793 break;
3794 case eCSR_AUTH_TYPE_RSN:
3795 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3796 break;
3797 case eCSR_AUTH_TYPE_RSN_PSK:
3798 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3799 break;
3800 case eCSR_AUTH_TYPE_FT_RSN:
3801 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3802 break;
3803 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3804 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3805 break;
3806 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3807 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3808 break;
3809 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3810 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3811 break;
3812 case eCSR_AUTH_TYPE_CCKM_WPA:
3813 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3814 break;
3815 case eCSR_AUTH_TYPE_CCKM_RSN:
3816 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3817 break;
3818 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3819 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3820 break;
3821 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3822 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3823 break;
3824 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3825 case eCSR_AUTH_TYPE_FAILED:
3826 case eCSR_AUTH_TYPE_NONE:
3827 default:
3828 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3829 break;
3830 }
3831 return ret_val;
3832}
3833
3834/**
3835 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3836 * vendor command
3837 * @dot11mode: dot11mode
3838 *
3839 * Return: Success(0) or reason code for failure
3840 */
3841static int hdd_convert_dot11mode(uint32_t dot11mode)
3842{
3843 uint32_t ret_val;
3844
3845 switch (dot11mode) {
3846 case eCSR_CFG_DOT11_MODE_11A:
3847 ret_val = QCA_WLAN_802_11_MODE_11A;
3848 break;
3849 case eCSR_CFG_DOT11_MODE_11B:
3850 ret_val = QCA_WLAN_802_11_MODE_11B;
3851 break;
3852 case eCSR_CFG_DOT11_MODE_11G:
3853 ret_val = QCA_WLAN_802_11_MODE_11G;
3854 break;
3855 case eCSR_CFG_DOT11_MODE_11N:
3856 ret_val = QCA_WLAN_802_11_MODE_11N;
3857 break;
3858 case eCSR_CFG_DOT11_MODE_11AC:
3859 ret_val = QCA_WLAN_802_11_MODE_11AC;
3860 break;
3861 case eCSR_CFG_DOT11_MODE_AUTO:
3862 case eCSR_CFG_DOT11_MODE_ABG:
3863 default:
3864 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3865 }
3866 return ret_val;
3867}
3868
3869/**
3870 * hdd_add_tx_bitrate() - add tx bitrate attribute
3871 * @skb: pointer to sk buff
3872 * @hdd_sta_ctx: pointer to hdd station context
3873 * @idx: attribute index
3874 *
3875 * Return: Success(0) or reason code for failure
3876 */
3877static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3878 hdd_station_ctx_t *hdd_sta_ctx,
3879 int idx)
3880{
3881 struct nlattr *nla_attr;
3882 uint32_t bitrate, bitrate_compat;
3883
3884 nla_attr = nla_nest_start(skb, idx);
3885 if (!nla_attr)
3886 goto fail;
3887 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3888 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3889
3890 /* report 16-bit bitrate only if we can */
3891 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3892 if (bitrate > 0 &&
3893 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3894 hdd_err("put fail");
3895 goto fail;
3896 }
3897 if (bitrate_compat > 0 &&
3898 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3899 hdd_err("put fail");
3900 goto fail;
3901 }
3902 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3903 hdd_sta_ctx->conn_info.txrate.nss)) {
3904 hdd_err("put fail");
3905 goto fail;
3906 }
3907 nla_nest_end(skb, nla_attr);
3908 return 0;
3909fail:
3910 return -EINVAL;
3911}
3912
3913/**
3914 * hdd_add_sta_info() - add station info attribute
3915 * @skb: pointer to sk buff
3916 * @hdd_sta_ctx: pointer to hdd station context
3917 * @idx: attribute index
3918 *
3919 * Return: Success(0) or reason code for failure
3920 */
3921static int32_t hdd_add_sta_info(struct sk_buff *skb,
3922 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3923{
3924 struct nlattr *nla_attr;
3925
3926 nla_attr = nla_nest_start(skb, idx);
3927 if (!nla_attr)
3928 goto fail;
3929 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3930 (hdd_sta_ctx->conn_info.signal + 100))) {
3931 hdd_err("put fail");
3932 goto fail;
3933 }
3934 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3935 goto fail;
3936 nla_nest_end(skb, nla_attr);
3937 return 0;
3938fail:
3939 return -EINVAL;
3940}
3941
3942/**
3943 * hdd_add_survey_info() - add survey info attribute
3944 * @skb: pointer to sk buff
3945 * @hdd_sta_ctx: pointer to hdd station context
3946 * @idx: attribute index
3947 *
3948 * Return: Success(0) or reason code for failure
3949 */
3950static int32_t hdd_add_survey_info(struct sk_buff *skb,
3951 hdd_station_ctx_t *hdd_sta_ctx,
3952 int idx)
3953{
3954 struct nlattr *nla_attr;
3955
3956 nla_attr = nla_nest_start(skb, idx);
3957 if (!nla_attr)
3958 goto fail;
3959 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3960 hdd_sta_ctx->conn_info.freq) ||
3961 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3962 (hdd_sta_ctx->conn_info.noise + 100))) {
3963 hdd_err("put fail");
3964 goto fail;
3965 }
3966 nla_nest_end(skb, nla_attr);
3967 return 0;
3968fail:
3969 return -EINVAL;
3970}
3971
3972/**
3973 * hdd_add_link_standard_info() - add link info attribute
3974 * @skb: pointer to sk buff
3975 * @hdd_sta_ctx: pointer to hdd station context
3976 * @idx: attribute index
3977 *
3978 * Return: Success(0) or reason code for failure
3979 */
3980static int32_t
3981hdd_add_link_standard_info(struct sk_buff *skb,
3982 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3983{
3984 struct nlattr *nla_attr;
3985
3986 nla_attr = nla_nest_start(skb, idx);
3987 if (!nla_attr)
3988 goto fail;
3989 if (nla_put(skb,
3990 NL80211_ATTR_SSID,
3991 hdd_sta_ctx->conn_info.SSID.SSID.length,
3992 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3993 hdd_err("put fail");
3994 goto fail;
3995 }
3996 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3997 goto fail;
3998 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3999 goto fail;
4000 nla_nest_end(skb, nla_attr);
4001 return 0;
4002fail:
4003 return -EINVAL;
4004}
4005
4006/**
4007 * hdd_add_ap_standard_info() - add ap info attribute
4008 * @skb: pointer to sk buff
4009 * @hdd_sta_ctx: pointer to hdd station context
4010 * @idx: attribute index
4011 *
4012 * Return: Success(0) or reason code for failure
4013 */
4014static int32_t
4015hdd_add_ap_standard_info(struct sk_buff *skb,
4016 hdd_station_ctx_t *hdd_sta_ctx, int idx)
4017{
4018 struct nlattr *nla_attr;
4019
4020 nla_attr = nla_nest_start(skb, idx);
4021 if (!nla_attr)
4022 goto fail;
4023 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
4024 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
4025 sizeof(hdd_sta_ctx->conn_info.vht_caps),
4026 &hdd_sta_ctx->conn_info.vht_caps)) {
4027 hdd_err("put fail");
4028 goto fail;
4029 }
4030 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
4031 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
4032 sizeof(hdd_sta_ctx->conn_info.ht_caps),
4033 &hdd_sta_ctx->conn_info.ht_caps)) {
4034 hdd_err("put fail");
4035 goto fail;
4036 }
4037 nla_nest_end(skb, nla_attr);
4038 return 0;
4039fail:
4040 return -EINVAL;
4041}
4042
4043/**
4044 * hdd_get_station_info() - send BSS information to supplicant
4045 * @hdd_ctx: pointer to hdd context
4046 * @adapter: pointer to adapter
4047 *
4048 * Return: 0 if success else error status
4049 */
4050static int hdd_get_station_info(hdd_context_t *hdd_ctx,
4051 hdd_adapter_t *adapter)
4052{
4053 struct sk_buff *skb = NULL;
4054 uint8_t *tmp_hs20 = NULL;
4055 uint32_t nl_buf_len;
4056 hdd_station_ctx_t *hdd_sta_ctx;
4057
4058 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4059
4060 nl_buf_len = NLMSG_HDRLEN;
4061 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
4062 sizeof(hdd_sta_ctx->conn_info.freq) +
4063 sizeof(hdd_sta_ctx->conn_info.noise) +
4064 sizeof(hdd_sta_ctx->conn_info.signal) +
4065 (sizeof(uint32_t) * 2) +
4066 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
4067 sizeof(hdd_sta_ctx->conn_info.roam_count) +
4068 sizeof(hdd_sta_ctx->conn_info.authType) +
4069 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
4070 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
4071 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
4072 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
4073 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
4074 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
4075 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
4076 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
4077 1);
4078 }
4079 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
4080 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
4081 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
4082 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
4083
4084
4085 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
4086 if (!skb) {
4087 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
4088 return -ENOMEM;
4089 }
4090
4091 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
4092 LINK_INFO_STANDARD_NL80211_ATTR)) {
4093 hdd_err("put fail");
4094 goto fail;
4095 }
4096 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
4097 AP_INFO_STANDARD_NL80211_ATTR)) {
4098 hdd_err("put fail");
4099 goto fail;
4100 }
4101 if (nla_put_u32(skb, INFO_ROAM_COUNT,
4102 hdd_sta_ctx->conn_info.roam_count) ||
4103 nla_put_u32(skb, INFO_AKM,
4104 hdd_convert_auth_type(
4105 hdd_sta_ctx->conn_info.authType)) ||
4106 nla_put_u32(skb, WLAN802_11_MODE,
4107 hdd_convert_dot11mode(
4108 hdd_sta_ctx->conn_info.dot11Mode))) {
4109 hdd_err("put fail");
4110 goto fail;
4111 }
4112 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
4113 if (nla_put(skb, HT_OPERATION,
4114 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
4115 &hdd_sta_ctx->conn_info.ht_operation)) {
4116 hdd_err("put fail");
4117 goto fail;
4118 }
4119 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
4120 if (nla_put(skb, VHT_OPERATION,
4121 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
4122 &hdd_sta_ctx->conn_info.vht_operation)) {
4123 hdd_err("put fail");
4124 goto fail;
4125 }
4126 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
4127 if (nla_put(skb, AP_INFO_HS20_INDICATION,
4128 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
4129 tmp_hs20 + 1)) {
4130 hdd_err("put fail");
4131 goto fail;
4132 }
4133
4134 return cfg80211_vendor_cmd_reply(skb);
4135fail:
4136 if (skb)
4137 kfree_skb(skb);
4138 return -EINVAL;
4139}
4140
4141/**
4142 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4143 * @wiphy: corestack handler
4144 * @wdev: wireless device
4145 * @data: data
4146 * @data_len: data length
4147 *
4148 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4149 * Validate cmd attributes and send the station info to upper layers.
4150 *
4151 * Return: Success(0) or reason code for failure
4152 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05304153static int
Anurag Chouhan96919482016-07-13 16:36:57 +05304154__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4155 struct wireless_dev *wdev,
4156 const void *data,
4157 int data_len)
4158{
4159 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4160 struct net_device *dev = wdev->netdev;
4161 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4162 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
4163 int32_t status;
4164
4165 ENTER_DEV(dev);
4166 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4167 hdd_err("Command not allowed in FTM mode");
4168 status = -EPERM;
4169 goto out;
4170 }
4171
4172 status = wlan_hdd_validate_context(hdd_ctx);
4173 if (0 != status)
4174 goto out;
4175
4176
4177 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
4178 data, data_len, NULL);
4179 if (status) {
4180 hdd_err("Invalid ATTR");
4181 goto out;
4182 }
4183
4184 /* Parse and fetch Command Type*/
4185 if (tb[STATION_INFO]) {
4186 status = hdd_get_station_info(hdd_ctx, adapter);
4187 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
4188 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
4189 } else {
4190 hdd_err("get station info cmd type failed");
4191 status = -EINVAL;
4192 goto out;
4193 }
4194 EXIT();
4195out:
4196 return status;
4197}
4198
4199/**
4200 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
4201 * @wiphy: corestack handler
4202 * @wdev: wireless device
4203 * @data: data
4204 * @data_len: data length
4205 *
4206 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
4207 * Validate cmd attributes and send the station info to upper layers.
4208 *
4209 * Return: Success(0) or reason code for failure
4210 */
4211static int32_t
4212hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
4213 struct wireless_dev *wdev,
4214 const void *data,
4215 int data_len)
4216{
4217 int ret;
4218
4219 cds_ssr_protect(__func__);
4220 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
4221 cds_ssr_unprotect(__func__);
4222
4223 return ret;
4224}
4225
4226/*
4227 * undef short names defined for get station command
4228 * used by __wlan_hdd_cfg80211_get_station_cmd()
4229 */
4230#undef STATION_INVALID
4231#undef STATION_INFO
4232#undef STATION_ASSOC_FAIL_REASON
4233#undef STATION_MAX
4234
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004235#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4236/**
4237 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4238 * @wiphy: pointer to wireless wiphy structure.
4239 * @wdev: pointer to wireless_dev structure.
4240 * @data: Pointer to the Key data
4241 * @data_len:Length of the data passed
4242 *
4243 * This is called when wlan driver needs to save the keys received via
4244 * vendor specific command.
4245 *
4246 * Return: Return the Success or Failure code.
4247 */
4248static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4249 struct wireless_dev *wdev,
4250 const void *data, int data_len)
4251{
4252 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4253 struct net_device *dev = wdev->netdev;
4254 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4255 hdd_context_t *hdd_ctx_ptr;
4256 int status;
4257
Jeff Johnson1f61b612016-02-12 16:28:33 -08004258 ENTER_DEV(dev);
4259
Anurag Chouhan6d760662016-02-20 16:05:43 +05304260 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004261 hdd_err("Command not allowed in FTM mode");
4262 return -EPERM;
4263 }
4264
4265 if ((data == NULL) || (data_len == 0) ||
4266 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004267 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004268 return -EINVAL;
4269 }
4270
4271 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4272 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004273 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004274 return -EINVAL;
4275 }
4276
4277 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304278 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004280 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4281 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004282 true,
4283 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304284 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4285 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004286 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4287 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4288 return 0;
4289}
4290
4291/**
4292 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4293 * @wiphy: pointer to wireless wiphy structure.
4294 * @wdev: pointer to wireless_dev structure.
4295 * @data: Pointer to the Key data
4296 * @data_len:Length of the data passed
4297 *
4298 * This is called when wlan driver needs to save the keys received via
4299 * vendor specific command.
4300 *
4301 * Return: Return the Success or Failure code.
4302 */
4303static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4304 struct wireless_dev *wdev,
4305 const void *data, int data_len)
4306{
4307 int ret;
4308
4309 cds_ssr_protect(__func__);
4310 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4311 cds_ssr_unprotect(__func__);
4312
4313 return ret;
4314}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004315#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004316
4317static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4318 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4319 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4320 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004321 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004322};
4323
4324/**
4325 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4326 * @wiphy: pointer to wireless wiphy structure.
4327 * @wdev: pointer to wireless_dev structure.
4328 * @data: Pointer to the data to be passed via vendor interface
4329 * @data_len:Length of the data to be passed
4330 *
4331 * This is called when wlan driver needs to send wifi driver related info
4332 * (driver/fw version) to the user space application upon request.
4333 *
4334 * Return: Return the Success or Failure code.
4335 */
4336static int
4337__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4338 struct wireless_dev *wdev,
4339 const void *data, int data_len)
4340{
4341 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4342 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004343 tSirVersionString driver_version;
4344 tSirVersionString firmware_version;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004345 const char *hw_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004346 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004347 uint32_t sub_id = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004348 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004349 struct sk_buff *reply_skb;
4350 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004351
Jeff Johnson1f61b612016-02-12 16:28:33 -08004352 ENTER_DEV(wdev->netdev);
4353
Anurag Chouhan6d760662016-02-20 16:05:43 +05304354 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 hdd_err("Command not allowed in FTM mode");
4356 return -EPERM;
4357 }
4358
4359 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304360 if (status)
4361 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362
4363 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4364 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004365 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004366 return -EINVAL;
4367 }
4368
4369 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004370 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004371 strlcpy(driver_version, QWLAN_VERSIONSTR,
4372 sizeof(driver_version));
4373 skb_len += strlen(driver_version) + 1;
4374 count++;
4375 }
4376
4377 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004378 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004379 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4380 &crmid);
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004381 sub_id = (hdd_ctx->target_fw_vers_ext & 0xf0000000) >> 28;
4382 hw_version = hdd_ctx->target_hw_name;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004383 snprintf(firmware_version, sizeof(firmware_version),
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07004384 "FW:%d.%d.%d.%d.%d HW:%s", major_spid, minor_spid,
4385 siid, crmid, sub_id, hw_version);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004386 skb_len += strlen(firmware_version) + 1;
4387 count++;
4388 }
4389
4390 if (count == 0) {
4391 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004392 return -EINVAL;
4393 }
4394
Ryan Hsu7ac88852016-04-28 10:20:34 -07004395 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4396 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4397
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004398 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004399 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 return -ENOMEM;
4401 }
4402
Ryan Hsu7ac88852016-04-28 10:20:34 -07004403 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4404 if (nla_put_string(reply_skb,
4405 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4406 driver_version))
4407 goto error_nla_fail;
4408 }
4409
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304410 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004411 if (nla_put_string(reply_skb,
4412 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4413 firmware_version))
4414 goto error_nla_fail;
4415 }
4416
4417 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4418 if (nla_put_u32(reply_skb,
4419 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4420 hdd_ctx->radio_index))
4421 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004422 }
4423
4424 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004425
4426error_nla_fail:
4427 hdd_err("nla put fail");
4428 kfree_skb(reply_skb);
4429 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430}
4431
4432/**
4433 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4434 * @wiphy: pointer to wireless wiphy structure.
4435 * @wdev: pointer to wireless_dev structure.
4436 * @data: Pointer to the data to be passed via vendor interface
4437 * @data_len:Length of the data to be passed
4438 *
4439 * This is called when wlan driver needs to send wifi driver related info
4440 * (driver/fw version) to the user space application upon request.
4441 *
4442 * Return: Return the Success or Failure code.
4443 */
4444static int
4445wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4446 struct wireless_dev *wdev,
4447 const void *data, int data_len)
4448{
4449 int ret;
4450
4451 cds_ssr_protect(__func__);
4452 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4453 cds_ssr_unprotect(__func__);
4454
4455 return ret;
4456}
4457
4458/**
4459 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4460 * @wiphy: pointer to wireless wiphy structure.
4461 * @wdev: pointer to wireless_dev structure.
4462 * @data: Pointer to the data to be passed via vendor interface
4463 * @data_len:Length of the data to be passed
4464 *
4465 * This is called by userspace to know the supported logger features
4466 *
4467 * Return: Return the Success or Failure code.
4468 */
4469static int
4470__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4471 struct wireless_dev *wdev,
4472 const void *data, int data_len)
4473{
4474 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4475 int status;
4476 uint32_t features;
4477 struct sk_buff *reply_skb = NULL;
4478
Jeff Johnson1f61b612016-02-12 16:28:33 -08004479 ENTER_DEV(wdev->netdev);
4480
Anurag Chouhan6d760662016-02-20 16:05:43 +05304481 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004482 hdd_err("Command not allowed in FTM mode");
4483 return -EPERM;
4484 }
4485
4486 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304487 if (status)
4488 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004489
4490 features = 0;
4491
4492 if (hdd_is_memdump_supported())
4493 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4494 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4495 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4496 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4497
4498 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4499 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4500 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004501 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004502 return -ENOMEM;
4503 }
4504
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004505 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004506 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4507 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004508 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004509 kfree_skb(reply_skb);
4510 return -EINVAL;
4511 }
4512
4513 return cfg80211_vendor_cmd_reply(reply_skb);
4514}
4515
4516/**
4517 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4518 * @wiphy: pointer to wireless wiphy structure.
4519 * @wdev: pointer to wireless_dev structure.
4520 * @data: Pointer to the data to be passed via vendor interface
4521 * @data_len:Length of the data to be passed
4522 *
4523 * This is called by userspace to know the supported logger features
4524 *
4525 * Return: Return the Success or Failure code.
4526 */
4527static int
4528wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4529 struct wireless_dev *wdev,
4530 const void *data, int data_len)
4531{
4532 int ret;
4533
4534 cds_ssr_protect(__func__);
4535 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4536 data, data_len);
4537 cds_ssr_unprotect(__func__);
4538
4539 return ret;
4540}
4541
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004542#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004543/**
4544 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304545 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004546 * @bssid: pointer to bssid of roamed AP.
4547 * @req_rsn_ie: Pointer to request RSN IE
4548 * @req_rsn_len: Length of the request RSN IE
4549 * @rsp_rsn_ie: Pointer to response RSN IE
4550 * @rsp_rsn_len: Length of the response RSN IE
4551 * @roam_info_ptr: Pointer to the roaming related information
4552 *
4553 * This is called when wlan driver needs to send the roaming and
4554 * authorization information after roaming.
4555 *
4556 * The information that would be sent is the request RSN IE, response
4557 * RSN IE and BSSID of the newly roamed AP.
4558 *
4559 * If the Authorized status is authenticated, then additional parameters
4560 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4561 * supplicant.
4562 *
4563 * The supplicant upon receiving this event would ignore the legacy
4564 * cfg80211_roamed call and use the entire information from this event.
4565 * The cfg80211_roamed should still co-exist since the kernel will
4566 * make use of the parameters even if the supplicant ignores it.
4567 *
4568 * Return: Return the Success or Failure code.
4569 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304570int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004571 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4572 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4573{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304574 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004575 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004576 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004577 ENTER();
4578
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304579 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004580 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004582 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004583 !roam_info_ptr->roamSynchInProgress)
4584 return 0;
4585
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004586 /*
4587 * The user space has issued a disconnect when roaming is in
4588 * progress. The disconnect should be honored gracefully.
4589 * If the roaming is complete and the roam event is sent
4590 * back to the user space, it will get confused as it is
4591 * expecting a disconnect event. So, do not send the event
4592 * and handle the disconnect later.
4593 */
4594 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004595 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004596 return 0;
4597 }
4598
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004599 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304600 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004601 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4602 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4603 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004604 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004605 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4606 GFP_KERNEL);
4607
4608 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004609 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004610 return -EINVAL;
4611 }
4612
4613 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4614 ETH_ALEN, bssid) ||
4615 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4616 req_rsn_len, req_rsn_ie) ||
4617 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4618 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004619 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004620 goto nla_put_failure;
4621 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004622 if (roam_info_ptr->synchAuthStatus ==
4623 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004624 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004625 if (nla_put_u8(skb,
4626 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4627 hdd_err("nla put fail");
4628 goto nla_put_failure;
4629 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004630 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4631 /* if FT or CCKM connection: dont send replay counter */
4632 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4633 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4634 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4635 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4636 nla_put(skb,
4637 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4638 SIR_REPLAY_CTR_LEN,
4639 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004640 hdd_err("non FT/non CCKM connection");
4641 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004642 goto nla_put_failure;
4643 }
4644 if (nla_put(skb,
4645 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4646 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4647 nla_put(skb,
4648 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4649 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4650 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004651 goto nla_put_failure;
4652 }
4653 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004654 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004655 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4656 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004657 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004658 goto nla_put_failure;
4659 }
4660 }
4661
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304662 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4663 roam_info_ptr->synchAuthStatus,
4664 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004665
4666 /*
4667 * Add subnet change status if subnet has changed
4668 * 0 = unchanged
4669 * 1 = changed
4670 * 2 = unknown
4671 */
4672 if (roam_info_ptr->subnet_change_status) {
4673 if (nla_put_u8(skb,
4674 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4675 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004676 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004677 goto nla_put_failure;
4678 }
4679 }
4680
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681 cfg80211_vendor_event(skb, GFP_KERNEL);
4682 return 0;
4683
4684nla_put_failure:
4685 kfree_skb(skb);
4686 return -EINVAL;
4687}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004688#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689
lifeng907edd62017-05-12 10:10:36 +08004690#define ANT_DIV_PROBE_PERIOD \
4691 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD
4692#define ANT_DIV_STAY_PERIOD \
4693 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD
4694#define ANT_DIV_SNR_DIFF \
4695 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF
4696#define ANT_DIV_PROBE_DWELL_TIME \
4697 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME
4698#define ANT_DIV_MGMT_SNR_WEIGHT \
4699 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT
4700#define ANT_DIV_DATA_SNR_WEIGHT \
4701 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT
4702#define ANT_DIV_ACK_SNR_WEIGHT \
4703 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004704static const struct nla_policy
4705wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4706
4707 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4708 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4709 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304710 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304711 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4712 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004713 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4714 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4715 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4716 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4717 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304718 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
lifeng907edd62017-05-12 10:10:36 +08004719 [ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
4720 [ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
4721 [ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
4722 [ANT_DIV_PROBE_DWELL_TIME] = {.type = NLA_U32},
4723 [ANT_DIV_MGMT_SNR_WEIGHT] = {.type = NLA_U32},
4724 [ANT_DIV_DATA_SNR_WEIGHT] = {.type = NLA_U32},
4725 [ANT_DIV_ACK_SNR_WEIGHT] = {.type = NLA_U32},
Ajit Pal Singh747b6802017-05-24 15:42:03 +05304726 [QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL] = {.type = NLA_U8},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004727};
4728
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004729/**
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304730 * wlan_hdd_add_qcn_ie() - Add QCN IE to a given IE buffer
4731 * @ie_data: IE buffer
4732 * @ie_len: length of the @ie_data
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304733 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304734 * Return: QDF_STATUS
4735 */
4736static QDF_STATUS wlan_hdd_add_qcn_ie(uint8_t *ie_data, uint16_t *ie_len)
4737{
4738 tDot11fIEQCN_IE qcn_ie;
4739 uint8_t qcn_ie_hdr[QCN_IE_HDR_LEN]
4740 = {IE_EID_VENDOR, DOT11F_IE_QCN_IE_MAX_LEN,
4741 0x8C, 0xFD, 0xF0, 0x1};
4742
4743 if (((*ie_len) + QCN_IE_HDR_LEN +
4744 QCN_IE_VERSION_SUBATTR_DATA_LEN) > MAX_DEFAULT_SCAN_IE_LEN) {
4745 hdd_err("IE buffer not enough for QCN IE");
4746 return QDF_STATUS_E_FAILURE;
4747 }
4748
4749 /* Add QCN IE header */
4750 qdf_mem_copy(ie_data + (*ie_len), qcn_ie_hdr, QCN_IE_HDR_LEN);
4751 (*ie_len) += QCN_IE_HDR_LEN;
4752
4753 /* Retrieve Version sub-attribute data */
4754 populate_dot11f_qcn_ie(&qcn_ie);
4755
4756 /* Add QCN IE data[version sub attribute] */
4757 qdf_mem_copy(ie_data + (*ie_len), qcn_ie.version,
4758 (QCN_IE_VERSION_SUBATTR_LEN));
4759 (*ie_len) += (QCN_IE_VERSION_SUBATTR_LEN);
4760
4761 return QDF_STATUS_SUCCESS;
4762}
4763
4764/**
4765 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4766 * @hdd_ctx: HDD context
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304767 * @adapter: Pointer to HDD adapter
4768 * @ie_data: Pointer to Scan IEs buffer
4769 * @ie_len: Length of Scan IEs
4770 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304771 * This API is used to store the default scan ies received from
4772 * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
4773 *
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304774 * Return: 0 on success; error number otherwise
4775 */
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304776static int wlan_hdd_save_default_scan_ies(hdd_context_t *hdd_ctx,
4777 hdd_adapter_t *adapter,
4778 uint8_t *ie_data, uint16_t ie_len)
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304779{
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304780 hdd_scaninfo_t *scan_info = &adapter->scan_info;
4781 bool add_qcn_ie = hdd_ctx->config->qcn_ie_support;
4782
4783 if (!scan_info)
4784 return -EINVAL;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304785
4786 if (scan_info->default_scan_ies) {
4787 qdf_mem_free(scan_info->default_scan_ies);
4788 scan_info->default_scan_ies = NULL;
4789 }
4790
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304791 scan_info->default_scan_ies_len = ie_len;
4792
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304793 if (add_qcn_ie)
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304794 ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304795
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304796 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304797 if (!scan_info->default_scan_ies) {
4798 scan_info->default_scan_ies_len = 0;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304799 return -ENOMEM;
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304800 }
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304801
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05304802 qdf_mem_copy(scan_info->default_scan_ies, ie_data,
4803 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05304804
4805 /* Add QCN IE if g_qcn_ie_support INI is enabled */
4806 if (add_qcn_ie)
4807 wlan_hdd_add_qcn_ie(scan_info->default_scan_ies,
4808 &(scan_info->default_scan_ies_len));
4809
4810 hdd_debug("Saved default scan IE:");
4811 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
4812 (uint8_t *) scan_info->default_scan_ies,
4813 scan_info->default_scan_ies_len);
4814
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304815 return 0;
4816}
4817
4818/**
Ajit Pal Singh747b6802017-05-24 15:42:03 +05304819 * wlan_hdd_handle_restrict_offchan_config() -
4820 * Handle wifi configuration attribute :
4821 * QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL
4822 * @adapter: Pointer to HDD adapter
4823 * @restrict_offchan: Restrict offchannel setting done by
4824 * application
4825 *
4826 * Return: 0 on success; error number otherwise
4827 */
4828static int wlan_hdd_handle_restrict_offchan_config(hdd_adapter_t *adapter,
4829 u8 restrict_offchan)
4830{
4831 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
4832 enum tQDF_ADAPTER_MODE dev_mode = adapter->device_mode;
4833 int ret_val = 0;
4834
4835 if (!(dev_mode == QDF_SAP_MODE || dev_mode == QDF_P2P_GO_MODE)) {
4836 hdd_err("Invalid interface type:%d", dev_mode);
4837 return -EINVAL;
4838 }
4839 /*
4840 * To cater to multiple apps we maintain
4841 * a counter to check if restrict_offchannel
4842 * is enabled or disabled per AP/GO vdev.
4843 */
4844 if (restrict_offchan == 1) {
4845 enum policy_mgr_con_mode pmode =
4846 policy_mgr_convert_device_mode_to_qdf_type(dev_mode);
4847 int chan;
4848
4849 adapter->restrict_offchannel_cnt++;
4850 if (adapter->restrict_offchannel_cnt == 1) {
4851 u32 vdev_id = wlan_vdev_get_id(adapter->hdd_vdev);
4852
4853 wlan_vdev_obj_lock(adapter->hdd_vdev);
4854 wlan_vdev_mlme_cap_set(adapter->hdd_vdev,
4855 WLAN_VDEV_C_RESTRICT_OFFCHAN);
4856 wlan_vdev_obj_unlock(adapter->hdd_vdev);
4857 chan = policy_mgr_get_channel(hdd_ctx->hdd_psoc, pmode,
4858 &vdev_id);
4859 if (!chan ||
4860 wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, chan)) {
4861 hdd_err("unable to send avoid_freq");
4862 ret_val = -EINVAL;
4863 }
4864 }
4865 } else if ((restrict_offchan == 0) &&
4866 (adapter->restrict_offchannel_cnt > 0)) {
4867 adapter->restrict_offchannel_cnt--;
4868 if (adapter->restrict_offchannel_cnt == 0) {
4869 wlan_vdev_obj_lock(adapter->hdd_vdev);
4870 wlan_vdev_mlme_cap_clear(adapter->hdd_vdev,
4871 WLAN_VDEV_C_RESTRICT_OFFCHAN);
4872 wlan_vdev_obj_unlock(adapter->hdd_vdev);
4873 if (wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0)) {
4874 hdd_err("unable to clear avoid_freq");
4875 ret_val = -EINVAL;
4876 }
4877 }
4878 } else {
4879 ret_val = -EINVAL;
4880 hdd_err("Invalid RESTRICT_OFFCHAN setting");
4881 }
4882
4883 return ret_val;
4884}
4885
4886/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004887 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4888 * vendor command
4889 *
4890 * @wiphy: wiphy device pointer
4891 * @wdev: wireless device pointer
4892 * @data: Vendor command data buffer
4893 * @data_len: Buffer length
4894 *
4895 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4896 *
4897 * Return: Error code.
4898 */
4899static int
4900__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4901 struct wireless_dev *wdev,
4902 const void *data,
4903 int data_len)
4904{
4905 struct net_device *dev = wdev->netdev;
4906 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4907 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4908 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4909 int ret_val = 0;
4910 u32 modulated_dtim;
4911 u16 stats_avg_factor;
4912 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304913 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004914 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004915 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304916 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304917 int attr_len;
4918 int access_policy = 0;
4919 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4920 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304921 uint16_t scan_ie_len = 0;
4922 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304923 struct sir_set_tx_rx_aggregation_size request;
4924 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004925 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004926 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004927 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304928 uint32_t tx_fail_count;
lifeng907edd62017-05-12 10:10:36 +08004929 uint32_t ant_div_usrcfg;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304930
Jeff Johnson1f61b612016-02-12 16:28:33 -08004931 ENTER_DEV(dev);
4932
Anurag Chouhan6d760662016-02-20 16:05:43 +05304933 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004934 hdd_err("Command not allowed in FTM mode");
4935 return -EPERM;
4936 }
4937
4938 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304939 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004940 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004941
4942 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4943 data, data_len,
4944 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004945 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004946 return -EINVAL;
4947 }
4948
Krunal Sonie3531942016-04-12 17:43:53 -07004949 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4950 ftm_capab = nla_get_u32(tb[
4951 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4952 hdd_ctx->config->fine_time_meas_cap =
4953 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4954 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304955 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004956 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004957 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4958 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004959 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004960 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4961 hdd_ctx->config->fine_time_meas_cap);
4962 }
4963
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004964 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4965 modulated_dtim = nla_get_u32(
4966 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4967
4968 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4969 adapter->sessionId,
4970 modulated_dtim);
4971
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304972 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004973 ret_val = -EPERM;
4974 }
4975
Kapil Gupta6213c012016-09-02 19:39:09 +05304976 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4977 qpower = nla_get_u8(
4978 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4979 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4980 ret_val = -EINVAL;
4981 }
4982
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004983 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4984 stats_avg_factor = nla_get_u16(
4985 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4986 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4987 adapter->sessionId,
4988 stats_avg_factor);
4989
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304990 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004991 ret_val = -EPERM;
4992 }
4993
4994
4995 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4996 guard_time = nla_get_u32(
4997 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4998 status = sme_configure_guard_time(hdd_ctx->hHal,
4999 adapter->sessionId,
5000 guard_time);
5001
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305002 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005003 ret_val = -EPERM;
5004 }
5005
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305006 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
5007 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
5008 attr_len = nla_len(
5009 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
5010 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005011 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305012 attr_len);
5013 return -EINVAL;
5014 }
5015
5016 nla_memcpy(&vendor_ie,
5017 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
5018 attr_len);
5019 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005020 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305021 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305022 }
5023
5024 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
5025 access_policy = (int) nla_get_u32(
5026 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
5027 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
5028 (access_policy >
5029 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005030 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305031 access_policy);
5032 return -EINVAL;
5033 }
5034 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005035 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305036 access_policy);
5037 }
5038
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005039 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
5040 retry = nla_get_u8(tb[
5041 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
5042 retry = retry > CFG_NON_AGG_RETRY_MAX ?
5043 CFG_NON_AGG_RETRY_MAX : retry;
5044 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
5045 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
5046 retry, PDEV_CMD);
5047 }
5048
5049 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
5050 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
5051 retry = retry > CFG_AGG_RETRY_MAX ?
5052 CFG_AGG_RETRY_MAX : retry;
5053
5054 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
5055 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
5056 CFG_AGG_RETRY_MIN : retry;
5057 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
5058 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
5059 retry, PDEV_CMD);
5060 }
5061
5062 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
5063 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
5064 retry = retry > CFG_MGMT_RETRY_MAX ?
5065 CFG_MGMT_RETRY_MAX : retry;
5066 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
5067 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
5068 retry, PDEV_CMD);
5069 }
5070
5071 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
5072 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
5073 retry = retry > CFG_CTRL_RETRY_MAX ?
5074 CFG_CTRL_RETRY_MAX : retry;
5075 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
5076 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
5077 retry, PDEV_CMD);
5078 }
5079
5080 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
5081 delay = nla_get_u8(tb[
5082 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
5083 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
5084 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08005085 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005086 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
5087 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08005088 abs_delay, PDEV_CMD);
5089 }
5090
5091 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
5092 abs_delay = nla_get_u8(tb[
5093 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
5094 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
5095 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
5096 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08005097 }
5098
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05305099 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
5100 tx_fail_count = nla_get_u32(
5101 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
5102 if (tx_fail_count) {
5103 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
5104 adapter->sessionId, tx_fail_count);
5105 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005106 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05305107 status);
5108 return -EINVAL;
5109 }
5110 }
5111 }
5112
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305113 if (vendor_ie_present && access_policy_present) {
5114 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
5115 access_policy =
5116 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305117 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305118 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305119 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305120
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005121 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305122 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
5123 adapter->sessionId, &vendor_ie[0],
5124 access_policy);
5125 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005126 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05305127 return -EINVAL;
5128 }
5129 }
5130
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05305131 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
5132 set_value = nla_get_u8(
5133 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005134 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05305135 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
5136 }
5137
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05305138 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
5139 scan_ie_len = nla_len(
5140 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005141 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05305142 scan_ie_len, adapter->sessionId,
5143 adapter->device_mode);
5144 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
5145 scan_ie = (uint8_t *) nla_data(tb
5146 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305147
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05305148 if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
5149 scan_ie, scan_ie_len))
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05305150 hdd_err("Failed to save default scan IEs");
5151
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05305152 if (adapter->device_mode == QDF_STA_MODE) {
5153 status = sme_set_default_scan_ie(hdd_ctx->hHal,
5154 adapter->sessionId, scan_ie,
5155 scan_ie_len);
5156 if (QDF_STATUS_SUCCESS != status)
5157 ret_val = -EPERM;
5158 }
5159 } else
5160 ret_val = -EPERM;
5161 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05305162
5163 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
5164 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
5165 /* if one is specified, both must be specified */
5166 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
5167 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
5168 hdd_err("Both TX and RX MPDU Aggregation required");
5169 return -EINVAL;
5170 }
5171
5172 request.tx_aggregation_size = nla_get_u8(
5173 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
5174 request.rx_aggregation_size = nla_get_u8(
5175 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
5176 request.vdev_id = adapter->sessionId;
5177
5178 if (request.tx_aggregation_size >=
5179 CFG_TX_AGGREGATION_SIZE_MIN &&
5180 request.tx_aggregation_size <=
5181 CFG_TX_AGGREGATION_SIZE_MAX &&
5182 request.rx_aggregation_size >=
5183 CFG_RX_AGGREGATION_SIZE_MIN &&
5184 request.rx_aggregation_size <=
5185 CFG_RX_AGGREGATION_SIZE_MAX) {
5186 qdf_status = wma_set_tx_rx_aggregation_size(&request);
5187 if (qdf_status != QDF_STATUS_SUCCESS) {
5188 hdd_err("failed to set aggr sizes err %d",
5189 qdf_status);
5190 ret_val = -EPERM;
5191 }
5192 } else {
5193 hdd_err("TX %d RX %d MPDU aggr size not in range",
5194 request.tx_aggregation_size,
5195 request.rx_aggregation_size);
5196 ret_val = -EINVAL;
5197 }
5198 }
5199
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305200 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
5201 uint8_t ignore_assoc_disallowed;
5202
5203 ignore_assoc_disallowed
5204 = nla_get_u8(tb[
5205 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005206 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05305207 ignore_assoc_disallowed);
5208 if ((ignore_assoc_disallowed <
5209 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
5210 (ignore_assoc_disallowed >
5211 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
5212 return -EPERM;
5213
5214 sme_update_session_param(hdd_ctx->hHal,
5215 adapter->sessionId,
5216 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
5217 ignore_assoc_disallowed);
5218 }
5219
lifeng907edd62017-05-12 10:10:36 +08005220#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
5221 ((1<<26)|((probe_period&0x1fff)<<13)|(stay_period&0x1fff))
5222
5223#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
5224 ((1<<27)|(snr_diff&0x1fff))
5225
5226#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
5227 ((1<<28)|(probe_dwell_time&0x1fff))
5228
5229#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
5230 ((1<<29)|((mgmt_snr_weight&0xff)<<16)|((data_snr_weight&0xff)<<8)| \
5231 (ack_snr_weight&0xff))
5232
5233 if (tb[ANT_DIV_PROBE_PERIOD] ||
5234 tb[ANT_DIV_STAY_PERIOD]) {
5235
5236 if (!tb[ANT_DIV_PROBE_PERIOD] ||
5237 !tb[ANT_DIV_STAY_PERIOD]) {
5238 hdd_err("Both probe and stay period required");
5239 return -EINVAL;
5240 }
5241
5242 ant_div_usrcfg = ANT_DIV_SET_PERIOD(
5243 nla_get_u32(tb[ANT_DIV_PROBE_PERIOD]),
5244 nla_get_u32(tb[ANT_DIV_STAY_PERIOD]));
5245 hdd_debug("ant div set period: %x", ant_div_usrcfg);
5246 ret_val = wma_cli_set_command((int)adapter->sessionId,
5247 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5248 ant_div_usrcfg, PDEV_CMD);
5249 if (ret_val) {
5250 hdd_err("Failed to set ant div period");
5251 return ret_val;
5252 }
5253 }
5254
5255 if (tb[ANT_DIV_SNR_DIFF]) {
5256 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(
5257 nla_get_u32(tb[ANT_DIV_SNR_DIFF]));
5258 hdd_debug("ant div set snr diff: %x", ant_div_usrcfg);
5259 ret_val = wma_cli_set_command((int)adapter->sessionId,
5260 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5261 ant_div_usrcfg, PDEV_CMD);
5262 if (ret_val) {
5263 hdd_err("Failed to set ant snr diff");
5264 return ret_val;
5265 }
5266 }
5267
5268 if (tb[ANT_DIV_PROBE_DWELL_TIME]) {
5269 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(
5270 nla_get_u32(tb[ANT_DIV_PROBE_DWELL_TIME]));
5271 hdd_debug("ant div set probe dewll time: %x",
5272 ant_div_usrcfg);
5273 ret_val = wma_cli_set_command((int)adapter->sessionId,
5274 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5275 ant_div_usrcfg, PDEV_CMD);
5276 if (ret_val) {
5277 hdd_err("Failed to set ant div probe dewll time");
5278 return ret_val;
5279 }
5280 }
5281
5282 if (tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5283 tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5284 tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5285
5286 if (!tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
5287 !tb[ANT_DIV_DATA_SNR_WEIGHT] ||
5288 !tb[ANT_DIV_ACK_SNR_WEIGHT]) {
5289 hdd_err("Mgmt snr, data snr and ack snr weight are required");
5290 return -EINVAL;
5291 }
5292
5293 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(
5294 nla_get_u32(tb[ANT_DIV_MGMT_SNR_WEIGHT]),
5295 nla_get_u32(tb[ANT_DIV_DATA_SNR_WEIGHT]),
5296 nla_get_u32(tb[ANT_DIV_ACK_SNR_WEIGHT]));
5297 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
5298 ret_val = wma_cli_set_command((int)adapter->sessionId,
5299 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
5300 ant_div_usrcfg, PDEV_CMD);
5301 if (ret_val) {
5302 hdd_err("Failed to set ant div weight");
5303 return ret_val;
5304 }
5305 }
5306
Ajit Pal Singh747b6802017-05-24 15:42:03 +05305307 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL]) {
5308 u8 restrict_offchan = nla_get_u8(
5309 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL]);
5310
5311 hdd_debug("Restrict offchannel:%d", restrict_offchan);
5312 if (restrict_offchan <= 1)
5313 ret_val =
5314 wlan_hdd_handle_restrict_offchan_config(adapter,
5315 restrict_offchan);
5316 else {
5317 ret_val = -EINVAL;
5318 hdd_err("Invalid RESTRICT_OFFCHAN setting");
5319 }
5320 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005321 return ret_val;
5322}
5323
5324/**
5325 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
5326 * vendor command
5327 *
5328 * @wiphy: wiphy device pointer
5329 * @wdev: wireless device pointer
5330 * @data: Vendor command data buffer
5331 * @data_len: Buffer length
5332 *
5333 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
5334 *
5335 * Return: EOK or other error codes.
5336 */
5337static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
5338 struct wireless_dev *wdev,
5339 const void *data,
5340 int data_len)
5341{
5342 int ret;
5343
5344 cds_ssr_protect(__func__);
5345 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
5346 data, data_len);
5347 cds_ssr_unprotect(__func__);
5348
5349 return ret;
5350}
5351
5352static const struct
5353nla_policy
5354qca_wlan_vendor_wifi_logger_start_policy
5355[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
5356 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
5357 = {.type = NLA_U32 },
5358 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
5359 = {.type = NLA_U32 },
5360 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
5361 = {.type = NLA_U32 },
5362};
5363
5364/**
5365 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
5366 * or disable the collection of packet statistics from the firmware
5367 * @wiphy: WIPHY structure pointer
5368 * @wdev: Wireless device structure pointer
5369 * @data: Pointer to the data received
5370 * @data_len: Length of the data received
5371 *
5372 * This function enables or disables the collection of packet statistics from
5373 * the firmware
5374 *
5375 * Return: 0 on success and errno on failure
5376 */
5377static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5378 struct wireless_dev *wdev,
5379 const void *data,
5380 int data_len)
5381{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305382 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005383 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5384 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
5385 struct sir_wifi_start_log start_log;
5386
Jeff Johnson1f61b612016-02-12 16:28:33 -08005387 ENTER_DEV(wdev->netdev);
5388
Anurag Chouhan6d760662016-02-20 16:05:43 +05305389 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005390 hdd_err("Command not allowed in FTM mode");
5391 return -EPERM;
5392 }
5393
5394 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305395 if (status)
5396 return status;
5397
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05305398 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
5399 hdd_err("Driver Modules are closed, can not start logger");
5400 return -EINVAL;
5401 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005402
5403 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
5404 data, data_len,
5405 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005406 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005407 return -EINVAL;
5408 }
5409
5410 /* Parse and fetch ring id */
5411 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005412 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413 return -EINVAL;
5414 }
5415 start_log.ring_id = nla_get_u32(
5416 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005417 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005418
5419 /* Parse and fetch verbose level */
5420 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005421 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005422 return -EINVAL;
5423 }
5424 start_log.verbose_level = nla_get_u32(
5425 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005426 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005427
5428 /* Parse and fetch flag */
5429 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005430 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431 return -EINVAL;
5432 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05305433 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005434 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005435 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005436
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305437 /* size is buff size which can be set using iwpriv command*/
5438 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05305439 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05305440
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005441 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
5442
5443 if (start_log.ring_id == RING_ID_WAKELOCK) {
5444 /* Start/stop wakelock events */
5445 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
5446 cds_set_wakelock_logging(true);
5447 else
5448 cds_set_wakelock_logging(false);
5449 return 0;
5450 }
5451
5452 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305453 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005454 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005455 status);
5456 return -EINVAL;
5457 }
5458 return 0;
5459}
5460
5461/**
5462 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
5463 * or disable the collection of packet statistics from the firmware
5464 * @wiphy: WIPHY structure pointer
5465 * @wdev: Wireless device structure pointer
5466 * @data: Pointer to the data received
5467 * @data_len: Length of the data received
5468 *
5469 * This function is used to enable or disable the collection of packet
5470 * statistics from the firmware
5471 *
5472 * Return: 0 on success and errno on failure
5473 */
5474static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
5475 struct wireless_dev *wdev,
5476 const void *data,
5477 int data_len)
5478{
5479 int ret = 0;
5480
5481 cds_ssr_protect(__func__);
5482 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
5483 wdev, data, data_len);
5484 cds_ssr_unprotect(__func__);
5485
5486 return ret;
5487}
5488
5489static const struct
5490nla_policy
5491qca_wlan_vendor_wifi_logger_get_ring_data_policy
5492[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
5493 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
5494 = {.type = NLA_U32 },
5495};
5496
5497/**
5498 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5499 * @wiphy: WIPHY structure pointer
5500 * @wdev: Wireless device structure pointer
5501 * @data: Pointer to the data received
5502 * @data_len: Length of the data received
5503 *
5504 * This function is used to flush or retrieve the per packet statistics from
5505 * the driver
5506 *
5507 * Return: 0 on success and errno on failure
5508 */
5509static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5510 struct wireless_dev *wdev,
5511 const void *data,
5512 int data_len)
5513{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305514 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005515 uint32_t ring_id;
5516 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5517 struct nlattr *tb
5518 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5519
Jeff Johnson1f61b612016-02-12 16:28:33 -08005520 ENTER_DEV(wdev->netdev);
5521
Anurag Chouhan6d760662016-02-20 16:05:43 +05305522 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005523 hdd_err("Command not allowed in FTM mode");
5524 return -EPERM;
5525 }
5526
5527 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305528 if (status)
5529 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005530
5531 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5532 data, data_len,
5533 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005534 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005535 return -EINVAL;
5536 }
5537
5538 /* Parse and fetch ring id */
5539 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005540 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005541 return -EINVAL;
5542 }
5543
5544 ring_id = nla_get_u32(
5545 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5546
5547 if (ring_id == RING_ID_PER_PACKET_STATS) {
5548 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005549 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305550 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5551 /*
5552 * As part of DRIVER ring ID, flush both driver and fw logs.
5553 * For other Ring ID's driver doesn't have any rings to flush
5554 */
5555 hdd_notice("Bug report triggered by framework");
5556
5557 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5558 WLAN_LOG_INDICATOR_FRAMEWORK,
5559 WLAN_LOG_REASON_CODE_UNUSED,
5560 true, false);
5561 if (QDF_STATUS_SUCCESS != status) {
5562 hdd_err("Failed to trigger bug report");
5563 return -EINVAL;
5564 }
5565 } else {
5566 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5567 WLAN_LOG_INDICATOR_FRAMEWORK,
5568 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005569 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005570 return 0;
5571}
5572
5573/**
5574 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5575 * @wiphy: WIPHY structure pointer
5576 * @wdev: Wireless device structure pointer
5577 * @data: Pointer to the data received
5578 * @data_len: Length of the data received
5579 *
5580 * This function is used to flush or retrieve the per packet statistics from
5581 * the driver
5582 *
5583 * Return: 0 on success and errno on failure
5584 */
5585static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5586 struct wireless_dev *wdev,
5587 const void *data,
5588 int data_len)
5589{
5590 int ret = 0;
5591
5592 cds_ssr_protect(__func__);
5593 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5594 wdev, data, data_len);
5595 cds_ssr_unprotect(__func__);
5596
5597 return ret;
5598}
5599
5600#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5601/**
5602 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5603 * @hdd_ctx: HDD context
5604 * @request_id: [input] request id
5605 * @pattern_id: [output] pattern id
5606 *
5607 * This function loops through request id to pattern id array
5608 * if the slot is available, store the request id and return pattern id
5609 * if entry exists, return the pattern id
5610 *
5611 * Return: 0 on success and errno on failure
5612 */
5613static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5614 uint32_t request_id,
5615 uint8_t *pattern_id)
5616{
5617 uint32_t i;
5618
5619 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5620 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5621 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5622 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5623 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5624 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5625 return 0;
5626 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5627 request_id) {
5628 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5629 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5630 return 0;
5631 }
5632 }
5633 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5634 return -EINVAL;
5635}
5636
5637/**
5638 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5639 * @hdd_ctx: HDD context
5640 * @request_id: [input] request id
5641 * @pattern_id: [output] pattern id
5642 *
5643 * This function loops through request id to pattern id array
5644 * reset request id to 0 (slot available again) and
5645 * return pattern id
5646 *
5647 * Return: 0 on success and errno on failure
5648 */
5649static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5650 uint32_t request_id,
5651 uint8_t *pattern_id)
5652{
5653 uint32_t i;
5654
5655 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5656 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5657 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5658 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5659 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5660 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5661 return 0;
5662 }
5663 }
5664 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5665 return -EINVAL;
5666}
5667
5668
5669/*
5670 * define short names for the global vendor params
5671 * used by __wlan_hdd_cfg80211_offloaded_packets()
5672 */
5673#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5674#define PARAM_REQUEST_ID \
5675 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5676#define PARAM_CONTROL \
5677 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5678#define PARAM_IP_PACKET \
5679 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5680#define PARAM_SRC_MAC_ADDR \
5681 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5682#define PARAM_DST_MAC_ADDR \
5683 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5684#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5685
5686/**
5687 * wlan_hdd_add_tx_ptrn() - add tx pattern
5688 * @adapter: adapter pointer
5689 * @hdd_ctx: hdd context
5690 * @tb: nl attributes
5691 *
5692 * This function reads the NL attributes and forms a AddTxPtrn message
5693 * posts it to SME.
5694 *
5695 */
5696static int
5697wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5698 struct nlattr **tb)
5699{
5700 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305701 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005702 uint32_t request_id, ret, len;
5703 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305704 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005705 uint16_t eth_type = htons(ETH_P_IP);
5706
5707 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005708 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005709 return -ENOTSUPP;
5710 }
5711
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305712 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005713 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005714 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005715 return -ENOMEM;
5716 }
5717
5718 /* Parse and fetch request Id */
5719 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005720 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005721 goto fail;
5722 }
5723
5724 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5725 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005726 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005727 return -EINVAL;
5728 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005729 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005730
5731 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005732 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005733 goto fail;
5734 }
5735 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005736 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005737 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005738 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005739 goto fail;
5740 }
5741
5742 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005743 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005744 goto fail;
5745 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005746 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305747 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005748 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005749 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005750
Anurag Chouhanc5548422016-02-24 18:33:27 +05305751 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005752 &adapter->macAddressCurrent)) {
5753 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005754 goto fail;
5755 }
5756
5757 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005758 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005759 goto fail;
5760 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305761 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005762 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005763 MAC_ADDR_ARRAY(dst_addr.bytes));
5764
5765 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005766 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005767 goto fail;
5768 }
5769 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005770 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005771
5772 if (add_req->ucPtrnSize < 0 ||
5773 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5774 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005775 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005776 add_req->ucPtrnSize);
5777 goto fail;
5778 }
5779
5780 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305781 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305782 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305783 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305784 QDF_MAC_ADDR_SIZE);
5785 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305786 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005787 len += 2;
5788
5789 /*
5790 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5791 * ------------------------------------------------------------
5792 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5793 * ------------------------------------------------------------
5794 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305795 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005796 nla_data(tb[PARAM_IP_PACKET]),
5797 add_req->ucPtrnSize);
5798 add_req->ucPtrnSize += len;
5799
5800 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5801 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005802 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005803 goto fail;
5804 }
5805 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005806 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005807
5808 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305809 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005810 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005811 goto fail;
5812 }
5813
5814 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305815 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005816 return 0;
5817
5818fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305819 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005820 return -EINVAL;
5821}
5822
5823/**
5824 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5825 * @adapter: adapter pointer
5826 * @hdd_ctx: hdd context
5827 * @tb: nl attributes
5828 *
5829 * This function reads the NL attributes and forms a DelTxPtrn message
5830 * posts it to SME.
5831 *
5832 */
5833static int
5834wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5835 struct nlattr **tb)
5836{
5837 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305838 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005839 uint32_t request_id, ret;
5840 uint8_t pattern_id = 0;
5841
5842 /* Parse and fetch request Id */
5843 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005844 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005845 return -EINVAL;
5846 }
5847 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5848 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005849 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005850 return -EINVAL;
5851 }
5852
5853 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5854 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005855 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005856 return -EINVAL;
5857 }
5858
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305859 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005860 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005861 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005862 return -ENOMEM;
5863 }
5864
Anurag Chouhanc5548422016-02-24 18:33:27 +05305865 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005866 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005867 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005868 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005869 request_id, del_req->ucPtrnId);
5870
5871 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305872 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005873 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005874 goto fail;
5875 }
5876
5877 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305878 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005879 return 0;
5880
5881fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305882 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005883 return -EINVAL;
5884}
5885
5886
5887/**
5888 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5889 * @wiphy: Pointer to wireless phy
5890 * @wdev: Pointer to wireless device
5891 * @data: Pointer to data
5892 * @data_len: Data length
5893 *
5894 * Return: 0 on success, negative errno on failure
5895 */
5896static int
5897__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5898 struct wireless_dev *wdev,
5899 const void *data,
5900 int data_len)
5901{
5902 struct net_device *dev = wdev->netdev;
5903 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5904 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5905 struct nlattr *tb[PARAM_MAX + 1];
5906 uint8_t control;
5907 int ret;
5908 static const struct nla_policy policy[PARAM_MAX + 1] = {
5909 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5910 [PARAM_CONTROL] = { .type = NLA_U32 },
5911 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305912 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005913 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305914 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005915 [PARAM_PERIOD] = { .type = NLA_U32 },
5916 };
5917
Jeff Johnson1f61b612016-02-12 16:28:33 -08005918 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919
Anurag Chouhan6d760662016-02-20 16:05:43 +05305920 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005921 hdd_err("Command not allowed in FTM mode");
5922 return -EPERM;
5923 }
5924
5925 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305926 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005927 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005928
5929 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005930 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005931 return -ENOTSUPP;
5932 }
5933
5934 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005935 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005936 return -EINVAL;
5937 }
5938
5939 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005940 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005941 return -EINVAL;
5942 }
5943 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005944 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005945
5946 if (control == WLAN_START_OFFLOADED_PACKETS)
5947 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005948 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005949 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005950
5951 hdd_err("Invalid control: %d", control);
5952
5953 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005954}
5955
5956/*
5957 * done with short names for the global vendor params
5958 * used by __wlan_hdd_cfg80211_offloaded_packets()
5959 */
5960#undef PARAM_MAX
5961#undef PARAM_REQUEST_ID
5962#undef PARAM_CONTROL
5963#undef PARAM_IP_PACKET
5964#undef PARAM_SRC_MAC_ADDR
5965#undef PARAM_DST_MAC_ADDR
5966#undef PARAM_PERIOD
5967
5968/**
5969 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5970 * @wiphy: wiphy structure pointer
5971 * @wdev: Wireless device structure pointer
5972 * @data: Pointer to the data received
5973 * @data_len: Length of @data
5974 *
5975 * Return: 0 on success; errno on failure
5976 */
5977static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5978 struct wireless_dev *wdev,
5979 const void *data,
5980 int data_len)
5981{
5982 int ret = 0;
5983
5984 cds_ssr_protect(__func__);
5985 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5986 wdev, data, data_len);
5987 cds_ssr_unprotect(__func__);
5988
5989 return ret;
5990}
5991#endif
5992
5993/*
5994 * define short names for the global vendor params
5995 * used by __wlan_hdd_cfg80211_monitor_rssi()
5996 */
5997#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5998#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5999#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
6000#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
6001#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
6002
6003/**
6004 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
6005 * @wiphy: Pointer to wireless phy
6006 * @wdev: Pointer to wireless device
6007 * @data: Pointer to data
6008 * @data_len: Data length
6009 *
6010 * Return: 0 on success, negative errno on failure
6011 */
6012static int
6013__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
6014 struct wireless_dev *wdev,
6015 const void *data,
6016 int data_len)
6017{
6018 struct net_device *dev = wdev->netdev;
6019 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6020 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6021 struct nlattr *tb[PARAM_MAX + 1];
6022 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306023 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006024 int ret;
6025 uint32_t control;
6026 static const struct nla_policy policy[PARAM_MAX + 1] = {
6027 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
6028 [PARAM_CONTROL] = { .type = NLA_U32 },
6029 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
6030 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
6031 };
6032
Jeff Johnson1f61b612016-02-12 16:28:33 -08006033 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006034
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05306035 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
6036 hdd_err("invalid session id: %d", adapter->sessionId);
6037 return -EINVAL;
6038 }
6039
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006040 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05306041 if (ret)
6042 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006043
6044 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07006045 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006046 return -ENOTSUPP;
6047 }
6048
6049 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006050 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006051 return -EINVAL;
6052 }
6053
6054 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006055 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006056 return -EINVAL;
6057 }
6058
6059 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006060 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006061 return -EINVAL;
6062 }
6063
6064 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
6065 req.session_id = adapter->sessionId;
6066 control = nla_get_u32(tb[PARAM_CONTROL]);
6067
6068 if (control == QCA_WLAN_RSSI_MONITORING_START) {
6069 req.control = true;
6070 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006071 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006072 return -EINVAL;
6073 }
6074
6075 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006076 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006077 return -EINVAL;
6078 }
6079
6080 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
6081 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
6082
6083 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006084 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006085 req.min_rssi, req.max_rssi);
6086 return -EINVAL;
6087 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006088 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006089 req.min_rssi, req.max_rssi);
6090
6091 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
6092 req.control = false;
6093 else {
Jeff Johnson77848112016-06-29 14:52:06 -07006094 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006095 return -EINVAL;
6096 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006097 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006098 req.request_id, req.session_id, req.control);
6099
6100 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306101 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006102 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006103 return -EINVAL;
6104 }
6105
6106 return 0;
6107}
6108
6109/*
6110 * done with short names for the global vendor params
6111 * used by __wlan_hdd_cfg80211_monitor_rssi()
6112 */
6113#undef PARAM_MAX
6114#undef PARAM_CONTROL
6115#undef PARAM_REQUEST_ID
6116#undef PARAM_MAX_RSSI
6117#undef PARAM_MIN_RSSI
6118
6119/**
6120 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
6121 * @wiphy: wiphy structure pointer
6122 * @wdev: Wireless device structure pointer
6123 * @data: Pointer to the data received
6124 * @data_len: Length of @data
6125 *
6126 * Return: 0 on success; errno on failure
6127 */
6128static int
6129wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
6130 const void *data, int data_len)
6131{
6132 int ret;
6133
6134 cds_ssr_protect(__func__);
6135 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
6136 cds_ssr_unprotect(__func__);
6137
6138 return ret;
6139}
6140
6141/**
6142 * hdd_rssi_threshold_breached() - rssi breached NL event
6143 * @hddctx: HDD context
6144 * @data: rssi breached event data
6145 *
6146 * This function reads the rssi breached event %data and fill in the skb with
6147 * NL attributes and send up the NL event.
6148 *
6149 * Return: none
6150 */
6151void hdd_rssi_threshold_breached(void *hddctx,
6152 struct rssi_breach_event *data)
6153{
6154 hdd_context_t *hdd_ctx = hddctx;
6155 struct sk_buff *skb;
6156
6157 ENTER();
6158
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05306159 if (wlan_hdd_validate_context(hdd_ctx))
6160 return;
6161 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006162 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006163 return;
6164 }
6165
6166 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
6167 NULL,
6168 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
6169 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
6170 GFP_KERNEL);
6171
6172 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006173 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006174 return;
6175 }
6176
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006177 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006178 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006179 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006180 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
6181
6182 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
6183 data->request_id) ||
6184 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
6185 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
6186 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
6187 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006188 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006189 goto fail;
6190 }
6191
6192 cfg80211_vendor_event(skb, GFP_KERNEL);
6193 return;
6194
6195fail:
6196 kfree_skb(skb);
6197 return;
6198}
6199
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306200static const struct nla_policy
6201ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
6202 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
6203};
6204
6205/**
6206 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
6207 * @wiphy: Pointer to wireless phy
6208 * @wdev: Pointer to wireless device
6209 * @data: Pointer to data
6210 * @data_len: Length of @data
6211 *
6212 * Return: 0 on success, negative errno on failure
6213 */
6214static int
6215__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
6216 struct wireless_dev *wdev,
6217 const void *data, int data_len)
6218{
6219 int status;
6220 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
6221 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07006222 struct net_device *dev = wdev->netdev;
6223 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306224
6225 ENTER_DEV(wdev->netdev);
6226
6227 status = wlan_hdd_validate_context(pHddCtx);
6228 if (0 != status)
6229 return status;
6230 if (!pHddCtx->config->fhostNSOffload) {
6231 hdd_err("ND Offload not supported");
6232 return -EINVAL;
6233 }
6234
6235 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
6236 (struct nlattr *)data,
6237 data_len, ns_offload_set_policy)) {
6238 hdd_err("nla_parse failed");
6239 return -EINVAL;
6240 }
6241
6242 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
6243 hdd_err("ND Offload flag attribute not present");
6244 return -EINVAL;
6245 }
6246
6247 pHddCtx->ns_offload_enable =
6248 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
6249
Dustin Brownd8279d22016-09-07 14:52:57 -07006250 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05306251 if (pHddCtx->ns_offload_enable)
6252 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
6253 else
6254 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07006255
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05306256 return 0;
6257}
6258
6259/**
6260 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
6261 * @wiphy: pointer to wireless wiphy structure.
6262 * @wdev: pointer to wireless_dev structure.
6263 * @data: Pointer to the data to be passed via vendor interface
6264 * @data_len:Length of the data to be passed
6265 *
6266 * Return: Return the Success or Failure code.
6267 */
6268static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
6269 struct wireless_dev *wdev,
6270 const void *data, int data_len)
6271{
6272 int ret;
6273
6274 cds_ssr_protect(__func__);
6275 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
6276 cds_ssr_unprotect(__func__);
6277
6278 return ret;
6279}
6280
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006281/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
6282 * @wiphy: Pointer to wireless phy
6283 * @wdev: Pointer to wireless device
6284 * @data: Pointer to data
6285 * @data_len: Data length
6286 *
6287 * This function return the preferred frequency list generated by the policy
6288 * manager.
6289 *
6290 * Return: success or failure code
6291 */
6292static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6293 struct wireless_dev
6294 *wdev, const void *data,
6295 int data_len)
6296{
6297 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6298 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306299 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306300 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006301 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306302 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006303 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006304 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
6305 struct sk_buff *reply_skb;
6306
Jeff Johnson1f61b612016-02-12 16:28:33 -08006307 ENTER_DEV(wdev->netdev);
6308
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006309 ret = wlan_hdd_validate_context(hdd_ctx);
6310 if (ret)
6311 return -EINVAL;
6312
6313 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
6314 data, data_len, NULL)) {
6315 hdd_err("Invalid ATTR");
6316 return -EINVAL;
6317 }
6318
6319 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
6320 hdd_err("attr interface type failed");
6321 return -EINVAL;
6322 }
6323
6324 intf_mode = nla_get_u32(tb
6325 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
6326
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006327 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006328 hdd_err("Invalid interface type");
6329 return -EINVAL;
6330 }
6331
6332 hdd_debug("Userspace requested pref freq list");
6333
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006334 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
6335 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05306336 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306337 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006338 hdd_err("Get pcl failed");
6339 return -EINVAL;
6340 }
6341
6342 /* convert channel number to frequency */
6343 for (i = 0; i < pcl_len; i++) {
6344 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
6345 freq_list[i] =
6346 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006347 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006348 else
6349 freq_list[i] =
6350 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07006351 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006352 }
6353
6354 /* send the freq_list back to supplicant */
6355 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
6356 sizeof(u32) *
6357 pcl_len +
6358 NLMSG_HDRLEN);
6359
6360 if (!reply_skb) {
6361 hdd_err("Allocate reply_skb failed");
6362 return -EINVAL;
6363 }
6364
6365 if (nla_put_u32(reply_skb,
6366 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
6367 intf_mode) ||
6368 nla_put(reply_skb,
6369 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
6370 sizeof(uint32_t) * pcl_len,
6371 freq_list)) {
6372 hdd_err("nla put fail");
6373 kfree_skb(reply_skb);
6374 return -EINVAL;
6375 }
6376
6377 return cfg80211_vendor_cmd_reply(reply_skb);
6378}
6379
6380/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
6381 * @wiphy: Pointer to wireless phy
6382 * @wdev: Pointer to wireless device
6383 * @data: Pointer to data
6384 * @data_len: Data length
6385 *
6386 * This function return the preferred frequency list generated by the policy
6387 * manager.
6388 *
6389 * Return: success or failure code
6390 */
6391static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
6392 struct wireless_dev
6393 *wdev, const void *data,
6394 int data_len)
6395{
6396 int ret = 0;
6397
6398 cds_ssr_protect(__func__);
6399 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
6400 data, data_len);
6401 cds_ssr_unprotect(__func__);
6402
6403 return ret;
6404}
6405
Jeff Johnsone5f33ba2017-06-05 14:48:48 -07006406static const struct nla_policy set_probable_oper_channel_policy
6407 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1] = {
6408 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE] = {
6409 .type = NLA_U32},
6410 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ] = {
6411 .type = NLA_U32},
6412};
6413
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006414/**
6415 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6416 * @wiphy: Pointer to wireless phy
6417 * @wdev: Pointer to wireless device
6418 * @data: Pointer to data
6419 * @data_len: Data length
6420 *
6421 * Return: 0 on success, negative errno on failure
6422 */
6423static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6424 struct wireless_dev *wdev,
6425 const void *data,
6426 int data_len)
6427{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05306428 struct net_device *ndev = wdev->netdev;
6429 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006430 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6431 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006432 enum policy_mgr_con_mode intf_mode;
Jeff Johnsone5f33ba2017-06-05 14:48:48 -07006433 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006434 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006435
Jeff Johnson1f61b612016-02-12 16:28:33 -08006436 ENTER_DEV(ndev);
6437
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006438 ret = wlan_hdd_validate_context(hdd_ctx);
6439 if (ret)
6440 return ret;
6441
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006442 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
Jeff Johnsone5f33ba2017-06-05 14:48:48 -07006443 data, data_len, set_probable_oper_channel_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006444 hdd_err("Invalid ATTR");
6445 return -EINVAL;
6446 }
6447
6448 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
6449 hdd_err("attr interface type failed");
6450 return -EINVAL;
6451 }
6452
6453 intf_mode = nla_get_u32(tb
6454 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
6455
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006456 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006457 hdd_err("Invalid interface type");
6458 return -EINVAL;
6459 }
6460
6461 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
6462 hdd_err("attr probable freq failed");
6463 return -EINVAL;
6464 }
6465
6466 channel_hint = cds_freq_to_chan(nla_get_u32(tb
6467 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
6468
6469 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006470 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006471 channel_hint, HW_MODE_20_MHZ)) {
6472 hdd_err("Set channel hint failed due to concurrency check");
6473 return -EINVAL;
6474 }
6475
Krunal Soni09e55032016-06-07 10:06:55 -07006476 if (0 != wlan_hdd_check_remain_on_channel(adapter))
6477 hdd_warn("Remain On Channel Pending");
6478
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006479 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006480 if (!QDF_IS_STATUS_SUCCESS(ret))
6481 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006482
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006483 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
6484 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07006485 SIR_UPDATE_REASON_SET_OPER_CHAN);
6486 if (QDF_STATUS_E_FAILURE == ret) {
6487 /* return in the failure case */
6488 hdd_err("ERROR: connections update failed!!");
6489 return -EINVAL;
6490 }
6491
6492 if (QDF_STATUS_SUCCESS == ret) {
6493 /*
6494 * Success is the only case for which we expect hw mode
6495 * change to take place, hence we need to wait.
6496 * For any other return value it should be a pass
6497 * through
6498 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006499 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006500 if (!QDF_IS_STATUS_SUCCESS(ret)) {
6501 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006502 return -EINVAL;
6503 }
6504
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006505 }
6506
6507 return 0;
6508}
6509
6510/**
6511 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6512 * @wiphy: Pointer to wireless phy
6513 * @wdev: Pointer to wireless device
6514 * @data: Pointer to data
6515 * @data_len: Data length
6516 *
6517 * Return: 0 on success, negative errno on failure
6518 */
6519static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6520 struct wireless_dev *wdev,
6521 const void *data,
6522 int data_len)
6523{
6524 int ret = 0;
6525
6526 cds_ssr_protect(__func__);
6527 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6528 data, data_len);
6529 cds_ssr_unprotect(__func__);
6530
6531 return ret;
6532}
6533
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306534static const struct
6535nla_policy
6536qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6537 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6538};
6539
6540/**
6541 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6542 * @wiphy: WIPHY structure pointer
6543 * @wdev: Wireless device structure pointer
6544 * @data: Pointer to the data received
6545 * @data_len: Length of the data received
6546 *
6547 * This function is used to get link properties like nss, rate flags and
6548 * operating frequency for the active connection with the given peer.
6549 *
6550 * Return: 0 on success and errno on failure
6551 */
6552static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6553 struct wireless_dev *wdev,
6554 const void *data,
6555 int data_len)
6556{
6557 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6558 struct net_device *dev = wdev->netdev;
6559 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6560 hdd_station_ctx_t *hdd_sta_ctx;
6561 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306562 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306563 uint32_t sta_id;
6564 struct sk_buff *reply_skb;
6565 uint32_t rate_flags = 0;
6566 uint8_t nss;
6567 uint8_t final_rate_flags = 0;
6568 uint32_t freq;
6569
Jeff Johnson1f61b612016-02-12 16:28:33 -08006570 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306571
Anurag Chouhan6d760662016-02-20 16:05:43 +05306572 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306573 hdd_err("Command not allowed in FTM mode");
6574 return -EPERM;
6575 }
6576
6577 if (0 != wlan_hdd_validate_context(hdd_ctx))
6578 return -EINVAL;
6579
6580 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6581 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006582 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306583 return -EINVAL;
6584 }
6585
6586 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006587 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306588 adapter->device_mode);
6589 return -EINVAL;
6590 }
6591
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306592 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306593 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006594 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306595 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6596
Krunal Sonib4326f22016-03-10 13:05:51 -08006597 if (adapter->device_mode == QDF_STA_MODE ||
6598 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306599 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6600 if ((hdd_sta_ctx->conn_info.connState !=
6601 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306602 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306603 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006604 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306605 MAC_ADDR_ARRAY(peer_mac));
6606 return -EINVAL;
6607 }
6608
6609 nss = hdd_sta_ctx->conn_info.nss;
6610 freq = cds_chan_to_freq(
6611 hdd_sta_ctx->conn_info.operationChannel);
6612 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006613 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6614 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306615
6616 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6617 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306618 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306619 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306620 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306621 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306622 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306623 break;
6624 }
6625
6626 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006627 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306628 MAC_ADDR_ARRAY(peer_mac));
6629 return -EINVAL;
6630 }
6631
6632 nss = adapter->aStaInfo[sta_id].nss;
6633 freq = cds_chan_to_freq(
6634 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6635 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6636 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006637 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306638 MAC_ADDR_ARRAY(peer_mac));
6639 return -EINVAL;
6640 }
6641
6642 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6643 if (rate_flags & eHAL_TX_RATE_VHT80) {
6644 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006645#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306646 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006647#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306648 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6649 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006650#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306651 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006652#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306653 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6654 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6655 } else if (rate_flags &
6656 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6657 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006658#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306659 if (rate_flags & eHAL_TX_RATE_HT40)
6660 final_rate_flags |=
6661 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006662#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306663 }
6664
6665 if (rate_flags & eHAL_TX_RATE_SGI) {
6666 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6667 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6668 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6669 }
6670 }
6671
6672 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6673 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6674
6675 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006676 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306677 return -EINVAL;
6678 }
6679
6680 if (nla_put_u8(reply_skb,
6681 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6682 nss) ||
6683 nla_put_u8(reply_skb,
6684 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6685 final_rate_flags) ||
6686 nla_put_u32(reply_skb,
6687 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6688 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006689 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306690 kfree_skb(reply_skb);
6691 return -EINVAL;
6692 }
6693
6694 return cfg80211_vendor_cmd_reply(reply_skb);
6695}
6696
6697/**
6698 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6699 * properties.
6700 * @wiphy: WIPHY structure pointer
6701 * @wdev: Wireless device structure pointer
6702 * @data: Pointer to the data received
6703 * @data_len: Length of the data received
6704 *
6705 * This function is used to get link properties like nss, rate flags and
6706 * operating frequency for the active connection with the given peer.
6707 *
6708 * Return: 0 on success and errno on failure
6709 */
6710static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6711 struct wireless_dev *wdev,
6712 const void *data,
6713 int data_len)
6714{
6715 int ret = 0;
6716
6717 cds_ssr_protect(__func__);
6718 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6719 wdev, data, data_len);
6720 cds_ssr_unprotect(__func__);
6721
6722 return ret;
6723}
6724
Peng Xu278d0122015-09-24 16:34:17 -07006725static const struct
6726nla_policy
6727qca_wlan_vendor_ota_test_policy
6728[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6729 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6730};
6731
6732/**
6733 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6734 * @wiphy: Pointer to wireless phy
6735 * @wdev: Pointer to wireless device
6736 * @data: Pointer to data
6737 * @data_len: Data length
6738 *
6739 * Return: 0 on success, negative errno on failure
6740 */
6741static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6742 struct wireless_dev *wdev,
6743 const void *data,
6744 int data_len)
6745{
6746 struct net_device *dev = wdev->netdev;
6747 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6748 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6749 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6750 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6751 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306752 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006753 uint32_t current_roam_state;
6754
Jeff Johnson1f61b612016-02-12 16:28:33 -08006755 ENTER_DEV(dev);
6756
Anurag Chouhan6d760662016-02-20 16:05:43 +05306757 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006758 hdd_err("Command not allowed in FTM mode");
6759 return -EPERM;
6760 }
6761
6762 if (0 != wlan_hdd_validate_context(hdd_ctx))
6763 return -EINVAL;
6764
6765 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6766 data, data_len,
6767 qca_wlan_vendor_ota_test_policy)) {
6768 hdd_err("invalid attr");
6769 return -EINVAL;
6770 }
6771
6772 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6773 hdd_err("attr ota test failed");
6774 return -EINVAL;
6775 }
6776
6777 ota_enable = nla_get_u8(
6778 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6779
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006780 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006781 if (ota_enable != 1) {
6782 hdd_err("Invalid value, only enable test mode is supported!");
6783 return -EINVAL;
6784 }
6785
6786 current_roam_state =
6787 sme_get_current_roam_state(hal, adapter->sessionId);
6788 status = sme_stop_roaming(hal, adapter->sessionId,
6789 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306790 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006791 hdd_err("Enable/Disable roaming failed");
6792 return -EINVAL;
6793 }
6794
6795 status = sme_ps_enable_disable(hal, adapter->sessionId,
6796 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306797 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006798 hdd_err("Enable/Disable power save failed");
6799 /* restore previous roaming setting */
6800 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6801 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6802 status = sme_start_roaming(hal, adapter->sessionId,
6803 eCsrHddIssued);
6804 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6805 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6806 status = sme_stop_roaming(hal, adapter->sessionId,
6807 eCsrHddIssued);
6808
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306809 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006810 hdd_err("Restoring roaming state failed");
6811
6812 return -EINVAL;
6813 }
6814
6815
6816 return 0;
6817}
6818
6819/**
6820 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6821 * @wiphy: Pointer to wireless phy
6822 * @wdev: Pointer to wireless device
6823 * @data: Pointer to data
6824 * @data_len: Data length
6825 *
6826 * Return: 0 on success, negative errno on failure
6827 */
6828static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6829 struct wireless_dev *wdev,
6830 const void *data,
6831 int data_len)
6832{
6833 int ret = 0;
6834
6835 cds_ssr_protect(__func__);
6836 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6837 cds_ssr_unprotect(__func__);
6838
6839 return ret;
6840}
6841
Dustin Brown8f3b0562017-06-06 11:38:45 -07006842static const struct nla_policy
6843txpower_scale_policy[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1] = {
6844 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE] = { .type = NLA_U8 },
6845};
6846
Peng Xu4d67c8f2015-10-16 16:02:26 -07006847/**
6848 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6849 * @wiphy: Pointer to wireless phy
6850 * @wdev: Pointer to wireless device
6851 * @data: Pointer to data
6852 * @data_len: Data length
6853 *
6854 * Return: 0 on success, negative errno on failure
6855 */
6856static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6857 struct wireless_dev *wdev,
6858 const void *data,
6859 int data_len)
6860{
6861 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6862 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006863 hdd_adapter_t *adapter;
6864 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006865 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6866 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006867 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006868
Jeff Johnson1f61b612016-02-12 16:28:33 -08006869 ENTER_DEV(dev);
6870
Peng Xu4d67c8f2015-10-16 16:02:26 -07006871 ret = wlan_hdd_validate_context(hdd_ctx);
6872 if (ret)
6873 return ret;
6874
6875 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6876
6877 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
Dustin Brown8f3b0562017-06-06 11:38:45 -07006878 data, data_len, txpower_scale_policy)) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006879 hdd_err("Invalid ATTR");
6880 return -EINVAL;
6881 }
6882
6883 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6884 hdd_err("attr tx power scale failed");
6885 return -EINVAL;
6886 }
6887
6888 scale_value = nla_get_u8(tb
6889 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6890
6891 if (scale_value > MAX_TXPOWER_SCALE) {
6892 hdd_err("Invalid tx power scale level");
6893 return -EINVAL;
6894 }
6895
Peng Xu62c8c432016-05-09 15:23:02 -07006896 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006897
Peng Xu62c8c432016-05-09 15:23:02 -07006898 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006899 hdd_err("Set tx power scale failed");
6900 return -EINVAL;
6901 }
6902
6903 return 0;
6904}
6905
6906/**
6907 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6908 * @wiphy: Pointer to wireless phy
6909 * @wdev: Pointer to wireless device
6910 * @data: Pointer to data
6911 * @data_len: Data length
6912 *
6913 * Return: 0 on success, negative errno on failure
6914 */
6915static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6916 struct wireless_dev *wdev,
6917 const void *data,
6918 int data_len)
6919{
Peng Xu62c8c432016-05-09 15:23:02 -07006920 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006921
6922 cds_ssr_protect(__func__);
6923 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6924 data, data_len);
6925 cds_ssr_unprotect(__func__);
6926
6927 return ret;
6928}
6929
6930/**
6931 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6932 * @wiphy: Pointer to wireless phy
6933 * @wdev: Pointer to wireless device
6934 * @data: Pointer to data
6935 * @data_len: Data length
6936 *
6937 * Return: 0 on success, negative errno on failure
6938 */
6939static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6940 struct wireless_dev *wdev,
6941 const void *data,
6942 int data_len)
6943{
6944 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6945 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006946 hdd_adapter_t *adapter;
6947 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006948 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6949 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006950 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006951
Jeff Johnson1f61b612016-02-12 16:28:33 -08006952 ENTER_DEV(dev);
6953
Peng Xu4d67c8f2015-10-16 16:02:26 -07006954 ret = wlan_hdd_validate_context(hdd_ctx);
6955 if (ret)
6956 return ret;
6957
6958 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6959
6960 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6961 data, data_len, NULL)) {
6962 hdd_err("Invalid ATTR");
6963 return -EINVAL;
6964 }
6965
6966 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6967 hdd_err("attr tx power decrease db value failed");
6968 return -EINVAL;
6969 }
6970
6971 scale_value = nla_get_u8(tb
6972 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6973
Peng Xu62c8c432016-05-09 15:23:02 -07006974 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6975 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006976
Peng Xu62c8c432016-05-09 15:23:02 -07006977 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006978 hdd_err("Set tx power decrease db failed");
6979 return -EINVAL;
6980 }
6981
6982 return 0;
6983}
6984
6985/**
6986 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6987 * @wiphy: Pointer to wireless phy
6988 * @wdev: Pointer to wireless device
6989 * @data: Pointer to data
6990 * @data_len: Data length
6991 *
6992 * Return: 0 on success, negative errno on failure
6993 */
6994static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6995 struct wireless_dev *wdev,
6996 const void *data,
6997 int data_len)
6998{
Peng Xu62c8c432016-05-09 15:23:02 -07006999 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07007000
7001 cds_ssr_protect(__func__);
7002 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
7003 data, data_len);
7004 cds_ssr_unprotect(__func__);
7005
7006 return ret;
7007}
Peng Xu8fdaa492016-06-22 10:20:47 -07007008
7009/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307010 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
7011 * @wiphy: Pointer to wireless phy
7012 * @wdev: Pointer to wireless device
7013 * @data: Pointer to data
7014 * @data_len: Data length
7015 *
7016 * Processes the conditional channel switch request and invokes the helper
7017 * APIs to process the channel switch request.
7018 *
7019 * Return: 0 on success, negative errno on failure
7020 */
7021static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
7022 struct wireless_dev *wdev,
7023 const void *data,
7024 int data_len)
7025{
7026 int ret;
7027 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7028 struct net_device *dev = wdev->netdev;
7029 hdd_adapter_t *adapter;
7030 struct nlattr
7031 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
7032 uint32_t freq_len, i;
7033 uint32_t *freq;
7034 uint8_t chans[QDF_MAX_NUM_CHAN];
7035
7036 ENTER_DEV(dev);
7037
7038 ret = wlan_hdd_validate_context(hdd_ctx);
7039 if (ret)
7040 return ret;
7041
7042 if (!hdd_ctx->config->enableDFSMasterCap) {
7043 hdd_err("DFS master capability is not present in the driver");
7044 return -EINVAL;
7045 }
7046
7047 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7048 hdd_err("Command not allowed in FTM mode");
7049 return -EPERM;
7050 }
7051
7052 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7053 if (adapter->device_mode != QDF_SAP_MODE) {
7054 hdd_err("Invalid device mode %d", adapter->device_mode);
7055 return -EINVAL;
7056 }
7057
7058 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
7059 data, data_len, NULL)) {
7060 hdd_err("Invalid ATTR");
7061 return -EINVAL;
7062 }
7063
7064 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
7065 hdd_err("Frequency list is missing");
7066 return -EINVAL;
7067 }
7068
7069 freq_len = nla_len(
7070 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
7071 sizeof(uint32_t);
7072
7073 if (freq_len > QDF_MAX_NUM_CHAN) {
7074 hdd_err("insufficient space to hold channels");
7075 return -ENOMEM;
7076 }
7077
7078 hdd_debug("freq_len=%d", freq_len);
7079
7080 freq = nla_data(
7081 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
7082
7083
7084 for (i = 0; i < freq_len; i++) {
7085 if (freq[i] == 0)
7086 chans[i] = 0;
7087 else
7088 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7089
7090 hdd_debug("freq[%d]=%d", i, freq[i]);
7091 }
7092
7093 /*
7094 * The input frequency list from user space is designed to be a
7095 * priority based frequency list. This is only to accommodate any
7096 * future request. But, current requirement is only to perform CAC
7097 * on a single channel. So, the first entry from the list is picked.
7098 *
7099 * If channel is zero, any channel in the available outdoor regulatory
7100 * domain will be selected.
7101 */
7102 ret = wlan_hdd_request_pre_cac(chans[0]);
7103 if (ret) {
7104 hdd_err("pre cac request failed with reason:%d", ret);
7105 return ret;
7106 }
7107
7108 return 0;
7109}
7110
7111/**
Peng Xu8fdaa492016-06-22 10:20:47 -07007112 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
7113 * @wiphy: Pointer to wireless phy
7114 * @wdev: Pointer to wireless device
7115 * @data: Pointer to data
7116 * @data_len: Data length
7117 *
7118 * This function is to process the p2p listen offload start vendor
7119 * command. It parses the input parameters and invoke WMA API to
7120 * send the command to firmware.
7121 *
7122 * Return: 0 on success, negative errno on failure
7123 */
7124static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
7125 struct wireless_dev *wdev,
7126 const void *data,
7127 int data_len)
7128{
7129 int ret;
7130 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7131 struct net_device *dev = wdev->netdev;
7132 hdd_adapter_t *adapter;
7133 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
7134 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07007135
7136 ENTER_DEV(dev);
7137
7138 ret = wlan_hdd_validate_context(hdd_ctx);
7139 if (ret)
7140 return ret;
7141
7142 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7143 hdd_err("Command not allowed in FTM mode");
7144 return -EPERM;
7145 }
7146
7147 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7148 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
7149 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
7150 (adapter->device_mode != QDF_P2P_GO_MODE)) {
7151 hdd_err("Invalid device mode %d", adapter->device_mode);
7152 return -EINVAL;
7153 }
7154
7155 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
7156 data, data_len, NULL)) {
7157 hdd_err("Invalid ATTR");
7158 return -EINVAL;
7159 }
7160
7161 memset(&params, 0, sizeof(params));
7162
7163 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
7164 params.ctl_flags = 1; /* set to default value */
7165 else
7166 params.ctl_flags = nla_get_u32(tb
7167 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
7168
7169 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
7170 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
7171 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
7172 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
7173 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
7174 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
7175 hdd_err("Attribute parsing failed");
7176 return -EINVAL;
7177 }
7178
7179 params.vdev_id = adapter->sessionId;
7180 params.freq = nla_get_u32(tb
7181 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
7182 if ((params.freq != 2412) && (params.freq != 2437) &&
7183 (params.freq != 2462)) {
7184 hdd_err("Invalid listening channel: %d", params.freq);
7185 return -EINVAL;
7186 }
7187
7188 params.period = nla_get_u32(tb
7189 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
7190 if (!((params.period > 0) && (params.period < UINT_MAX))) {
7191 hdd_err("Invalid period: %d", params.period);
7192 return -EINVAL;
7193 }
7194
7195 params.interval = nla_get_u32(tb
7196 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
7197 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
7198 hdd_err("Invalid interval: %d", params.interval);
7199 return -EINVAL;
7200 }
7201
7202 params.count = nla_get_u32(tb
7203 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08007204 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07007205 hdd_err("Invalid count: %d", params.count);
7206 return -EINVAL;
7207 }
7208
7209 params.device_types = nla_data(tb
7210 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
7211 if (params.device_types == NULL) {
7212 hdd_err("Invalid device types");
7213 return -EINVAL;
7214 }
7215
7216 params.dev_types_len = nla_len(tb
7217 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
7218 if (params.dev_types_len < 8) {
7219 hdd_err("Invalid device type length: %d", params.dev_types_len);
7220 return -EINVAL;
7221 }
7222
7223 params.probe_resp_tmplt = nla_data(tb
7224 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
7225 if (params.probe_resp_tmplt == NULL) {
7226 hdd_err("Invalid probe response template");
7227 return -EINVAL;
7228 }
7229
7230 params.probe_resp_len = nla_len(tb
7231 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
7232 if (params.probe_resp_len == 0) {
7233 hdd_err("Invalid probe resp template length: %d",
7234 params.probe_resp_len);
7235 return -EINVAL;
7236 }
7237
7238 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
7239 params.freq, params.period, params.interval, params.count);
7240
Wu Gao9a704f42017-03-10 18:42:11 +08007241 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07007242}
7243
7244
7245/**
7246 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
7247 * @wiphy: Pointer to wireless phy
7248 * @wdev: Pointer to wireless device
7249 * @data: Pointer to data
7250 * @data_len: Data length
7251 *
7252 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
7253 * to process p2p listen offload start vendor command.
7254 *
7255 * Return: 0 on success, negative errno on failure
7256 */
7257static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
7258 struct wireless_dev *wdev,
7259 const void *data,
7260 int data_len)
7261{
7262 int ret = 0;
7263
7264 cds_ssr_protect(__func__);
7265 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
7266 data, data_len);
7267 cds_ssr_unprotect(__func__);
7268
7269 return ret;
7270}
7271
7272/**
7273 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
7274 * @wiphy: Pointer to wireless phy
7275 * @wdev: Pointer to wireless device
7276 * @data: Pointer to data
7277 * @data_len: Data length
7278 *
7279 * This function is to process the p2p listen offload stop vendor
7280 * command. It invokes WMA API to send command to firmware.
7281 *
7282 * Return: 0 on success, negative errno on failure
7283 */
7284static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
7285 struct wireless_dev *wdev,
7286 const void *data,
7287 int data_len)
7288{
Peng Xu8fdaa492016-06-22 10:20:47 -07007289 hdd_adapter_t *adapter;
7290 struct net_device *dev = wdev->netdev;
7291
7292 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7293 hdd_err("Command not allowed in FTM mode");
7294 return -EPERM;
7295 }
7296
7297 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7298 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
7299 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
7300 (adapter->device_mode != QDF_P2P_GO_MODE)) {
7301 hdd_err("Invalid device mode");
7302 return -EINVAL;
7303 }
7304
Wu Gao9a704f42017-03-10 18:42:11 +08007305 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07007306}
7307
7308/**
7309 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
7310 * @wiphy: Pointer to wireless phy
7311 * @wdev: Pointer to wireless device
7312 * @data: Pointer to data
7313 * @data_len: Data length
7314 *
7315 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
7316 * to process p2p listen offload stop vendor command.
7317 *
7318 * Return: 0 on success, negative errno on failure
7319 */
7320static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
7321 struct wireless_dev *wdev,
7322 const void *data,
7323 int data_len)
7324{
7325 int ret = 0;
7326
7327 cds_ssr_protect(__func__);
7328 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
7329 data, data_len);
7330 cds_ssr_unprotect(__func__);
7331
7332 return ret;
7333}
7334
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307335/**
7336 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
7337 * @wiphy: Pointer to wireless phy
7338 * @wdev: Pointer to wireless device
7339 * @data: Pointer to data
7340 * @data_len: Data length
7341 *
7342 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
7343 * to process the conditional channel switch request.
7344 *
7345 * Return: 0 on success, negative errno on failure
7346 */
7347static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
7348 struct wireless_dev *wdev,
7349 const void *data,
7350 int data_len)
7351{
7352 int ret;
7353
7354 cds_ssr_protect(__func__);
7355 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
7356 data, data_len);
7357 cds_ssr_unprotect(__func__);
7358
7359 return ret;
7360}
7361
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307362/*
7363 * define short names for the global vendor params
7364 * used by __wlan_hdd_cfg80211_bpf_offload()
7365 */
7366#define BPF_INVALID \
7367 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
7368#define BPF_SET_RESET \
7369 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
7370#define BPF_VERSION \
7371 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
7372#define BPF_FILTER_ID \
7373 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
7374#define BPF_PACKET_SIZE \
7375 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
7376#define BPF_CURRENT_OFFSET \
7377 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
7378#define BPF_PROGRAM \
7379 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
7380#define BPF_MAX \
7381 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07007382
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307383static const struct nla_policy
7384wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
7385 [BPF_SET_RESET] = {.type = NLA_U32},
7386 [BPF_VERSION] = {.type = NLA_U32},
7387 [BPF_FILTER_ID] = {.type = NLA_U32},
7388 [BPF_PACKET_SIZE] = {.type = NLA_U32},
7389 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
7390 [BPF_PROGRAM] = {.type = NLA_U8},
7391};
7392
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007393struct bpf_offload_priv {
7394 struct sir_bpf_get_offload bpf_get_offload;
7395};
7396
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307397/**
7398 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007399 * @context: opaque context originally passed to SME. HDD always passes
7400 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307401 * @bpf_get_offload: struct for get offload
7402 *
7403 * This function receives the response/data from the lower layer and
7404 * checks to see if the thread is still waiting then post the results to
7405 * upper layer, if the request has timed out then ignore.
7406 *
7407 * Return: None
7408 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007409static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007410 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307411{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007412 struct hdd_request *request;
7413 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307414
7415 ENTER();
7416
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007417 request = hdd_request_get(context);
7418 if (!request) {
7419 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307420 return;
7421 }
7422
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007423 priv = hdd_request_priv(request);
7424 priv->bpf_get_offload = *data;
7425 hdd_request_complete(request);
7426 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307427}
7428
7429/**
7430 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
7431 * @hdd_context: hdd_context
7432 * @bpf_get_offload: struct for get offload
7433 *
7434 * Return: 0 on success, error number otherwise.
7435 */
7436static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
7437 struct sir_bpf_get_offload *bpf_get_offload)
7438{
7439 struct sk_buff *skb;
7440 uint32_t nl_buf_len;
7441
7442 ENTER();
7443
7444 nl_buf_len = NLMSG_HDRLEN;
7445 nl_buf_len +=
7446 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
7447 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
7448
7449 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7450 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07007451 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307452 return -ENOMEM;
7453 }
7454
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007455 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307456 bpf_get_offload->bpf_version,
7457 bpf_get_offload->max_bytes_for_bpf_inst);
7458
7459 if (nla_put_u32(skb, BPF_PACKET_SIZE,
7460 bpf_get_offload->max_bytes_for_bpf_inst) ||
7461 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007462 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307463 goto nla_put_failure;
7464 }
7465
7466 cfg80211_vendor_cmd_reply(skb);
7467 EXIT();
7468 return 0;
7469
7470nla_put_failure:
7471 kfree_skb(skb);
7472 return -EINVAL;
7473}
7474
7475/**
7476 * hdd_get_bpf_offload - Get BPF offload Capabilities
7477 * @hdd_ctx: Hdd context
7478 *
7479 * Return: 0 on success, errno on failure
7480 */
7481static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
7482{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307483 QDF_STATUS status;
7484 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007485 void *cookie;
7486 struct hdd_request *request;
7487 struct bpf_offload_priv *priv;
7488 static const struct hdd_request_params params = {
7489 .priv_size = sizeof(*priv),
7490 .timeout_ms = WLAN_WAIT_TIME_BPF,
7491 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307492
7493 ENTER();
7494
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007495 request = hdd_request_alloc(&params);
7496 if (!request) {
7497 hdd_err("Unable to allocate request");
7498 return -EINVAL;
7499 }
7500 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307501
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007502 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
7503 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007504 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307505 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007506 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007507 ret = qdf_status_to_os_return(status);
7508 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307509 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007510 ret = hdd_request_wait_for_response(request);
7511 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007512 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007513 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307514 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007515 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307516 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007517 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307518 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007519 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307520
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007521cleanup:
7522 /*
7523 * either we never sent a request to SME, we sent a request to
7524 * SME and timed out, or we sent a request to SME, received a
7525 * response from SME, and posted the response to userspace.
7526 * regardless we are done with the request.
7527 */
7528 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307529 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007530
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307531 return ret;
7532}
7533
7534/**
7535 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7536 * @hdd_ctx: Hdd context
7537 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307538 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307539 *
7540 * Return: 0 on success; errno on failure
7541 */
7542static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7543 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307544 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307545{
7546 struct sir_bpf_set_offload *bpf_set_offload;
7547 QDF_STATUS status;
7548 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307549 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307550
7551 ENTER();
7552
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307553 if (adapter->device_mode == QDF_STA_MODE ||
7554 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7555 if (!hdd_conn_is_connected(
7556 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7557 hdd_err("Not in Connected state!");
7558 return -ENOTSUPP;
7559 }
7560 }
7561
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307562 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7563 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007564 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307565 return -ENOMEM;
7566 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307567
7568 /* Parse and fetch bpf packet size */
7569 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007570 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307571 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307572 goto fail;
7573 }
7574 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7575
7576 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007577 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307578 goto post_sme;
7579 }
7580
7581 /* Parse and fetch bpf program */
7582 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007583 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307584 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307585 goto fail;
7586 }
7587
7588 prog_len = nla_len(tb[BPF_PROGRAM]);
7589 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307590
7591 if (bpf_set_offload->program == NULL) {
7592 hdd_err("qdf_mem_malloc failed for bpf offload program");
7593 ret = -ENOMEM;
7594 goto fail;
7595 }
7596
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307597 bpf_set_offload->current_length = prog_len;
7598 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307599 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307600
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007601 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007602 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307603 bpf_set_offload->program, prog_len);
7604
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307605 /* Parse and fetch filter Id */
7606 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007607 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307608 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307609 goto fail;
7610 }
7611 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7612
7613 /* Parse and fetch current offset */
7614 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007615 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307616 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307617 goto fail;
7618 }
7619 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7620
7621post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007622 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 +05307623 bpf_set_offload->session_id,
7624 bpf_set_offload->version,
7625 bpf_set_offload->filter_id,
7626 bpf_set_offload->total_length,
7627 bpf_set_offload->current_length,
7628 bpf_set_offload->current_offset);
7629
7630 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7631 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007632 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307633 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307634 goto fail;
7635 }
7636 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307637
7638fail:
7639 if (bpf_set_offload->current_length)
7640 qdf_mem_free(bpf_set_offload->program);
7641 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307642 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307643}
7644
7645/**
7646 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7647 * @wiphy: wiphy structure pointer
7648 * @wdev: Wireless device structure pointer
7649 * @data: Pointer to the data received
7650 * @data_len: Length of @data
7651 *
7652 * Return: 0 on success; errno on failure
7653 */
7654static int
7655__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7656 struct wireless_dev *wdev,
7657 const void *data, int data_len)
7658{
7659 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7660 struct net_device *dev = wdev->netdev;
7661 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7662 struct nlattr *tb[BPF_MAX + 1];
7663 int ret_val, packet_filter_subcmd;
7664
7665 ENTER();
7666
7667 ret_val = wlan_hdd_validate_context(hdd_ctx);
7668 if (ret_val)
7669 return ret_val;
7670
7671 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007672 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307673 return -EINVAL;
7674 }
7675
7676 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007677 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307678 return -ENOTSUPP;
7679 }
7680
7681 if (nla_parse(tb, BPF_MAX, data, data_len,
7682 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007683 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307684 return -EINVAL;
7685 }
7686
7687 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007688 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307689 return -EINVAL;
7690 }
7691
7692 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7693
7694 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7695 return hdd_get_bpf_offload(hdd_ctx);
7696 else
7697 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307698 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307699}
7700
7701/**
7702 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7703 * @wiphy: wiphy structure pointer
7704 * @wdev: Wireless device structure pointer
7705 * @data: Pointer to the data received
7706 * @data_len: Length of @data
7707 *
7708 * Return: 0 on success; errno on failure
7709 */
7710
7711static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7712 struct wireless_dev *wdev,
7713 const void *data, int data_len)
7714{
7715 int ret;
7716
7717 cds_ssr_protect(__func__);
7718 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7719 cds_ssr_unprotect(__func__);
7720
7721 return ret;
7722}
7723
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307724/**
7725 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7726 * @pre_cac_adapter: AP adapter used for pre cac
7727 * @status: Status (true or false)
7728 * @handle: Global handle
7729 *
7730 * Sets the status of pre cac i.e., whether the pre cac is active or not
7731 *
7732 * Return: Zero on success, non-zero on failure
7733 */
7734static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7735 bool status, tHalHandle handle)
7736{
7737 QDF_STATUS ret;
7738
7739 ret = wlan_sap_set_pre_cac_status(
7740 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7741 if (QDF_IS_STATUS_ERROR(ret))
7742 return -EINVAL;
7743
7744 return 0;
7745}
7746
7747/**
7748 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7749 * @ap_adapter: AP adapter
7750 * @chan_before_pre_cac: Channel
7751 *
7752 * Saves the channel which the AP was beaconing on before moving to the pre
7753 * cac channel. If radar is detected on the pre cac channel, this saved
7754 * channel will be used for AP operations.
7755 *
7756 * Return: Zero on success, non-zero on failure
7757 */
7758static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7759 uint8_t chan_before_pre_cac)
7760{
7761 QDF_STATUS ret;
7762
7763 ret = wlan_sap_set_chan_before_pre_cac(
7764 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7765 if (QDF_IS_STATUS_ERROR(ret))
7766 return -EINVAL;
7767
7768 return 0;
7769}
7770
7771/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307772 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7773 * are in nol list from provided channel list
7774 * @adapter: AP adapter
7775 * @channel_count: channel count
7776 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307777 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307778 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307779 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307780static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7781 uint32_t *channel_count,
7782 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307783{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307784 uint8_t i, j;
7785 uint32_t nol_len = 0;
7786 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7787 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7788 uint32_t chan_count;
7789 bool found;
7790 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307791
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307792 if (!hdd_ctx) {
7793 hdd_err("hdd ctx not found");
7794 *channel_count = 0;
7795 return;
7796 }
7797
7798 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7799 hdd_err("invalid channel count %d", *channel_count);
7800 return;
7801 }
7802
7803 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7804 if (nol_len == 0)
7805 return;
7806
7807 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7808 chan_count = *channel_count;
7809 qdf_mem_zero(channel_list, chan_count);
7810 *channel_count = 0;
7811
7812 for (i = 0 ; i < chan_count; i++) {
7813 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7814 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7815 continue;
7816 found = false;
7817 for (j = 0; j < nol_len; j++) {
7818 if (tmp_chan_list[i] == nol[j]) {
7819 found = true;
7820 hdd_notice("skipped channel %d due to nol",
7821 nol[j]);
7822 break;
7823 }
7824 }
7825 if (!found) {
7826 channel_list[*channel_count] = tmp_chan_list[i];
7827 *channel_count = *channel_count + 1;
7828 }
7829 }
7830}
7831
7832int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7833 uint32_t *channel_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307834 uint8_t *channel_list,
7835 eCsrBand band)
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307836{
7837 tsap_Config_t *sap_config;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307838 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
7839 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7840 uint32_t chan_count;
7841 uint8_t i;
7842 QDF_STATUS status;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307843
7844 sap_config = &adapter->sessionCtx.ap.sapConfig;
7845
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05307846 status =
7847 policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7848 tmp_chan_list,
7849 &chan_count);
7850 if (QDF_IS_STATUS_ERROR(status)) {
7851 hdd_err("Failed to get channel list");
7852 return -EINVAL;
7853 }
7854 for (i = 0; i < chan_count; i++) {
7855 if (*channel_count < QDF_MAX_NUM_CHAN) {
7856 if ((eCSR_BAND_24 == band) &&
7857 (WLAN_REG_IS_24GHZ_CH(tmp_chan_list[i]))) {
7858 channel_list[*channel_count] = tmp_chan_list[i];
7859 *channel_count += 1;
7860 } else if ((eCSR_BAND_5G == band) &&
7861 (WLAN_REG_IS_5GHZ_CH(tmp_chan_list[i]))) {
7862 channel_list[*channel_count] = tmp_chan_list[i];
7863 *channel_count += 1;
7864 }
7865 } else {
7866 break;
7867 }
7868 }
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307869 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307870 if (*channel_count == 0) {
7871 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307872 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307873 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307874
7875 return 0;
7876}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307877
7878/**
7879 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7880 * @hdd_ctx: HDD context
7881 * @ap_adapter: AP adapter
7882 * @channel: Channel requested by userspace
7883 * @pre_cac_chan: Pointer to the pre CAC channel
7884 *
7885 * Validates the channel provided by userspace. If user provided channel 0,
7886 * a valid outdoor channel must be selected from the regulatory channel.
7887 *
7888 * Return: Zero on success and non zero value on error
7889 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007890static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7891 hdd_adapter_t *ap_adapter,
7892 uint8_t channel,
7893 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307894{
7895 uint32_t i, j;
7896 QDF_STATUS status;
7897 int ret;
7898 uint8_t nol[QDF_MAX_NUM_CHAN];
7899 uint32_t nol_len = 0, weight_len = 0;
7900 bool found;
7901 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7902 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7903 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7904
7905 if (0 == channel) {
7906 /* Channel is not obtained from PCL because PCL may not have
7907 * the entire channel list. For example: if SAP is up on
7908 * channel 6 and PCL is queried for the next SAP interface,
7909 * if SCC is preferred, the PCL will contain only the channel
7910 * 6. But, we are in need of a DFS channel. So, going with the
7911 * first channel from the valid channel list.
7912 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007913 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7914 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307915 if (QDF_IS_STATUS_ERROR(status)) {
7916 hdd_err("Failed to get channel list");
7917 return -EINVAL;
7918 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007919 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307920 pcl_weights, weight_len);
7921 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7922 for (i = 0; i < len; i++) {
7923 found = false;
7924 for (j = 0; j < nol_len; j++) {
7925 if (channel_list[i] == nol[j]) {
7926 found = true;
7927 break;
7928 }
7929 }
7930 if (found)
7931 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007932 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7933 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307934 *pre_cac_chan = channel_list[i];
7935 break;
7936 }
7937 }
7938 if (*pre_cac_chan == 0) {
7939 hdd_err("unable to find outdoor channel");
7940 return -EINVAL;
7941 }
7942 } else {
7943 /* Only when driver selects a channel, check is done for
7944 * unnsafe and NOL channels. When user provides a fixed channel
7945 * the user is expected to take care of this.
7946 */
7947 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007948 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307949 hdd_err("Invalid channel for pre cac:%d", channel);
7950 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307951 }
Jeff Johnson68755312017-02-10 11:46:55 -08007952
7953 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307954 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007955 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307956 return 0;
7957}
7958
7959/**
7960 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7961 * @channel: Channel option provided by userspace
7962 *
7963 * Sets the driver to the required hardware mode and start an adapater for
7964 * pre CAC which will mimic an AP.
7965 *
7966 * Return: Zero on success, non-zero value on error
7967 */
7968int wlan_hdd_request_pre_cac(uint8_t channel)
7969{
Krunal Sonib37bb352016-12-20 14:12:21 -08007970 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307971 hdd_context_t *hdd_ctx;
7972 int ret;
7973 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7974 hdd_ap_ctx_t *hdd_ap_ctx;
7975 QDF_STATUS status;
7976 struct wiphy *wiphy;
7977 struct net_device *dev;
7978 struct cfg80211_chan_def chandef;
7979 enum nl80211_channel_type channel_type;
7980 uint32_t freq;
7981 struct ieee80211_channel *chan;
7982 tHalHandle handle;
7983 bool val;
7984
7985 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7986 if (0 != wlan_hdd_validate_context(hdd_ctx))
7987 return -EINVAL;
7988
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007989 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307990 hdd_err("pre cac not allowed in concurrency");
7991 return -EINVAL;
7992 }
7993
7994 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7995 if (!ap_adapter) {
7996 hdd_err("unable to get SAP adapter");
7997 return -EINVAL;
7998 }
7999
8000 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
8001 if (!handle) {
8002 hdd_err("Invalid handle");
8003 return -EINVAL;
8004 }
8005
8006 val = wlan_sap_is_pre_cac_active(handle);
8007 if (val) {
8008 hdd_err("pre cac is already in progress");
8009 return -EINVAL;
8010 }
8011
8012 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
8013 if (!hdd_ap_ctx) {
8014 hdd_err("SAP context is NULL");
8015 return -EINVAL;
8016 }
8017
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008018 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
8019 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308020 hdd_err("SAP is already on DFS channel:%d",
8021 hdd_ap_ctx->operatingChannel);
8022 return -EINVAL;
8023 }
8024
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008025 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308026 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
8027 hdd_ap_ctx->operatingChannel);
8028 return -EINVAL;
8029 }
8030
Krunal Sonib37bb352016-12-20 14:12:21 -08008031 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
8032 if (!mac_addr) {
8033 hdd_err("can't add virtual intf: Not getting valid mac addr");
8034 return -EINVAL;
8035 }
8036
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008037 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308038
8039 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
8040 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08008041 if (ret != 0) {
8042 hdd_err("can't validate pre-cac channel");
8043 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308044 }
8045
8046 hdd_debug("starting pre cac SAP adapter");
8047
8048 /* Starting a SAP adapter:
8049 * Instead of opening an adapter, we could just do a SME open session
8050 * for AP type. But, start BSS would still need an adapter.
8051 * So, this option is not taken.
8052 *
8053 * hdd open adapter is going to register this precac interface with
8054 * user space. This interface though exposed to user space will be in
8055 * DOWN state. Consideration was done to avoid this registration to the
8056 * user space. But, as part of SAP operations multiple events are sent
8057 * to user space. Some of these events received from unregistered
8058 * interface was causing crashes. So, retaining the registration.
8059 *
8060 * So, this interface would remain registered and will remain in DOWN
8061 * state for the CAC duration. We will add notes in the feature
8062 * announcement to not use this temporary interface for any activity
8063 * from user space.
8064 */
8065 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08008066 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308067 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308068 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08008069 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308070 }
8071
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308072 /*
8073 * This interface is internally created by the driver. So, no interface
8074 * up comes for this interface from user space and hence starting
8075 * the adapter internally.
8076 */
8077 if (hdd_start_adapter(pre_cac_adapter)) {
8078 hdd_err("error starting the pre cac adapter");
8079 goto close_pre_cac_adapter;
8080 }
8081
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308082 hdd_debug("preparing for start ap/bss on the pre cac adapter");
8083
8084 wiphy = hdd_ctx->wiphy;
8085 dev = pre_cac_adapter->dev;
8086
8087 /* Since this is only a dummy interface lets us use the IEs from the
8088 * other active SAP interface. In regular scenarios, these IEs would
8089 * come from the user space entity
8090 */
8091 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
8092 sizeof(*ap_adapter->sessionCtx.ap.beacon));
8093 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
8094 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308095 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308096 }
8097 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
8098 ap_adapter->sessionCtx.ap.beacon,
8099 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
8100 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
8101 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
8102 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
8103 ap_adapter->sessionCtx.ap.sapConfig.authType;
8104
8105 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
8106 * to operate on the same bandwidth as that of the 2.4GHz operations.
8107 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
8108 */
8109 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
8110 case CH_WIDTH_20MHZ:
8111 channel_type = NL80211_CHAN_HT20;
8112 break;
8113 case CH_WIDTH_40MHZ:
8114 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
8115 ap_adapter->sessionCtx.ap.sapConfig.channel)
8116 channel_type = NL80211_CHAN_HT40PLUS;
8117 else
8118 channel_type = NL80211_CHAN_HT40MINUS;
8119 break;
8120 default:
8121 channel_type = NL80211_CHAN_NO_HT;
8122 break;
8123 }
8124
8125 freq = cds_chan_to_freq(pre_cac_chan);
8126 chan = __ieee80211_get_channel(wiphy, freq);
8127 if (!chan) {
8128 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308129 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308130 }
8131
8132 cfg80211_chandef_create(&chandef, chan, channel_type);
8133
8134 hdd_debug("orig width:%d channel_type:%d freq:%d",
8135 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
8136 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08008137 /*
8138 * Doing update after opening and starting pre-cac adapter will make
8139 * sure that driver won't do hardware mode change if there are any
8140 * initial hick-ups or issues in pre-cac adapter's configuration.
8141 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
8142 * connection update should result in DBS mode
8143 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008144 status = policy_mgr_update_and_wait_for_connection_update(
8145 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08008146 ap_adapter->sessionId,
8147 pre_cac_chan,
8148 SIR_UPDATE_REASON_PRE_CAC);
8149 if (QDF_IS_STATUS_ERROR(status)) {
8150 hdd_err("error in moving to DBS mode");
8151 goto stop_close_pre_cac_adapter;
8152 }
8153
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308154
8155 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
8156 if (0 != ret) {
8157 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308158 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308159 }
8160
8161 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
8162 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08008163 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308164 if (QDF_IS_STATUS_ERROR(status)) {
8165 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308166 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308167 }
8168
8169 /*
8170 * The pre cac status is set here. But, it would not be reset explicitly
8171 * anywhere, since after the pre cac success/failure, the pre cac
8172 * adapter itself would be removed.
8173 */
8174 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
8175 if (0 != ret) {
8176 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308177 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308178 }
8179
8180 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
8181 hdd_ap_ctx->operatingChannel);
8182 if (0 != ret) {
8183 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308184 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308185 }
8186
8187 ap_adapter->pre_cac_chan = pre_cac_chan;
8188
8189 return 0;
8190
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308191stop_close_pre_cac_adapter:
8192 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308193 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
8194 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05308195close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308196 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08008197release_intf_addr_and_return_failure:
8198 /*
8199 * Release the interface address as the adapter
8200 * failed to start, if you don't release then next
8201 * adapter which is trying to come wouldn't get valid
8202 * mac address. Remember we have limited pool of mac addresses
8203 */
8204 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308205 return -EINVAL;
8206}
8207
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308208static const struct nla_policy
8209wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
8210 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
8211};
8212
Agrawal Ashish65634612016-08-18 13:24:32 +05308213static const struct nla_policy
8214wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
8215 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
8216 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
8217};
8218
8219/**
8220 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
8221 * @wiphy: Pointer to wireless phy
8222 * @wdev: Pointer to wireless device
8223 * @data: Pointer to data
8224 * @data_len: Length of @data
8225 *
8226 * This function parses the incoming NL vendor command data attributes and
8227 * updates the SAP context about channel_hint and DFS mode.
8228 * If channel_hint is set, SAP will choose that channel
8229 * as operating channel.
8230 *
8231 * If DFS mode is enabled, driver will include DFS channels
8232 * in ACS else driver will skip DFS channels.
8233 *
8234 * Return: 0 on success, negative errno on failure
8235 */
8236static int
8237__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8238 struct wireless_dev *wdev,
8239 const void *data, int data_len)
8240{
8241 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8242 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
8243 int ret;
8244 struct acs_dfs_policy *acs_policy;
8245 int mode = DFS_MODE_NONE;
8246 int channel_hint = 0;
8247
8248 ENTER_DEV(wdev->netdev);
8249
8250 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8251 hdd_err("Command not allowed in FTM mode");
8252 return -EINVAL;
8253 }
8254
8255 ret = wlan_hdd_validate_context(hdd_ctx);
8256 if (0 != ret)
8257 return ret;
8258
8259 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
8260 data, data_len,
8261 wlan_hdd_set_acs_dfs_config_policy)) {
8262 hdd_err("invalid attr");
8263 return -EINVAL;
8264 }
8265
8266 acs_policy = &hdd_ctx->acs_policy;
8267 /*
8268 * SCM sends this attribute to restrict SAP from choosing
8269 * DFS channels from ACS.
8270 */
8271 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
8272 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
8273
8274 if (!IS_DFS_MODE_VALID(mode)) {
8275 hdd_err("attr acs dfs mode is not valid");
8276 return -EINVAL;
8277 }
8278 acs_policy->acs_dfs_mode = mode;
8279
8280 /*
8281 * SCM sends this attribute to provide an active channel,
8282 * to skip redundant ACS between drivers, and save driver start up time
8283 */
8284 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
8285 channel_hint = nla_get_u8(
8286 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
8287
8288 if (!IS_CHANNEL_VALID(channel_hint)) {
8289 hdd_err("acs channel is not valid");
8290 return -EINVAL;
8291 }
8292 acs_policy->acs_channel = channel_hint;
8293
8294 return 0;
8295}
8296
8297/**
8298 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
8299 * @wiphy: wiphy structure pointer
8300 * @wdev: Wireless device structure pointer
8301 * @data: Pointer to the data received
8302 * @data_len: Length of @data
8303 *
8304 * This function parses the incoming NL vendor command data attributes and
8305 * updates the SAP context about channel_hint and DFS mode.
8306 *
8307 * Return: 0 on success; errno on failure
8308 */
8309static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
8310 struct wireless_dev *wdev,
8311 const void *data, int data_len)
8312{
8313 int ret;
8314
8315 cds_ssr_protect(__func__);
8316 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
8317 cds_ssr_unprotect(__func__);
8318
8319 return ret;
8320}
8321
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308322/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308323 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
8324 * @mode : cfg80211 dfs mode
8325 *
8326 * Return: return csr sta roam dfs mode else return NONE
8327 */
8328static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
8329 enum dfs_mode mode)
8330{
8331 switch (mode) {
8332 case DFS_MODE_ENABLE:
8333 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
8334 break;
8335 case DFS_MODE_DISABLE:
8336 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
8337 break;
8338 case DFS_MODE_DEPRIORITIZE:
8339 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
8340 break;
8341 default:
8342 hdd_err("STA Roam policy dfs mode is NONE");
8343 return CSR_STA_ROAM_POLICY_NONE;
8344 }
8345}
8346
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308347/*
8348 * hdd_get_sap_operating_band: Get current operating channel
8349 * for sap.
8350 * @hdd_ctx: hdd context
8351 *
8352 * Return : Corresponding band for SAP operating channel
8353 */
8354uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
8355{
8356 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
8357 QDF_STATUS status;
8358 hdd_adapter_t *adapter;
8359 uint8_t operating_channel = 0;
8360 uint8_t sap_operating_band = 0;
8361 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8362 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
8363 adapter = adapter_node->pAdapter;
8364
8365 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
8366 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8367 &next);
8368 adapter_node = next;
8369 continue;
8370 }
8371 operating_channel = adapter->sessionCtx.ap.operatingChannel;
8372 if (IS_24G_CH(operating_channel))
8373 sap_operating_band = eCSR_BAND_24;
8374 else if (IS_5G_CH(operating_channel))
8375 sap_operating_band = eCSR_BAND_5G;
8376 else
8377 sap_operating_band = eCSR_BAND_ALL;
8378 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8379 &next);
bings373b99b2017-01-23 10:35:08 +08008380 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308381 }
8382 return sap_operating_band;
8383}
8384
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308385static const struct nla_policy
8386wlan_hdd_set_sta_roam_config_policy[
8387QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
8388 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
8389 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
8390};
8391
8392/**
8393 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
8394 * for station connection or roaming.
8395 * @wiphy: Pointer to wireless phy
8396 * @wdev: Pointer to wireless device
8397 * @data: Pointer to data
8398 * @data_len: Length of @data
8399 *
8400 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8401 * channels needs to be skipped in scanning or not.
8402 * If dfs_mode is disabled, driver will not scan DFS channels.
8403 * If skip_unsafe_channels is set, driver will skip unsafe channels
8404 * in Scanning.
8405 *
8406 * Return: 0 on success, negative errno on failure
8407 */
8408static int
8409__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8410 struct wireless_dev *wdev,
8411 const void *data, int data_len)
8412{
8413 struct net_device *dev = wdev->netdev;
8414 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8415 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8416 struct nlattr *tb[
8417 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
8418 int ret;
8419 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
8420 enum dfs_mode mode = DFS_MODE_NONE;
8421 bool skip_unsafe_channels = false;
8422 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308423 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308424
8425 ENTER_DEV(dev);
8426
8427 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8428 hdd_err("Command not allowed in FTM mode");
8429 return -EINVAL;
8430 }
8431
8432 ret = wlan_hdd_validate_context(hdd_ctx);
8433 if (0 != ret)
8434 return ret;
8435 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
8436 data, data_len,
8437 wlan_hdd_set_sta_roam_config_policy)) {
8438 hdd_err("invalid attr");
8439 return -EINVAL;
8440 }
8441 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
8442 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
8443 if (!IS_DFS_MODE_VALID(mode)) {
8444 hdd_err("attr sta roam dfs mode policy is not valid");
8445 return -EINVAL;
8446 }
8447
8448 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
8449
8450 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
8451 skip_unsafe_channels = nla_get_u8(
8452 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308453 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308454 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05308455 skip_unsafe_channels, adapter->sessionId,
8456 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308457
8458 if (!QDF_IS_STATUS_SUCCESS(status)) {
8459 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
8460 return -EINVAL;
8461 }
8462 return 0;
8463}
8464
8465/**
8466 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
8467 * connection and roaming for station.
8468 * @wiphy: wiphy structure pointer
8469 * @wdev: Wireless device structure pointer
8470 * @data: Pointer to the data received
8471 * @data_len: Length of @data
8472 *
8473 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
8474 * channels needs to be skipped in scanning or not.
8475 * If dfs_mode is disabled, driver will not scan DFS channels.
8476 * If skip_unsafe_channels is set, driver will skip unsafe channels
8477 * in Scanning.
8478 * Return: 0 on success; errno on failure
8479 */
8480static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
8481 struct wireless_dev *wdev,
8482 const void *data, int data_len)
8483{
8484 int ret;
8485
8486 cds_ssr_protect(__func__);
8487 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
8488 cds_ssr_unprotect(__func__);
8489
8490 return ret;
8491}
8492
Agrawal Ashish467dde42016-09-08 18:44:22 +05308493#ifdef FEATURE_WLAN_CH_AVOID
8494/**
8495 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8496 * is on unsafe channel.
8497 * @wiphy: wiphy structure pointer
8498 * @wdev: Wireless device structure pointer
8499 * @data: Pointer to the data received
8500 * @data_len: Length of @data
8501 *
8502 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8503 * on any of unsafe channels.
8504 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8505 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8506 *
8507 * Return: 0 on success; errno on failure
8508 */
8509static int
8510__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8511 struct wireless_dev *wdev,
8512 const void *data, int data_len)
8513{
8514 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8515 int ret;
8516 uint16_t unsafe_channel_count;
8517 int unsafe_channel_index;
8518 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
8519
8520 ENTER_DEV(wdev->netdev);
8521
8522 if (!qdf_ctx) {
8523 cds_err("qdf_ctx is NULL");
8524 return -EINVAL;
8525 }
8526
8527 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8528 hdd_err("Command not allowed in FTM mode");
8529 return -EINVAL;
8530 }
8531
8532 ret = wlan_hdd_validate_context(hdd_ctx);
8533 if (0 != ret)
8534 return ret;
8535 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8536 &(hdd_ctx->unsafe_channel_count),
8537 sizeof(hdd_ctx->unsafe_channel_list));
8538
8539 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8540 (uint16_t)NUM_CHANNELS);
8541 for (unsafe_channel_index = 0;
8542 unsafe_channel_index < unsafe_channel_count;
8543 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008544 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308545 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8546 }
8547 hdd_unsafe_channel_restart_sap(hdd_ctx);
8548 return 0;
8549}
8550
8551/**
8552 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8553 * is on unsafe channel.
8554 * @wiphy: wiphy structure pointer
8555 * @wdev: Wireless device structure pointer
8556 * @data: Pointer to the data received
8557 * @data_len: Length of @data
8558 *
8559 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8560 * on any of unsafe channels.
8561 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8562 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8563 *
8564 * Return: 0 on success; errno on failure
8565 */
8566static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8567 struct wireless_dev *wdev,
8568 const void *data, int data_len)
8569{
8570 int ret;
8571
8572 cds_ssr_protect(__func__);
8573 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8574 cds_ssr_unprotect(__func__);
8575
8576 return ret;
8577}
8578
8579#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308580/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308581 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8582 * SAP is on unsafe channel.
8583 * @wiphy: wiphy structure pointer
8584 * @wdev: Wireless device structure pointer
8585 * @data: Pointer to the data received
8586 * @data_len: Length of @data
8587 *
8588 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8589 * driver.
8590 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8591 * will initiate restart of sap.
8592 *
8593 * Return: 0 on success; errno on failure
8594 */
8595static int
8596__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8597 struct wireless_dev *wdev,
8598 const void *data, int data_len)
8599{
8600 struct net_device *ndev = wdev->netdev;
8601 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8602 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8603 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8604 uint8_t config_channel = 0;
8605 hdd_ap_ctx_t *ap_ctx;
8606 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308607 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308608
8609 ENTER();
8610
8611 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008612 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308613 return -EINVAL;
8614 }
8615
8616 ret = wlan_hdd_validate_context(hdd_ctx);
8617 if (0 != ret)
8618 return -EINVAL;
8619
8620 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8621 data, data_len,
8622 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008623 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308624 return -EINVAL;
8625 }
8626
8627 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8628 if (!test_bit(SOFTAP_BSS_STARTED,
8629 &hostapd_adapter->event_flags)) {
8630 hdd_err("SAP is not started yet. Restart sap will be invalid");
8631 return -EINVAL;
8632 }
8633
8634 config_channel =
8635 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8636
8637 if (!((IS_24G_CH(config_channel)) ||
8638 (IS_5G_CH(config_channel)))) {
8639 hdd_err("Channel %d is not valid to restart SAP",
8640 config_channel);
8641 return -ENOTSUPP;
8642 }
8643
8644 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8645 ap_ctx->sapConfig.channel = config_channel;
8646 ap_ctx->sapConfig.ch_params.ch_width =
8647 ap_ctx->sapConfig.ch_width_orig;
8648
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008649 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8650 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308651 ap_ctx->sapConfig.sec_ch,
8652 &ap_ctx->sapConfig.ch_params);
8653
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008654 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308655 }
8656
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308657 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8658 uint32_t freq_len, i;
8659 uint32_t *freq;
8660 uint8_t chans[QDF_MAX_NUM_CHAN];
8661
8662 hdd_debug("setting mandatory freq/chan list");
8663
8664 freq_len = nla_len(
8665 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8666 sizeof(uint32_t);
8667
8668 if (freq_len > QDF_MAX_NUM_CHAN) {
8669 hdd_err("insufficient space to hold channels");
8670 return -ENOMEM;
8671 }
8672
8673 freq = nla_data(
8674 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8675
8676 hdd_debug("freq_len=%d", freq_len);
8677
8678 for (i = 0; i < freq_len; i++) {
8679 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8680 hdd_debug("freq[%d]=%d", i, freq[i]);
8681 }
8682
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008683 status = policy_mgr_set_sap_mandatory_channels(
8684 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308685 if (QDF_IS_STATUS_ERROR(status))
8686 return -EINVAL;
8687 }
8688
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308689 return 0;
8690}
8691
8692/**
8693 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8694 * @wiphy: wiphy structure pointer
8695 * @wdev: Wireless device structure pointer
8696 * @data: Pointer to the data received
8697 * @data_len: Length of @data
8698 *
8699 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8700 * driver.
8701 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8702 * will initiate restart of sap.
8703 *
8704 * Return: 0 on success; errno on failure
8705 */
8706static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8707 struct wireless_dev *wdev,
8708 const void *data, int data_len)
8709{
8710 int ret;
8711
8712 cds_ssr_protect(__func__);
8713 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8714 wdev, data, data_len);
8715 cds_ssr_unprotect(__func__);
8716
8717 return ret;
8718}
8719
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308720#undef BPF_INVALID
8721#undef BPF_SET_RESET
8722#undef BPF_VERSION
8723#undef BPF_ID
8724#undef BPF_PACKET_SIZE
8725#undef BPF_CURRENT_OFFSET
8726#undef BPF_PROGRAM
8727#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308728
8729/**
8730 * define short names for the global vendor params
8731 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8732 */
8733#define PARAM_TOTAL_CMD_EVENT_WAKE \
8734 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8735#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8736 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8737#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8738 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8739#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8740 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8741#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8742 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8743#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8744 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8745#define PARAM_TOTAL_RX_DATA_WAKE \
8746 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8747#define PARAM_RX_UNICAST_CNT \
8748 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8749#define PARAM_RX_MULTICAST_CNT \
8750 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8751#define PARAM_RX_BROADCAST_CNT \
8752 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8753#define PARAM_ICMP_PKT \
8754 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8755#define PARAM_ICMP6_PKT \
8756 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8757#define PARAM_ICMP6_RA \
8758 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8759#define PARAM_ICMP6_NA \
8760 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8761#define PARAM_ICMP6_NS \
8762 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8763#define PARAM_ICMP4_RX_MULTICAST_CNT \
8764 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8765#define PARAM_ICMP6_RX_MULTICAST_CNT \
8766 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8767#define PARAM_OTHER_RX_MULTICAST_CNT \
8768 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308769#define PARAM_RSSI_BREACH_CNT \
8770 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8771#define PARAM_LOW_RSSI_CNT \
8772 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8773#define PARAM_GSCAN_CNT \
8774 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8775#define PARAM_PNO_COMPLETE_CNT \
8776 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8777#define PARAM_PNO_MATCH_CNT \
8778 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8779
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308780
8781
8782/**
8783 * hdd_send_wakelock_stats() - API to send wakelock stats
8784 * @ctx: context to be passed to callback
8785 * @data: data passed to callback
8786 *
8787 * This function is used to send wake lock stats to HAL layer
8788 *
8789 * Return: 0 on success, error number otherwise.
8790 */
8791static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8792 const struct sir_wake_lock_stats *data)
8793{
8794 struct sk_buff *skb;
8795 uint32_t nl_buf_len;
8796 uint32_t total_rx_data_wake, rx_multicast_cnt;
8797 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308798 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308799
8800 ENTER();
8801
8802 nl_buf_len = NLMSG_HDRLEN;
8803 nl_buf_len +=
8804 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8805 (NLMSG_HDRLEN + sizeof(uint32_t));
8806
8807 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8808
8809 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008810 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308811 return -ENOMEM;
8812 }
8813
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008814 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308815 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008816 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308817 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008818 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308819 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008820 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308821 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008822 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308823 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008824 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308825 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008826 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308827 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008828 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8829 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308830 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008831 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308832 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008833 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308834 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008835 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308836 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008837 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308838 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008839 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308840 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308841
8842 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308843 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308844
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308845 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308846 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308847
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308848 rx_multicast_cnt =
8849 data->wow_ipv4_mcast_wake_up_count +
8850 ipv6_rx_multicast_addr_cnt;
8851
8852 total_rx_data_wake =
8853 data->wow_ucast_wake_up_count +
8854 data->wow_bcast_wake_up_count +
8855 rx_multicast_cnt;
8856
8857 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8858 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8859 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8860 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8861 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8862 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8863 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8864 total_rx_data_wake) ||
8865 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8866 data->wow_ucast_wake_up_count) ||
8867 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8868 rx_multicast_cnt) ||
8869 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8870 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308871 nla_put_u32(skb, PARAM_ICMP_PKT,
8872 data->wow_icmpv4_count) ||
8873 nla_put_u32(skb, PARAM_ICMP6_PKT,
8874 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308875 nla_put_u32(skb, PARAM_ICMP6_RA,
8876 data->wow_ipv6_mcast_ra_stats) ||
8877 nla_put_u32(skb, PARAM_ICMP6_NA,
8878 data->wow_ipv6_mcast_na_stats) ||
8879 nla_put_u32(skb, PARAM_ICMP6_NS,
8880 data->wow_ipv6_mcast_ns_stats) ||
8881 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8882 data->wow_ipv4_mcast_wake_up_count) ||
8883 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8884 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308885 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8886 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8887 data->wow_rssi_breach_wake_up_count) ||
8888 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8889 data->wow_low_rssi_wake_up_count) ||
8890 nla_put_u32(skb, PARAM_GSCAN_CNT,
8891 data->wow_gscan_wake_up_count) ||
8892 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8893 data->wow_pno_complete_wake_up_count) ||
8894 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8895 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008896 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308897 goto nla_put_failure;
8898 }
8899
8900 cfg80211_vendor_cmd_reply(skb);
8901
8902 EXIT();
8903 return 0;
8904
8905nla_put_failure:
8906 kfree_skb(skb);
8907 return -EINVAL;
8908}
8909
8910/**
8911 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8912 * @wiphy: wiphy pointer
8913 * @wdev: pointer to struct wireless_dev
8914 * @data: pointer to incoming NL vendor data
8915 * @data_len: length of @data
8916 *
8917 * This function parses the incoming NL vendor command data attributes and
8918 * invokes the SME Api and blocks on a completion variable.
8919 * WMA copies required data and invokes callback
8920 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8921 *
8922 * Return: 0 on success; error number otherwise.
8923 */
8924static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8925 struct wireless_dev *wdev,
8926 const void *data,
8927 int data_len)
8928{
8929 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8930 int status, ret;
8931 struct sir_wake_lock_stats wake_lock_stats;
8932 QDF_STATUS qdf_status;
8933
8934 ENTER();
8935
8936 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008937 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308938 return -EINVAL;
8939 }
8940
8941 status = wlan_hdd_validate_context(hdd_ctx);
8942 if (0 != status)
8943 return -EINVAL;
8944
8945 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8946 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008947 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308948 return -EINVAL;
8949 }
8950
8951 ret = hdd_send_wakelock_stats(hdd_ctx,
8952 &wake_lock_stats);
8953 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008954 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308955
8956 EXIT();
8957 return ret;
8958}
8959
8960/**
8961 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8962 * @wiphy: wiphy pointer
8963 * @wdev: pointer to struct wireless_dev
8964 * @data: pointer to incoming NL vendor data
8965 * @data_len: length of @data
8966 *
8967 * This function parses the incoming NL vendor command data attributes and
8968 * invokes the SME Api and blocks on a completion variable.
8969 * WMA copies required data and invokes callback
8970 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8971 *
8972 * Return: 0 on success; error number otherwise.
8973 */
8974static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8975 struct wireless_dev *wdev,
8976 const void *data, int data_len)
8977{
8978 int ret;
8979
8980 cds_ssr_protect(__func__);
8981 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8982 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008983 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308984
8985 return ret;
8986}
8987
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308988/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308989 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8990 * @wiphy: wiphy structure pointer
8991 * @wdev: Wireless device structure pointer
8992 * @data: Pointer to the data received
8993 * @data_len: Length of @data
8994 *
8995 * This function reads wmi max bus size and fill in the skb with
8996 * NL attributes and send up the NL event.
8997 * Return: 0 on success; errno on failure
8998 */
8999static int
9000__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
9001 struct wireless_dev *wdev,
9002 const void *data, int data_len)
9003{
9004 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9005 int ret_val;
9006 struct sk_buff *skb;
9007 uint32_t nl_buf_len;
9008
9009 ENTER();
9010
9011 ret_val = wlan_hdd_validate_context(hdd_ctx);
9012 if (ret_val)
9013 return ret_val;
9014
9015 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9016 hdd_err("Command not allowed in FTM mode");
9017 return -EINVAL;
9018 }
9019
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009020 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309021
9022 nl_buf_len = NLMSG_HDRLEN;
9023 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
9024
9025 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
9026 if (!skb) {
9027 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
9028 return -ENOMEM;
9029 }
9030
9031 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
9032 hdd_ctx->wmi_max_len)) {
9033 hdd_err("nla put failure");
9034 goto nla_put_failure;
9035 }
9036
9037 cfg80211_vendor_cmd_reply(skb);
9038
9039 EXIT();
9040
9041 return 0;
9042
9043nla_put_failure:
9044 kfree_skb(skb);
9045 return -EINVAL;
9046}
9047
9048/**
9049 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
9050 * @wiphy: wiphy structure pointer
9051 * @wdev: Wireless device structure pointer
9052 * @data: Pointer to the data received
9053 * @data_len: Length of @data
9054 *
9055 * Return: 0 on success; errno on failure
9056 */
9057static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
9058 struct wireless_dev *wdev,
9059 const void *data, int data_len)
9060{
9061 int ret;
9062
9063 cds_ssr_protect(__func__);
9064 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
9065 cds_ssr_unprotect(__func__);
9066
9067 return ret;
9068}
9069
9070/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309071 *__wlan_hdd_cfg80211_setband() - set band
9072 * @wiphy: Pointer to wireless phy
9073 * @wdev: Pointer to wireless device
9074 * @data: Pointer to data
9075 * @data_len: Length of @data
9076 *
9077 * Return: 0 on success, negative errno on failure
9078 */
9079static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9080 struct wireless_dev *wdev,
9081 const void *data, int data_len)
9082{
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309083 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07009084 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309085 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9086 int ret;
9087 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
9088 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
9089
9090 ENTER();
9091
9092 ret = wlan_hdd_validate_context(hdd_ctx);
9093 if (ret)
9094 return ret;
9095
9096 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
9097 hdd_err(FL("Invalid ATTR"));
9098 return -EINVAL;
9099 }
9100
9101 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
9102 hdd_err(FL("attr SETBAND_VALUE failed"));
9103 return -EINVAL;
9104 }
9105
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07009106 ret = hdd_reg_set_band(dev,
9107 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309108
9109 EXIT();
9110 return ret;
9111}
9112
9113/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309114 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
9115 * @adapter: hdd adapter
9116 * @channel: channel number
9117 *
9118 * return: QDF status based on success or failure
9119 */
9120static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
9121 int channel, int chan_bw)
9122{
9123 if (QDF_STATUS_SUCCESS !=
9124 wlan_hdd_validate_operation_channel(adapter, channel))
9125 return QDF_STATUS_E_FAILURE;
9126 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9127 channel,
9128 PHY_SINGLE_CHANNEL_CENTERED))) {
9129 hdd_notice("channel %d is in nol", channel);
9130 return -EINVAL;
9131 }
9132
9133 if ((wlansap_is_channel_leaking_in_nol(
9134 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9135 channel, chan_bw))) {
9136 hdd_notice("channel %d is leaking in nol", channel);
9137 return -EINVAL;
9138 }
9139
9140 return 0;
9141
9142}
9143
Kapil Gupta8878ad92017-02-13 11:56:04 +05309144static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
9145 tsap_Config_t *sap_config,
9146 struct hdd_vendor_chan_info *channel_list)
9147{
9148 sap_config->channel = channel_list->pri_ch;
9149
9150 sap_config->ch_params.center_freq_seg0 =
9151 channel_list->vht_seg0_center_ch;
9152 sap_config->ch_params.center_freq_seg1 =
9153 channel_list->vht_seg1_center_ch;
9154
9155 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
9156 sap_config->ch_params.ch_width = channel_list->chan_width;
9157 if (sap_config->channel >= 36)
9158 sap_config->ch_width_orig =
9159 hdd_ctx->config->vhtChannelWidth;
9160 else
9161 sap_config->ch_width_orig =
9162 hdd_ctx->config->nChannelBondingMode24GHz ?
9163 eHT_CHANNEL_WIDTH_40MHZ :
9164 eHT_CHANNEL_WIDTH_20MHZ;
9165
9166 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
9167 sap_config->acs_cfg.ch_width = channel_list->chan_width;
9168 sap_config->acs_cfg.vht_seg0_center_ch =
9169 channel_list->vht_seg0_center_ch;
9170 sap_config->acs_cfg.vht_seg1_center_ch =
9171 channel_list->vht_seg1_center_ch;
9172 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
9173}
9174
9175static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
9176 uint8_t channel_cnt,
9177 struct hdd_vendor_chan_info *channel_list)
9178{
9179 tsap_Config_t *sap_config;
9180 hdd_ap_ctx_t *hdd_ap_ctx;
9181 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9182 QDF_STATUS status = QDF_STATUS_SUCCESS;
9183
9184 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
9185 sap_config = &adapter->sessionCtx.ap.sapConfig;
9186
9187 if (QDF_TIMER_STATE_RUNNING ==
9188 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
9189 ap.vendor_acs_timer)) {
9190 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
9191 }
9192
9193 if (channel_list && channel_list->pri_ch == 0) {
9194 /* Check mode, set default channel */
9195 channel_list->pri_ch = 6;
9196 /*
9197 * sap_select_default_oper_chan(hdd_ctx->hHal,
9198 * sap_config->acs_cfg.hw_mode);
9199 */
9200 }
9201
9202 switch (reason) {
9203 /* SAP init case */
9204 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
9205 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
9206 /* Update Hostapd */
9207 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
9208 break;
9209
9210 /* DFS detected on current channel */
9211 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
9212 wlan_sap_update_next_channel(
9213 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
9214 channel_list->pri_ch,
9215 channel_list->chan_width);
9216 status = sme_update_new_channel_event(
9217 WLAN_HDD_GET_HAL_CTX(adapter),
9218 adapter->sessionId);
9219 break;
9220
9221 /* LTE coex event on current channel */
9222 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
9223 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
9224 sap_config->acs_cfg.ch_width = channel_list->chan_width;
9225 hdd_ap_ctx->sapConfig.ch_width_orig =
9226 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08009227 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05309228 break;
9229
9230 default:
9231 hdd_info("invalid reason for timer invoke");
9232 }
9233 qdf_mem_free(channel_list);
9234 EXIT();
9235 return status;
9236}
9237
9238/**
9239 * Define short name for vendor channel set config
9240 */
9241#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
9242#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
9243#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
9244#define SET_CHAN_PRIMARY_CHANNEL \
9245 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
9246#define SET_CHAN_SECONDARY_CHANNEL \
9247 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
9248#define SET_CHAN_SEG0_CENTER_CHANNEL \
9249 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
9250#define SET_CHAN_SEG1_CENTER_CHANNEL \
9251 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
9252#define SET_CHAN_CHANNEL_WIDTH \
9253 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
9254#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
9255
9256/**
9257 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
9258 * @channel_list: pointer to hdd_vendor_chan_info
9259 * @reason: channel change reason
9260 * @channel_cnt: channel count
9261 * @data: data
9262 * @data_len: data len
9263 *
9264 * Return: 0 on success, negative errno on failure
9265 */
9266static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
9267 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
9268 const void *data, int data_len)
9269{
9270 int rem, i = 0;
9271 struct nlattr *tb[SET_CHAN_MAX + 1];
9272 struct nlattr *tb2[SET_CHAN_MAX + 1];
9273 struct nlattr *curr_attr;
9274 struct hdd_vendor_chan_info *channel_list;
9275
9276 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
9277 hdd_err("Invalid ATTR");
9278 return -EINVAL;
9279 }
9280
9281 if (tb[SET_CHAN_REASON])
9282 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
9283
9284 if (tb[SET_CHAN_CHANNEL_COUNT]) {
9285 *channel_cnt = nla_get_u8(tb[
9286 SET_CHAN_CHANNEL_COUNT]);
9287 hdd_info("channel count %d", *channel_cnt);
9288 }
9289
9290 if (!(*channel_cnt)) {
9291 hdd_err("channel count is %d", *channel_cnt);
9292 return -EINVAL;
9293 }
9294
9295 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
9296 (*channel_cnt));
9297
9298 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
9299 if (nla_parse(tb2,
9300 SET_CHAN_MAX,
9301 nla_data(curr_attr), nla_len(curr_attr),
9302 NULL)) {
9303 hdd_err("nla_parse failed");
9304 return -EINVAL;
9305 }
9306 /* Parse and Fetch allowed SSID list*/
9307 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
9308 channel_list[i].pri_ch =
9309 nla_get_u8(
9310 tb2[SET_CHAN_PRIMARY_CHANNEL]);
9311 }
9312 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
9313 channel_list[i].ht_sec_ch =
9314 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
9315 }
9316 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
9317 channel_list[i].vht_seg0_center_ch =
9318 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
9319 }
9320 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
9321 channel_list[i].vht_seg1_center_ch =
9322 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
9323 }
9324 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
9325 channel_list[i].chan_width =
9326 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
9327 }
9328 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
9329 i, channel_list[i].pri_ch,
9330 channel_list[i].ht_sec_ch,
9331 channel_list[i].vht_seg0_center_ch,
9332 channel_list[i].vht_seg1_center_ch,
9333 channel_list[i].chan_width);
9334 i++;
9335 if (i > *channel_cnt)
9336 break;
9337 }
9338 *chan_list_ptr = channel_list;
9339
9340 return 0;
9341}
9342
9343/**
9344 * Undef short names for vendor set channel configuration
9345 */
9346#undef SET_CHAN_REASON
9347#undef SET_CHAN_CHANNEL_COUNT
9348#undef SET_CHAN_CHAN_LIST
9349#undef SET_CHAN_PRIMARY_CHANNEL
9350#undef SET_CHAN_SECONDARY_CHANNEL
9351#undef SET_CHAN_SEG0_CENTER_CHANNEL
9352#undef SET_CHAN_SEG1_CENTER_CHANNEL
9353#undef SET_CHAN_CHANNEL_WIDTH
9354#undef SET_CHAN_MAX
9355
9356/**
9357 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9358 * @wiphy: Pointer to wireless phy
9359 * @wdev: Pointer to wireless device
9360 * @data: Pointer to data
9361 * @data_len: Length of @data
9362 *
9363 * Return: 0 on success, negative errno on failure
9364 */
9365static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9366 struct wireless_dev *wdev,
9367 const void *data, int data_len)
9368{
9369 int ret_val;
9370 QDF_STATUS qdf_status;
9371 uint8_t channel_cnt = 0, reason = -1;
9372 struct hdd_vendor_chan_info *channel_list = NULL;
9373 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
9374 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9375
9376 ENTER();
9377
9378 ret_val = wlan_hdd_validate_context(hdd_ctx);
9379 if (ret_val)
9380 return ret_val;
9381
9382 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9383 hdd_err("Command not allowed in FTM mode");
9384 return -EINVAL;
9385 }
9386
9387 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
9388 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
9389 else {
9390 hdd_err("already timeout happened for acs");
9391 return -EINVAL;
9392 }
9393
9394 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
9395 &channel_cnt, data, data_len);
9396 if (ret_val)
9397 return ret_val;
9398
9399 /* Validate channel to be set */
9400 while (channel_cnt && channel_list) {
9401 qdf_status = wlan_hdd_validate_acs_channel(adapter,
9402 channel_list->pri_ch,
9403 channel_list->chan_width);
9404 if (qdf_status == QDF_STATUS_SUCCESS)
9405 break;
9406 channel_cnt--;
9407 channel_list++;
9408 }
9409 if ((channel_cnt <= 0) || !channel_list) {
9410 hdd_err("no available channel/chanlist %p", channel_list);
9411 return -EINVAL;
9412 }
9413
9414 qdf_status = hdd_update_acs_channel(adapter, reason,
9415 channel_cnt, channel_list);
9416 return qdf_status_to_os_return(qdf_status);
9417}
9418
9419/**
9420 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
9421 * @wiphy: Pointer to wireless phy
9422 * @wdev: Pointer to wireless device
9423 * @data: Pointer to data
9424 * @data_len: Length of @data
9425 *
9426 * Return: 0 on success, negative errno on failure
9427 */
9428static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
9429 struct wireless_dev *wdev,
9430 const void *data, int data_len)
9431{
9432 int ret;
9433
9434 cds_ssr_protect(__func__);
9435 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
9436 data_len);
9437 cds_ssr_protect(__func__);
9438
9439 return ret;
9440}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309441
9442/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309443 * wlan_hdd_cfg80211_setband() - Wrapper to setband
9444 * @wiphy: wiphy structure pointer
9445 * @wdev: Wireless device structure pointer
9446 * @data: Pointer to the data received
9447 * @data_len: Length of @data
9448 *
9449 * Return: 0 on success; errno on failure
9450 */
9451static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
9452 struct wireless_dev *wdev,
9453 const void *data, int data_len)
9454{
9455 int ret;
9456
9457 cds_ssr_protect(__func__);
9458 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
9459 cds_ssr_unprotect(__func__);
9460
9461 return ret;
9462}
9463
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009464/**
9465 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
9466 * @nl80211_value: Vendor command attribute value
9467 * @wmi_value: Pointer to return converted WMI return value
9468 *
9469 * Convert NL80211 vendor command value for SAR limit set to WMI value
9470 * Return: 0 on success, -1 on invalid value
9471 */
9472static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
9473 u32 *wmi_value)
9474{
9475 int ret = 0;
9476
9477 switch (nl80211_value) {
9478 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
9479 *wmi_value = WMI_SAR_FEATURE_OFF;
9480 break;
9481 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
9482 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
9483 break;
9484 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
9485 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
9486 break;
9487 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
9488 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
9489 break;
9490 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
9491 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
9492 break;
9493 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
9494 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
9495 break;
9496 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
9497 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
9498 break;
9499 default:
9500 ret = -1;
9501 }
9502 return ret;
9503}
9504
9505/**
9506 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
9507 * @nl80211_value: Vendor command attribute value
9508 * @wmi_value: Pointer to return converted WMI return value
9509 *
9510 * Convert NL80211 vendor command value for SAR BAND to WMI value
9511 * Return: 0 on success, -1 on invalid value
9512 */
9513static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
9514{
9515 int ret = 0;
9516
9517 switch (nl80211_value) {
9518 case NL80211_BAND_2GHZ:
9519 *wmi_value = WMI_SAR_2G_ID;
9520 break;
9521 case NL80211_BAND_5GHZ:
9522 *wmi_value = WMI_SAR_5G_ID;
9523 break;
9524 default:
9525 ret = -1;
9526 }
9527 return ret;
9528}
9529
9530/**
9531 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9532 * @nl80211_value: Vendor command attribute value
9533 * @wmi_value: Pointer to return converted WMI return value
9534 *
9535 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9536 * Return: 0 on success, -1 on invalid value
9537 */
9538static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9539 u32 *wmi_value)
9540{
9541 int ret = 0;
9542
9543 switch (nl80211_value) {
9544 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9545 *wmi_value = WMI_SAR_MOD_CCK;
9546 break;
9547 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9548 *wmi_value = WMI_SAR_MOD_OFDM;
9549 break;
9550 default:
9551 ret = -1;
9552 }
9553 return ret;
9554}
9555
Jeff Johnsonb17a93c2017-06-02 12:26:55 -07009556static const struct nla_policy
9557sar_limits_policy[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1] = {
9558 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE] = {.type = NLA_U32},
9559 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS] = {.type = NLA_U32},
9560 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND] = {.type = NLA_U32},
9561 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN] = {.type = NLA_U32},
9562 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION] = {.type = NLA_U32},
9563 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT] = {.type = NLA_U32},
9564};
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009565
9566/**
9567 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9568 * @wiphy: Pointer to wireless phy
9569 * @wdev: Pointer to wireless device
9570 * @data: Pointer to data
9571 * @data_len: Length of @data
9572 *
9573 * This function is used to setup Specific Absorption Rate limit specs.
9574 *
9575 * Return: 0 on success, negative errno on failure
9576 */
9577static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9578 struct wireless_dev *wdev,
9579 const void *data, int data_len)
9580{
9581 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9582 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9583 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9584 *sar_spec_list;
9585 struct sar_limit_cmd_params sar_limit_cmd = {0};
9586 int ret = -EINVAL, i = 0, rem = 0;
9587
9588 ENTER();
9589
9590 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9591 hdd_err("Command not allowed in FTM mode");
9592 return -EPERM;
9593 }
9594
9595 if (wlan_hdd_validate_context(hdd_ctx))
9596 return -EINVAL;
9597
9598 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
Jeff Johnsonb17a93c2017-06-02 12:26:55 -07009599 data, data_len, sar_limits_policy)) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009600 hdd_err("Invalid SAR attributes");
9601 return -EINVAL;
9602 }
9603
9604 /* Vendor command manadates all SAR Specs in single call */
9605 sar_limit_cmd.commit_limits = 1;
9606 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9607 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9608 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9609 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9610 &sar_limit_cmd.sar_enable) < 0) {
9611 hdd_err("Invalid SAR Enable attr");
9612 goto fail;
9613 }
9614 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009615 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009616
9617 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9618 sar_limit_cmd.num_limit_rows = nla_get_u32(
9619 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009620 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009621 sar_limit_cmd.num_limit_rows);
9622 }
9623 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9624 hdd_err("SAR Spec list exceed supported size");
9625 goto fail;
9626 }
9627 if (sar_limit_cmd.num_limit_rows == 0)
9628 goto send_sar_limits;
9629 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9630 struct sar_limit_cmd_row) *
9631 sar_limit_cmd.num_limit_rows);
9632 if (!sar_limit_cmd.sar_limit_row_list) {
9633 ret = -ENOMEM;
9634 goto fail;
9635 }
9636 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9637 hdd_err("Invalid SAR SPECs list");
9638 goto fail;
9639 }
9640
9641 nla_for_each_nested(sar_spec_list,
9642 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9643 if (i == sar_limit_cmd.num_limit_rows) {
9644 hdd_warn("SAR Cmd has excess SPECs in list");
9645 break;
9646 }
9647
9648 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9649 nla_data(sar_spec_list), nla_len(sar_spec_list),
Jeff Johnsonb17a93c2017-06-02 12:26:55 -07009650 sar_limits_policy)) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009651 hdd_err("nla_parse failed for SAR Spec list");
9652 goto fail;
9653 }
9654 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9655 if (sar_spec[
9656 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9657 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9658 nla_get_u32(sar_spec[
9659 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9660 } else {
9661 hdd_err("SAR Spec does not have power limit value");
9662 goto fail;
9663 }
9664
9665 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9666 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9667 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9668 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9669 < 0) {
9670 hdd_err("Invalid SAR Band attr");
9671 goto fail;
9672 }
9673 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9674 WMI_SAR_BAND_ID_VALID_MASK;
9675 }
9676 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9677 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9678 nla_get_u32(sar_spec[
9679 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9680 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9681 WMI_SAR_CHAIN_ID_VALID_MASK;
9682 }
9683 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9684 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9685 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9686 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9687 < 0) {
9688 hdd_err("Invalid SAR Modulation attr");
9689 goto fail;
9690 }
9691 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9692 WMI_SAR_MOD_ID_VALID_MASK;
9693 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009694 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009695 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9696 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9697 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9698 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9699 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9700 i++;
9701 }
9702
9703 if (i < sar_limit_cmd.num_limit_rows) {
9704 hdd_warn("SAR Cmd has less SPECs in list");
9705 sar_limit_cmd.num_limit_rows = i;
9706 }
9707
9708send_sar_limits:
9709 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9710 QDF_STATUS_SUCCESS)
9711 ret = 0;
9712fail:
9713 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9714 return ret;
9715}
9716
9717/**
9718 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9719 * @wiphy: Pointer to wireless phy
9720 * @wdev: Pointer to wireless device
9721 * @data: Pointer to data
9722 * @data_len: Length of @data
9723 *
9724 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9725 *
9726 * Return: 0 on success, negative errno on failure
9727 */
9728static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9729 struct wireless_dev *wdev,
9730 const void *data,
9731 int data_len)
9732{
9733 int ret;
9734
9735 cds_ssr_protect(__func__);
9736 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9737 data_len);
9738 cds_ssr_unprotect(__func__);
9739
9740 return ret;
9741}
9742
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309743static const struct
9744nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9745 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9746 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9747 .len = QDF_MAC_ADDR_SIZE},
9748};
9749
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309750void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9751{
9752 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9753 hdd_adapter_t *adapter;
9754
9755 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9756 if (!adapter) {
9757 hdd_err("adapter NULL");
9758 return;
9759 }
9760
9761 adapter->lfr_fw_status.is_disabled = rso_status->status;
9762 complete(&adapter->lfr_fw_status.disable_lfr_event);
9763}
9764
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309765/**
9766 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9767 * @wiphy: Pointer to wireless phy
9768 * @wdev: Pointer to wireless device
9769 * @data: Pointer to data
9770 * @data_len: Length of @data
9771 *
9772 * This function is used to enable/disable roaming using vendor commands
9773 *
9774 * Return: 0 on success, negative errno on failure
9775 */
9776static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9777 struct wireless_dev *wdev,
9778 const void *data, int data_len)
9779{
9780 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9781 struct net_device *dev = wdev->netdev;
9782 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9783 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309784 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309785 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309786 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309787 unsigned long rc;
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309788 hdd_station_ctx_t *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309789
9790 ENTER_DEV(dev);
9791
9792 ret = wlan_hdd_validate_context(hdd_ctx);
9793 if (0 != ret)
9794 return ret;
9795
9796 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9797 hdd_err("Command not allowed in FTM mode");
9798 return -EINVAL;
9799 }
9800
9801 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9802 qca_wlan_vendor_attr);
9803 if (ret) {
9804 hdd_err("Invalid ATTR");
9805 return -EINVAL;
9806 }
9807
9808 /* Parse and fetch Enable flag */
9809 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9810 hdd_err("attr enable failed");
9811 return -EINVAL;
9812 }
9813
9814 is_fast_roam_enabled = nla_get_u32(
9815 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009816 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009817 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309818
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009819 if (!adapter->fast_roaming_allowed) {
9820 hdd_err("fast roaming not allowed on %s interface",
9821 adapter->dev->name);
9822 return -EINVAL;
9823 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309824 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309825 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309826 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309827 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309828 if (qdf_status != QDF_STATUS_SUCCESS)
9829 hdd_err("sme_config_fast_roaming failed with status=%d",
9830 qdf_status);
9831 ret = qdf_status_to_os_return(qdf_status);
9832
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +05309833 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.connState &&
9834 QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9835
9836 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309837 /*
9838 * wait only for LFR disable in fw as LFR enable
9839 * is always success
9840 */
9841 rc = wait_for_completion_timeout(
9842 &adapter->lfr_fw_status.disable_lfr_event,
9843 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9844 if (!rc) {
9845 hdd_err("Timed out waiting for RSO CMD status");
9846 return -ETIMEDOUT;
9847 }
9848
9849 if (!adapter->lfr_fw_status.is_disabled) {
9850 hdd_err("Roam disable attempt in FW fails");
9851 return -EBUSY;
9852 }
9853 }
9854
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309855 EXIT();
9856 return ret;
9857}
9858
9859/**
9860 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9861 * @wiphy: Pointer to wireless phy
9862 * @wdev: Pointer to wireless device
9863 * @data: Pointer to data
9864 * @data_len: Length of @data
9865 *
9866 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9867 *
9868 * Return: 0 on success, negative errno on failure
9869 */
9870static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9871 struct wireless_dev *wdev,
9872 const void *data, int data_len)
9873{
9874 int ret;
9875
9876 cds_ssr_protect(__func__);
9877 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9878 cds_ssr_unprotect(__func__);
9879
9880 return ret;
9881}
9882
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309883
9884void hdd_update_cca_info_cb(void *context, uint32_t congestion,
9885 uint32_t vdev_id)
9886{
9887 hdd_context_t *hdd_ctx = (hdd_context_t *)context;
9888 int status;
9889 hdd_adapter_t *adapter = NULL;
9890 hdd_station_ctx_t *hdd_sta_ctx;
9891
9892 status = wlan_hdd_validate_context(hdd_ctx);
9893 if (status != 0)
9894 return;
9895
9896 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9897 if (adapter == NULL) {
9898 hdd_err("vdev_id %d does not exist with host", vdev_id);
9899 return;
9900 }
9901
9902 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9903 hdd_sta_ctx->conn_info.cca = congestion;
9904 hdd_info("congestion:%d", congestion);
9905}
9906
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309907static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9908 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9909 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9910 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9911 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9912};
9913
9914/**
9915 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9916 * @wiphy: Pointer to wireless phy
9917 * @wdev: Pointer to wireless device
9918 * @data: Pointer to data
9919 * @data_len: Length of @data
9920 *
9921 * Return: 0 on success, negative errno on failure
9922 */
9923static int
9924__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9925 struct wireless_dev *wdev,
9926 const void *data,
9927 int data_len)
9928{
9929 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9930 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9931 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9932 struct nlattr *apth;
9933 int rem;
9934 int ret = 1;
9935 int print_idx = -1;
9936 int module_id = -1;
9937 int bit_mask = -1;
9938 int status;
9939
9940 ENTER();
9941
9942 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9943 hdd_err("Command not allowed in FTM mode");
9944 return -EINVAL;
9945 }
9946
9947 ret = wlan_hdd_validate_context(hdd_ctx);
9948 if (ret != 0)
9949 return -EINVAL;
9950
9951 print_idx = qdf_get_pidx();
9952 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9953 hdd_err("Invalid print controle object index");
9954 return -EINVAL;
9955 }
9956
9957 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9958 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9959 hdd_err("Invalid attr");
9960 return -EINVAL;
9961 }
9962
9963 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9964 hdd_err("attr trace level param failed");
9965 return -EINVAL;
9966 }
9967
9968 nla_for_each_nested(apth,
9969 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9970 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9971 nla_data(apth), nla_len(apth), NULL)) {
9972 hdd_err("Invalid attr");
9973 return -EINVAL;
9974 }
9975
9976 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9977 hdd_err("attr Module ID failed");
9978 return -EINVAL;
9979 }
9980 module_id = nla_get_u32
9981 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9982
9983 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9984 hdd_err("attr Verbose mask failed");
9985 return -EINVAL;
9986 }
9987 bit_mask = nla_get_u32
9988 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9989
9990 status = hdd_qdf_trace_enable(module_id, bit_mask);
9991
9992 if (status != 0)
9993 hdd_err("can not set verbose mask %d for the category %d",
9994 bit_mask, module_id);
9995 }
9996
9997 EXIT();
9998 return ret;
9999}
10000
10001/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +053010002 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
10003 * @wiphy: Pointer to wireless phy
10004 * @wdev: Pointer to wireless device
10005 * @data: Pointer to data
10006 * @data_len: Length of @data
10007 *
10008 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
10009 *
10010 * Return: 0 on success, negative errno on failure
10011 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010012
10013static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
10014 struct wireless_dev *wdev,
10015 const void *data,
10016 int data_len)
10017{
10018 int ret;
10019
10020 cds_ssr_protect(__func__);
10021 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
10022 cds_ssr_unprotect(__func__);
10023
10024 return ret;
10025}
10026
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010027const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
10028 {
10029 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10030 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
10031 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +053010032 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010033 .doit = is_driver_dfs_capable
10034 },
10035
10036#ifdef WLAN_FEATURE_NAN
10037 {
10038 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10039 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
10040 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10041 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10042 .doit = wlan_hdd_cfg80211_nan_request
10043 },
10044#endif
10045
10046#ifdef WLAN_FEATURE_STATS_EXT
10047 {
10048 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10049 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
10050 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10051 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10052 .doit = wlan_hdd_cfg80211_stats_ext_request
10053 },
10054#endif
10055#ifdef FEATURE_WLAN_EXTSCAN
10056 {
10057 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10058 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
10059 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10060 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10061 .doit = wlan_hdd_cfg80211_extscan_start
10062 },
10063 {
10064 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10065 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
10066 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10067 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10068 .doit = wlan_hdd_cfg80211_extscan_stop
10069 },
10070 {
10071 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10072 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
10073 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
10074 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
10075 },
10076 {
10077 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10078 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
10079 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10080 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10081 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
10082 },
10083 {
10084 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10085 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
10086 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10087 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10088 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
10089 },
10090 {
10091 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10092 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
10093 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10094 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10095 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
10096 },
10097 {
10098 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10099 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
10100 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10101 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10102 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
10103 },
10104 {
10105 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10106 .info.subcmd =
10107 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
10108 .flags =
10109 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
10110 WIPHY_VENDOR_CMD_NEED_RUNNING,
10111 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
10112 },
10113 {
10114 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10115 .info.subcmd =
10116 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
10117 .flags =
10118 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
10119 WIPHY_VENDOR_CMD_NEED_RUNNING,
10120 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
10121 },
10122 {
10123 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10124 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
10125 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10126 WIPHY_VENDOR_CMD_NEED_NETDEV |
10127 WIPHY_VENDOR_CMD_NEED_RUNNING,
10128 .doit = wlan_hdd_cfg80211_set_epno_list
10129 },
10130#endif /* FEATURE_WLAN_EXTSCAN */
10131
10132#ifdef WLAN_FEATURE_LINK_LAYER_STATS
10133 {
10134 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10135 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
10136 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10137 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10138 .doit = wlan_hdd_cfg80211_ll_stats_clear
10139 },
10140
10141 {
10142 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10143 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
10144 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10145 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10146 .doit = wlan_hdd_cfg80211_ll_stats_set
10147 },
10148
10149 {
10150 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10151 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
10152 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10153 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10154 .doit = wlan_hdd_cfg80211_ll_stats_get
10155 },
10156#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
10157#ifdef FEATURE_WLAN_TDLS
10158 {
10159 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10160 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
10161 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10162 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10163 .doit = wlan_hdd_cfg80211_exttdls_enable
10164 },
10165 {
10166 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10167 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
10168 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10169 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
10170 .doit = wlan_hdd_cfg80211_exttdls_disable
10171 },
10172 {
10173 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10174 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
10175 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
10176 .doit = wlan_hdd_cfg80211_exttdls_get_status
10177 },
10178#endif
10179 {
10180 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10181 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
10182 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
10183 .doit = wlan_hdd_cfg80211_get_supported_features
10184 },
10185 {
10186 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10187 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010188 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10189 WIPHY_VENDOR_CMD_NEED_NETDEV |
10190 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010191 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
10192 },
10193 {
10194 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10195 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
10196 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +053010197 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010198 },
10199 {
10200 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10201 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
10202 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010203 WIPHY_VENDOR_CMD_NEED_NETDEV |
10204 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010205 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
10206 },
Manikandan Mohan80dea792016-04-28 16:36:48 -070010207 {
10208 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10209 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
10210 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010211 WIPHY_VENDOR_CMD_NEED_NETDEV |
10212 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -070010213 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
10214 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010215 {
10216 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +053010217 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
10218 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10219 WIPHY_VENDOR_CMD_NEED_NETDEV |
10220 WIPHY_VENDOR_CMD_NEED_RUNNING,
10221 .doit = hdd_cfg80211_get_station_cmd
10222 },
10223 {
10224 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010225 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
10226 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10227 WIPHY_VENDOR_CMD_NEED_NETDEV |
10228 WIPHY_VENDOR_CMD_NEED_RUNNING,
10229 .doit = wlan_hdd_cfg80211_do_acs
10230 },
10231
10232 {
10233 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10234 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
10235 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10236 WIPHY_VENDOR_CMD_NEED_NETDEV,
10237 .doit = wlan_hdd_cfg80211_get_features
10238 },
10239#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10240 {
10241 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10242 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
10243 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10244 WIPHY_VENDOR_CMD_NEED_NETDEV |
10245 WIPHY_VENDOR_CMD_NEED_RUNNING,
10246 .doit = wlan_hdd_cfg80211_keymgmt_set_key
10247 },
10248#endif
10249#ifdef FEATURE_WLAN_EXTSCAN
10250 {
10251 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10252 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
10253 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10254 WIPHY_VENDOR_CMD_NEED_NETDEV |
10255 WIPHY_VENDOR_CMD_NEED_RUNNING,
10256 .doit = wlan_hdd_cfg80211_set_passpoint_list
10257 },
10258 {
10259 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10260 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
10261 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10262 WIPHY_VENDOR_CMD_NEED_NETDEV |
10263 WIPHY_VENDOR_CMD_NEED_RUNNING,
10264 .doit = wlan_hdd_cfg80211_reset_passpoint_list
10265 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010266#endif /* FEATURE_WLAN_EXTSCAN */
10267 {
10268 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10269 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
10270 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10271 WIPHY_VENDOR_CMD_NEED_NETDEV,
10272 .doit = wlan_hdd_cfg80211_get_wifi_info
10273 },
Paul Zhang3a210c52016-12-08 10:18:12 +080010274#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010275 {
10276 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10277 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
10278 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10279 WIPHY_VENDOR_CMD_NEED_NETDEV |
10280 WIPHY_VENDOR_CMD_NEED_RUNNING,
10281 .doit = wlan_hdd_cfg80211_wifi_configuration_set
10282 },
Paul Zhang3a210c52016-12-08 10:18:12 +080010283#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010284 {
10285 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10286 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
10287 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010288 WIPHY_VENDOR_CMD_NEED_NETDEV |
10289 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010290 .doit = wlan_hdd_cfg80211_set_ext_roam_params
10291 },
10292 {
10293 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10294 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
10295 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010296 WIPHY_VENDOR_CMD_NEED_NETDEV |
10297 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010298 .doit = wlan_hdd_cfg80211_wifi_logger_start
10299 },
10300 {
10301 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10302 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
10303 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053010304 WIPHY_VENDOR_CMD_NEED_NETDEV |
10305 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010306 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
10307 },
10308 {
10309 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10310 .info.subcmd =
10311 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
10312 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10313 WIPHY_VENDOR_CMD_NEED_NETDEV |
10314 WIPHY_VENDOR_CMD_NEED_RUNNING,
10315 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
10316 },
10317 {
10318 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10319 .info.subcmd =
10320 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
10321 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10322 WIPHY_VENDOR_CMD_NEED_NETDEV |
10323 WIPHY_VENDOR_CMD_NEED_RUNNING,
10324 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
10325 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070010326#ifdef WLAN_FEATURE_TSF
10327 {
10328 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10329 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
10330 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10331 WIPHY_VENDOR_CMD_NEED_NETDEV |
10332 WIPHY_VENDOR_CMD_NEED_RUNNING,
10333 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
10334 },
10335#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010336#ifdef FEATURE_WLAN_TDLS
10337 {
10338 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10339 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
10340 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10341 WIPHY_VENDOR_CMD_NEED_NETDEV |
10342 WIPHY_VENDOR_CMD_NEED_RUNNING,
10343 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
10344 },
10345#endif
10346#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
10347 {
10348 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10349 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
10350 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10351 WIPHY_VENDOR_CMD_NEED_NETDEV |
10352 WIPHY_VENDOR_CMD_NEED_RUNNING,
10353 .doit = wlan_hdd_cfg80211_offloaded_packets
10354 },
10355#endif
10356 {
10357 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10358 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
10359 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10360 WIPHY_VENDOR_CMD_NEED_NETDEV |
10361 WIPHY_VENDOR_CMD_NEED_RUNNING,
10362 .doit = wlan_hdd_cfg80211_monitor_rssi
10363 },
10364 {
10365 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053010366 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
10367 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10368 WIPHY_VENDOR_CMD_NEED_NETDEV |
10369 WIPHY_VENDOR_CMD_NEED_RUNNING,
10370 .doit = wlan_hdd_cfg80211_set_ns_offload
10371 },
10372 {
10373 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010374 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
10375 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10376 WIPHY_VENDOR_CMD_NEED_NETDEV |
10377 WIPHY_VENDOR_CMD_NEED_RUNNING,
10378 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
10379 },
10380#ifdef WLAN_FEATURE_MEMDUMP
10381 {
10382 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10383 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
10384 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10385 WIPHY_VENDOR_CMD_NEED_NETDEV |
10386 WIPHY_VENDOR_CMD_NEED_RUNNING,
10387 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
10388 },
10389#endif /* WLAN_FEATURE_MEMDUMP */
10390 {
10391 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10392 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
10393 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10394 WIPHY_VENDOR_CMD_NEED_NETDEV |
10395 WIPHY_VENDOR_CMD_NEED_RUNNING,
10396 .doit = wlan_hdd_cfg80211_vendor_scan
10397 },
10398
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053010399 /* Vendor abort scan */
10400 {
10401 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10402 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
10403 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10404 WIPHY_VENDOR_CMD_NEED_NETDEV |
10405 WIPHY_VENDOR_CMD_NEED_RUNNING,
10406 .doit = wlan_hdd_vendor_abort_scan
10407 },
10408
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010409 /* OCB commands */
10410 {
10411 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10412 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
10413 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10414 WIPHY_VENDOR_CMD_NEED_NETDEV |
10415 WIPHY_VENDOR_CMD_NEED_RUNNING,
10416 .doit = wlan_hdd_cfg80211_ocb_set_config
10417 },
10418 {
10419 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10420 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
10421 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10422 WIPHY_VENDOR_CMD_NEED_NETDEV |
10423 WIPHY_VENDOR_CMD_NEED_RUNNING,
10424 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
10425 },
10426 {
10427 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10428 .info.subcmd =
10429 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
10430 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10431 WIPHY_VENDOR_CMD_NEED_NETDEV |
10432 WIPHY_VENDOR_CMD_NEED_RUNNING,
10433 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
10434 },
10435 {
10436 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10437 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
10438 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10439 WIPHY_VENDOR_CMD_NEED_NETDEV |
10440 WIPHY_VENDOR_CMD_NEED_RUNNING,
10441 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
10442 },
10443 {
10444 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10445 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
10446 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10447 WIPHY_VENDOR_CMD_NEED_NETDEV |
10448 WIPHY_VENDOR_CMD_NEED_RUNNING,
10449 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
10450 },
10451 {
10452 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10453 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
10454 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10455 WIPHY_VENDOR_CMD_NEED_NETDEV |
10456 WIPHY_VENDOR_CMD_NEED_RUNNING,
10457 .doit = wlan_hdd_cfg80211_dcc_get_stats
10458 },
10459 {
10460 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10461 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
10462 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10463 WIPHY_VENDOR_CMD_NEED_NETDEV |
10464 WIPHY_VENDOR_CMD_NEED_RUNNING,
10465 .doit = wlan_hdd_cfg80211_dcc_clear_stats
10466 },
10467 {
10468 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10469 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
10470 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10471 WIPHY_VENDOR_CMD_NEED_NETDEV |
10472 WIPHY_VENDOR_CMD_NEED_RUNNING,
10473 .doit = wlan_hdd_cfg80211_dcc_update_ndl
10474 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053010475 {
10476 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10477 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
10478 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10479 WIPHY_VENDOR_CMD_NEED_NETDEV |
10480 WIPHY_VENDOR_CMD_NEED_RUNNING,
10481 .doit = wlan_hdd_cfg80211_get_link_properties
10482 },
Peng Xu278d0122015-09-24 16:34:17 -070010483 {
Peng Xud2220962016-07-11 17:59:17 -070010484 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -070010485 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
10486 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10487 WIPHY_VENDOR_CMD_NEED_NETDEV |
10488 WIPHY_VENDOR_CMD_NEED_RUNNING,
10489 .doit = wlan_hdd_cfg80211_set_ota_test
10490 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -080010491#ifdef FEATURE_LFR_SUBNET_DETECTION
10492 {
10493 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10494 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
10495 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10496 WIPHY_VENDOR_CMD_NEED_NETDEV |
10497 WIPHY_VENDOR_CMD_NEED_RUNNING,
10498 .doit = wlan_hdd_cfg80211_set_gateway_params
10499 },
10500#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -070010501 {
Peng Xud2220962016-07-11 17:59:17 -070010502 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -070010503 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
10504 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10505 WIPHY_VENDOR_CMD_NEED_NETDEV |
10506 WIPHY_VENDOR_CMD_NEED_RUNNING,
10507 .doit = wlan_hdd_cfg80211_txpower_scale
10508 },
10509 {
10510 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10511 .info.subcmd =
10512 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
10513 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10514 WIPHY_VENDOR_CMD_NEED_NETDEV |
10515 WIPHY_VENDOR_CMD_NEED_RUNNING,
10516 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
10517 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +053010518 {
10519 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10520 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
10521 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10522 WIPHY_VENDOR_CMD_NEED_NETDEV |
10523 WIPHY_VENDOR_CMD_NEED_RUNNING,
10524 .doit = wlan_hdd_cfg80211_bpf_offload
10525 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010526 {
10527 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053010528 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
10529 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10530 WIPHY_VENDOR_CMD_NEED_NETDEV |
10531 WIPHY_VENDOR_CMD_NEED_RUNNING,
10532 .doit = wlan_hdd_cfg80211_acs_dfs_mode
10533 },
10534 {
10535 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010536 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
10537 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10538 WIPHY_VENDOR_CMD_NEED_NETDEV |
10539 WIPHY_VENDOR_CMD_NEED_RUNNING,
10540 .doit = wlan_hdd_cfg80211_sta_roam_policy
10541 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053010542#ifdef FEATURE_WLAN_CH_AVOID
10543 {
10544 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10545 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
10546 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10547 WIPHY_VENDOR_CMD_NEED_NETDEV |
10548 WIPHY_VENDOR_CMD_NEED_RUNNING,
10549 .doit = wlan_hdd_cfg80211_avoid_freq
10550 },
10551#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010552 {
10553 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010554 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
10555 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10556 WIPHY_VENDOR_CMD_NEED_NETDEV |
10557 WIPHY_VENDOR_CMD_NEED_RUNNING,
10558 .doit = wlan_hdd_cfg80211_sap_configuration_set
10559 },
Peng Xu8fdaa492016-06-22 10:20:47 -070010560 {
Peng Xu4225c152016-07-14 21:18:14 -070010561 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070010562 .info.subcmd =
10563 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
10564 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10565 WIPHY_VENDOR_CMD_NEED_NETDEV |
10566 WIPHY_VENDOR_CMD_NEED_RUNNING,
10567 .doit = wlan_hdd_cfg80211_p2p_lo_start
10568 },
10569 {
10570 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10571 .info.subcmd =
10572 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
10573 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10574 WIPHY_VENDOR_CMD_NEED_NETDEV |
10575 WIPHY_VENDOR_CMD_NEED_RUNNING,
10576 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10577 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010578 {
10579 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10580 .info.subcmd =
10581 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10582 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10583 WIPHY_VENDOR_CMD_NEED_NETDEV |
10584 WIPHY_VENDOR_CMD_NEED_RUNNING,
10585 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10586 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010587#ifdef WLAN_FEATURE_NAN_DATAPATH
10588 {
10589 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10590 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10591 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10592 WIPHY_VENDOR_CMD_NEED_NETDEV |
10593 WIPHY_VENDOR_CMD_NEED_RUNNING,
10594 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10595 },
10596#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010597 {
10598 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10599 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10600 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10601 WIPHY_VENDOR_CMD_NEED_NETDEV |
10602 WIPHY_VENDOR_CMD_NEED_RUNNING,
10603 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10604 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010605 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010606 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10607 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10608 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10609 WIPHY_VENDOR_CMD_NEED_NETDEV |
10610 WIPHY_VENDOR_CMD_NEED_RUNNING,
10611 .doit = wlan_hdd_cfg80211_get_bus_size
10612 },
10613 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010614 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10615 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10616 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10617 WIPHY_VENDOR_CMD_NEED_NETDEV |
10618 WIPHY_VENDOR_CMD_NEED_RUNNING,
10619 .doit = wlan_hdd_cfg80211_update_vendor_channel
10620 },
10621 {
bingsd09dea32017-03-17 10:08:26 +080010622 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010623 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10624 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10625 WIPHY_VENDOR_CMD_NEED_NETDEV |
10626 WIPHY_VENDOR_CMD_NEED_RUNNING,
10627 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010628 },
10629 {
10630 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10631 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10632 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10633 WIPHY_VENDOR_CMD_NEED_NETDEV |
10634 WIPHY_VENDOR_CMD_NEED_RUNNING,
10635 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010636 },
10637#ifdef WLAN_FEATURE_DISA
10638 {
10639 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10640 .info.subcmd =
10641 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10642 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10643 WIPHY_VENDOR_CMD_NEED_NETDEV |
10644 WIPHY_VENDOR_CMD_NEED_RUNNING,
10645 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10646 },
10647#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010648#ifdef FEATURE_WLAN_TDLS
10649 {
10650 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10651 .info.subcmd =
10652 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10653 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10654 WIPHY_VENDOR_CMD_NEED_NETDEV |
10655 WIPHY_VENDOR_CMD_NEED_RUNNING,
10656 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010657 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010658#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010659 {
10660 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10661 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10662 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10663 WIPHY_VENDOR_CMD_NEED_RUNNING,
10664 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10665 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010666 {
10667 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10668 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10669 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10670 WIPHY_VENDOR_CMD_NEED_NETDEV |
10671 WIPHY_VENDOR_CMD_NEED_RUNNING,
10672 .doit = wlan_hdd_cfg80211_set_trace_level
10673 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080010674 {
10675 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10676 .info.subcmd =
10677 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
10678 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10679 WIPHY_VENDOR_CMD_NEED_NETDEV |
10680 WIPHY_VENDOR_CMD_NEED_RUNNING,
10681 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
10682 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010683
Paul Zhang3a210c52016-12-08 10:18:12 +080010684#ifdef WLAN_UMAC_CONVERGENCE
10685 COMMON_VENDOR_COMMANDS
10686#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010687 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010688};
10689
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010690#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10691 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10692 defined(FEATURE_WLAN_SCAN_PNO)
10693/**
10694 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10695 * @wiphy: pointer to wiphy
10696 * @config: pointer to config
10697 *
10698 * Return: None
10699 */
10700static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10701 struct hdd_config *config)
10702{
10703 if (config->configPNOScanSupport) {
10704 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010705 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10706 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010707 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010708 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010709 if (config->max_sched_scan_plan_interval)
10710 wiphy->max_sched_scan_plan_interval =
10711 config->max_sched_scan_plan_interval;
10712 if (config->max_sched_scan_plan_iterations)
10713 wiphy->max_sched_scan_plan_iterations =
10714 config->max_sched_scan_plan_iterations;
10715 }
10716}
10717#else
10718static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10719 struct hdd_config *config)
10720{
10721}
10722#endif
10723
10724
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010725/**
10726 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10727 * @priv_size: Size of the hdd context.
10728 *
10729 * Allocate wiphy context and hdd context.
10730 *
10731 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010732 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010733hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010734{
10735 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010736 hdd_context_t *hdd_ctx;
10737
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010738 ENTER();
10739
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010740 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10741
10742 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010743 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010744 return NULL;
10745 }
10746
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010747 hdd_ctx = wiphy_priv(wiphy);
10748
10749 hdd_ctx->wiphy = wiphy;
10750
10751 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010752}
10753
10754/*
10755 * FUNCTION: wlan_hdd_cfg80211_update_band
10756 * This function is called from the supplicant through a
10757 * private ioctl to change the band value
10758 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010759int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10760 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010761{
10762 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010763 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010764
10765 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010766 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010767
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010768 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010769 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010770
10771 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10772 struct ieee80211_supported_band *band = wiphy->bands[i];
10773
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010774 channelEnabledState = wlan_reg_get_channel_state(
10775 hdd_ctx->hdd_pdev,
10776 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010777
Dustin Browna30892e2016-10-12 17:28:36 -070010778 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010779 /* 5G only */
10780#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10781 /* Enable Social channels for P2P */
10782 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10783 (band->channels[j].center_freq)
10784 && CHANNEL_STATE_ENABLE ==
10785 channelEnabledState)
10786 band->channels[j].flags &=
10787 ~IEEE80211_CHAN_DISABLED;
10788 else
10789#endif
10790 band->channels[j].flags |=
10791 IEEE80211_CHAN_DISABLED;
10792 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010793 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010794 eCSR_BAND_24 == eBand) {
10795 /* 2G only */
10796 band->channels[j].flags |=
10797 IEEE80211_CHAN_DISABLED;
10798 continue;
10799 }
10800
Amar Singhal6842e8f2016-02-23 16:30:32 -080010801 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010802 band->channels[j].flags &=
10803 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010804 }
10805 }
10806 return 0;
10807}
10808
Peng Xuacfdda12017-02-06 16:15:38 -080010809#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010810/*
10811 * FUNCTION: wlan_hdd_cfg80211_init
10812 * This function is called by hdd_wlan_startup()
10813 * during initialization.
10814 * This function is used to initialize and register wiphy structure.
10815 */
10816int wlan_hdd_cfg80211_init(struct device *dev,
10817 struct wiphy *wiphy, struct hdd_config *pCfg)
10818{
10819 int i, j;
10820 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10821
10822 ENTER();
10823
10824 /* Now bind the underlying wlan device with wiphy */
10825 set_wiphy_dev(wiphy, dev);
10826
10827 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10828
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010829 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10830 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10831 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10832#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10833 | WIPHY_FLAG_4ADDR_STATION
10834#endif
10835 | WIPHY_FLAG_OFFCHAN_TX;
10836
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010837#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10838 wiphy->wowlan = &wowlan_support_cfg80211_init;
10839#else
10840 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10841 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10842 wiphy->wowlan.pattern_min_len = 1;
10843 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10844#endif
10845
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010846 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010847#ifdef FEATURE_WLAN_ESE
10848 || pCfg->isEseIniFeatureEnabled
10849#endif
10850 ) {
10851 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10852 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010853#ifdef FEATURE_WLAN_TDLS
10854 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10855 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10856#endif
10857
10858 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10859
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010860#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10861 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10862#endif
10863
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010864 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010865
10866#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010867 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010868#endif
10869
10870 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010871 * driver can still register regulatory callback and
10872 * it will get regulatory settings in wiphy->band[], but
10873 * driver need to determine what to do with both
10874 * regulatory settings
10875 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010876
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010877#if defined QCA_WIFI_FTM
10878}
10879#endif
10880
10881 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10882
10883 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10884
10885 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10886
Arun Khandavallifae92942016-08-01 13:31:08 +053010887 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10888 | BIT(NL80211_IFTYPE_ADHOC)
10889 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10890 | BIT(NL80211_IFTYPE_P2P_GO)
10891 | BIT(NL80211_IFTYPE_AP)
10892 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010893
Arun Khandavallifae92942016-08-01 13:31:08 +053010894 if (pCfg->advertiseConcurrentOperation) {
10895 if (pCfg->enableMCC) {
10896 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010897
Arun Khandavallifae92942016-08-01 13:31:08 +053010898 for (i = 0;
10899 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10900 i++) {
10901 if (!pCfg->allowMCCGODiffBI)
10902 wlan_hdd_iface_combination[i].
10903 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010904 }
10905 }
10906 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010907 ARRAY_SIZE(wlan_hdd_iface_combination);
10908 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010909 }
10910
10911 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010912 * on ini values
10913 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010914 if (!pCfg->ShortGI20MhzEnable) {
10915 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10916 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010917 }
10918
10919 if (!pCfg->ShortGI40MhzEnable) {
10920 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10921 }
10922
10923 if (!pCfg->nChannelBondingMode5GHz) {
10924 wlan_hdd_band_5_ghz.ht_cap.cap &=
10925 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10926 }
10927
Abhishek Singhf512bf32016-05-04 16:47:46 +053010928 /*
10929 * In case of static linked driver at the time of driver unload,
10930 * module exit doesn't happens. Module cleanup helps in cleaning
10931 * of static memory.
10932 * If driver load happens statically, at the time of driver unload,
10933 * wiphy flags don't get reset because of static memory.
10934 * It's better not to store channel in static memory.
10935 */
Dustin Browna30892e2016-10-12 17:28:36 -070010936 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10937 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010938 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010939 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010940 hdd_err("Not enough memory to allocate channels");
10941 return -ENOMEM;
10942 }
Dustin Browna30892e2016-10-12 17:28:36 -070010943 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010944 &hdd_channels_2_4_ghz[0],
10945 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010946 if ((hdd_is_5g_supported(pHddCtx)) &&
10947 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10948 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10949 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10950 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010951 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10952 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010953 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010954 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010955 hdd_err("Not enough memory to allocate channels");
10956 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010957 bands[NL80211_BAND_2GHZ]->channels);
10958 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010959 return -ENOMEM;
10960 }
Dustin Browna30892e2016-10-12 17:28:36 -070010961 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010962 &hdd_channels_5_ghz[0],
10963 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010964 }
10965
Dustin Browna30892e2016-10-12 17:28:36 -070010966 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010967
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010968 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010969 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010970
10971 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10972 struct ieee80211_supported_band *band = wiphy->bands[i];
10973
Dustin Browna30892e2016-10-12 17:28:36 -070010974 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010975 eCSR_BAND_5G == pCfg->nBandCapability) {
10976 /* 5G only */
10977#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10978 /* Enable social channels for P2P */
10979 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10980 (band->channels[j].center_freq))
10981 band->channels[j].flags &=
10982 ~IEEE80211_CHAN_DISABLED;
10983 else
10984#endif
10985 band->channels[j].flags |=
10986 IEEE80211_CHAN_DISABLED;
10987 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010988 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010989 eCSR_BAND_24 == pCfg->nBandCapability) {
10990 /* 2G only */
10991 band->channels[j].flags |=
10992 IEEE80211_CHAN_DISABLED;
10993 continue;
10994 }
10995 }
10996 }
10997 /*Initialise the supported cipher suite details */
10998 wiphy->cipher_suites = hdd_cipher_suites;
10999 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
11000
11001 /*signal strength in mBm (100*dBm) */
11002 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
11003 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
11004
Anurag Chouhan6d760662016-02-20 16:05:43 +053011005 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011006 wiphy->n_vendor_commands =
11007 ARRAY_SIZE(hdd_wiphy_vendor_commands);
11008 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
11009
11010 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
11011 wiphy->n_vendor_events =
11012 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
11013 }
11014
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011015 if (pCfg->enableDFSMasterCap) {
11016 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
11017 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011018
11019 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
11020
11021#ifdef QCA_HT_2040_COEX
11022 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
11023#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053011024 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080011025
11026#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
11027 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
11028 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
11029 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
11030 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
11031#endif
11032
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011033 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080011034 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053011035
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011036 EXIT();
11037 return 0;
11038}
11039
Abhishek Singhf512bf32016-05-04 16:47:46 +053011040/**
Yingying Tang80e15f32016-09-27 18:23:01 +080011041 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
11042 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053011043 *
11044 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053011045 * memory allocated in wlan_hdd_cfg80211_init also
11046 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053011047 *
11048 * Return: void
11049 */
11050void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
11051{
11052 int i;
11053
Dustin Browna30892e2016-10-12 17:28:36 -070011054 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053011055 if (NULL != wiphy->bands[i] &&
11056 (NULL != wiphy->bands[i]->channels)) {
11057 qdf_mem_free(wiphy->bands[i]->channels);
11058 wiphy->bands[i]->channels = NULL;
11059 }
11060 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080011061
Abhishek Singh3e6172f2016-05-04 16:56:48 +053011062 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053011063}
11064
Yingying Tang80e15f32016-09-27 18:23:01 +080011065/**
11066 * wlan_hdd_update_band_cap() - update capabilities for supported bands
11067 * @hdd_ctx: HDD context
11068 *
11069 * this function will update capabilities for supported bands
11070 *
11071 * Return: void
11072 */
11073static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
11074{
11075 uint32_t val32;
11076 uint16_t val16;
11077 tSirMacHTCapabilityInfo *ht_cap_info;
11078 QDF_STATUS status;
11079
11080 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
11081 if (QDF_STATUS_SUCCESS != status) {
11082 hdd_err("could not get HT capability info");
11083 val32 = 0;
11084 }
11085 val16 = (uint16_t)val32;
11086 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
11087
11088 if (ht_cap_info->txSTBC == true) {
11089 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
11090 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
11091 IEEE80211_HT_CAP_TX_STBC;
11092 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
11093 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
11094 IEEE80211_HT_CAP_TX_STBC;
11095 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080011096
11097 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
11098 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
11099 vht_cap.vht_supported = 0;
11100 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
11101 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
11102 vht_cap.vht_supported = 0;
11103 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
11104 }
Yingying Tang80e15f32016-09-27 18:23:01 +080011105}
11106
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011107/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011108 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011109 * initialization. In wlan_hdd_cfg80211_init, only the
11110 * default values will be initialized. The final initialization
11111 * of all required members can be done here.
11112 */
Yingying Tang80e15f32016-09-27 18:23:01 +080011113void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011114{
Yingying Tang80e15f32016-09-27 18:23:01 +080011115 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
11116
11117 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011118}
11119
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080011120/**
11121 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
11122 * @cfg: hdd cfg
11123 *
11124 * this function update 11n mode in hdd cfg
11125 *
11126 * Return: void
11127 */
11128void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
11129{
11130 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011131 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080011132 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011133 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080011134 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
11135 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
11136 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
11137 cfg->sap_p2p_11ac_override = 0;
11138 }
11139 }
11140}
11141
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011142/* In this function we are registering wiphy. */
11143int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
11144{
11145 ENTER();
11146 /* Register our wiphy dev with cfg80211 */
11147 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011148 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011149 return -EIO;
11150 }
11151
11152 EXIT();
11153 return 0;
11154}
11155
11156/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011157 * HDD function to update wiphy capability based on target offload status.
11158 *
11159 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
11160 * capability even before downloading firmware to the target. In discrete
11161 * case, host will get know certain offload capability (say sched_scan
11162 * caps) only after downloading firmware to the target and target boots up.
11163 * This function is used to override setting done in wlan_hdd_cfg80211_init()
11164 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011165 */
11166void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
11167{
11168#ifdef FEATURE_WLAN_SCAN_PNO
11169 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
11170 struct hdd_config *pCfg = pHddCtx->config;
11171
11172 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
11173 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011174 * have PNO support.
11175 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011176 if (!pCfg->PnoOffload) {
11177 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
11178 wiphy->max_sched_scan_ssids = 0;
11179 wiphy->max_match_sets = 0;
11180 wiphy->max_sched_scan_ie_len = 0;
11181 }
11182#endif
11183}
11184
11185/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011186#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
11187
Wu Gao84d120c2017-03-24 18:46:00 +080011188void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
11189{
11190 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11191 /* Register for all P2P action, public action etc frames */
11192 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
11193
11194 ENTER();
11195
11196 /* Register frame indication call back */
11197 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
11198
11199 /* Register for p2p ack indication */
11200 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
11201
11202 /* Right now we are registering these frame when driver is getting
11203 * initialized. Once we will move to 2.6.37 kernel, in which we have
11204 * frame register ops, we will move this code as a part of that
11205 */
11206
11207 /* GAS Initial Request */
11208 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11209 (uint8_t *) GAS_INITIAL_REQ,
11210 GAS_INITIAL_REQ_SIZE);
11211
11212 /* GAS Initial Response */
11213 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11214 (uint8_t *) GAS_INITIAL_RSP,
11215 GAS_INITIAL_RSP_SIZE);
11216
11217 /* GAS Comeback Request */
11218 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11219 (uint8_t *) GAS_COMEBACK_REQ,
11220 GAS_COMEBACK_REQ_SIZE);
11221
11222 /* GAS Comeback Response */
11223 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11224 (uint8_t *) GAS_COMEBACK_RSP,
11225 GAS_COMEBACK_RSP_SIZE);
11226
11227 /* WNM BSS Transition Request frame */
11228 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11229 (uint8_t *) WNM_BSS_ACTION_FRAME,
11230 WNM_BSS_ACTION_FRAME_SIZE);
11231
11232 /* WNM-Notification */
11233 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
11234 (uint8_t *) WNM_NOTIFICATION_FRAME,
11235 WNM_NOTIFICATION_FRAME_SIZE);
11236}
11237#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
11239{
11240 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11241 /* Register for all P2P action, public action etc frames */
11242 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
11243
11244 ENTER();
11245
Abhishek Singh7996eb72015-12-30 17:24:02 +053011246 /* Register frame indication call back */
11247 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
11248
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053011249 /* Register for p2p ack indication */
11250 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
11251
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011252 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011253 * initialized. Once we will move to 2.6.37 kernel, in which we have
11254 * frame register ops, we will move this code as a part of that
11255 */
11256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011257 /* GAS Initial Request */
11258 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11259 (uint8_t *) GAS_INITIAL_REQ,
11260 GAS_INITIAL_REQ_SIZE);
11261
11262 /* GAS Initial Response */
11263 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11264 (uint8_t *) GAS_INITIAL_RSP,
11265 GAS_INITIAL_RSP_SIZE);
11266
11267 /* GAS Comeback Request */
11268 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11269 (uint8_t *) GAS_COMEBACK_REQ,
11270 GAS_COMEBACK_REQ_SIZE);
11271
11272 /* GAS Comeback Response */
11273 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11274 (uint8_t *) GAS_COMEBACK_RSP,
11275 GAS_COMEBACK_RSP_SIZE);
11276
11277 /* P2P Public Action */
11278 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11279 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
11280 P2P_PUBLIC_ACTION_FRAME_SIZE);
11281
11282 /* P2P Action */
11283 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11284 (uint8_t *) P2P_ACTION_FRAME,
11285 P2P_ACTION_FRAME_SIZE);
11286
11287 /* WNM BSS Transition Request frame */
11288 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11289 (uint8_t *) WNM_BSS_ACTION_FRAME,
11290 WNM_BSS_ACTION_FRAME_SIZE);
11291
11292 /* WNM-Notification */
11293 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
11294 (uint8_t *) WNM_NOTIFICATION_FRAME,
11295 WNM_NOTIFICATION_FRAME_SIZE);
11296}
Wu Gao84d120c2017-03-24 18:46:00 +080011297#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011298
11299void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
11300{
11301 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11302 /* Register for all P2P action, public action etc frames */
11303 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
11304
11305 ENTER();
11306
11307 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011308 * initialized. Once we will move to 2.6.37 kernel, in which we have
11309 * frame register ops, we will move this code as a part of that
11310 */
11311
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011312 /* GAS Initial Request */
11313
11314 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11315 (uint8_t *) GAS_INITIAL_REQ,
11316 GAS_INITIAL_REQ_SIZE);
11317
11318 /* GAS Initial Response */
11319 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11320 (uint8_t *) GAS_INITIAL_RSP,
11321 GAS_INITIAL_RSP_SIZE);
11322
11323 /* GAS Comeback Request */
11324 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11325 (uint8_t *) GAS_COMEBACK_REQ,
11326 GAS_COMEBACK_REQ_SIZE);
11327
11328 /* GAS Comeback Response */
11329 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11330 (uint8_t *) GAS_COMEBACK_RSP,
11331 GAS_COMEBACK_RSP_SIZE);
11332
11333 /* P2P Public Action */
11334 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11335 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
11336 P2P_PUBLIC_ACTION_FRAME_SIZE);
11337
11338 /* P2P Action */
11339 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
11340 (uint8_t *) P2P_ACTION_FRAME,
11341 P2P_ACTION_FRAME_SIZE);
11342
11343 /* WNM-Notification */
11344 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
11345 (uint8_t *) WNM_NOTIFICATION_FRAME,
11346 WNM_NOTIFICATION_FRAME_SIZE);
11347}
11348
11349#ifdef FEATURE_WLAN_WAPI
11350void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
11351 const uint8_t *mac_addr, const uint8_t *key,
11352 int key_Len)
11353{
11354 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11355 tCsrRoamSetKey setKey;
11356 bool isConnected = true;
11357 int status = 0;
11358 uint32_t roamId = 0xFF;
11359 uint8_t *pKeyPtr = NULL;
11360 int n = 0;
11361
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011362 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011363 hdd_device_mode_to_string(pAdapter->device_mode),
11364 pAdapter->device_mode);
11365
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011366 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011367 setKey.keyId = key_index; /* Store Key ID */
11368 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
11369 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
11370 setKey.paeRole = 0; /* the PAE role */
11371 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053011372 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011373 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011374 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011375 }
11376 setKey.keyLength = key_Len;
11377 pKeyPtr = setKey.Key;
11378 memcpy(pKeyPtr, key, key_Len);
11379
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011380 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011381 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011382 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070011383 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011384
11385 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11386 if (isConnected) {
11387 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11388 pAdapter->sessionId, &setKey, &roamId);
11389 }
11390 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011391 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011392 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
11393 }
11394}
11395#endif /* FEATURE_WLAN_WAPI */
11396
11397uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
11398 uint8_t eid)
11399{
11400 int left = length;
11401 uint8_t *ptr = (uint8_t *)ies_ptr;
11402 uint8_t elem_id, elem_len;
11403
11404 while (left >= 2) {
11405 elem_id = ptr[0];
11406 elem_len = ptr[1];
11407 left -= 2;
11408 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011409 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011410 eid, elem_len, left);
11411 return NULL;
11412 }
11413 if (elem_id == eid) {
11414 return ptr;
11415 }
11416
11417 left -= elem_len;
11418 ptr += (elem_len + 2);
11419 }
11420 return NULL;
11421}
11422
Krunal Soni364e0872017-05-10 21:24:34 -070011423bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
11424{
11425 uint8_t *vendor_ie;
11426
11427 if (length < 2) {
11428 hdd_debug("bss size is less than expected");
11429 return true;
11430 }
11431 if (!ies) {
11432 hdd_debug("invalid IE pointer");
11433 return true;
11434 }
11435 vendor_ie = wlan_hdd_get_vendor_oui_ie_ptr(VENDOR1_AP_OUI_TYPE,
11436 VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
11437 if (vendor_ie) {
11438 hdd_debug("AP can't support immediate powersave. defer it");
11439 return false;
11440 }
11441 return true;
11442}
11443
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011444/*
11445 * FUNCTION: wlan_hdd_validate_operation_channel
11446 * called by wlan_hdd_cfg80211_start_bss() and
11447 * wlan_hdd_set_channel()
11448 * This function validates whether given channel is part of valid
11449 * channel list.
11450 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011451QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011452 int channel)
11453{
11454
11455 uint32_t num_ch = 0;
11456 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
11457 u32 indx = 0;
11458 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11459 uint8_t fValidChannel = false, count = 0;
11460 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
11461
11462 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
11463
11464 if (hdd_pConfig_ini->sapAllowAllChannel) {
11465 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080011466 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070011467 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011468 fValidChannel = true;
11469 break;
11470 }
11471 }
11472 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011473 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011474 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011475 }
11476 } else {
11477 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
11478 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011479 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011480 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011481 }
11482 for (indx = 0; indx < num_ch; indx++) {
11483 if (channel == valid_ch[indx]) {
11484 break;
11485 }
11486 }
11487
11488 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011489 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011490 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011491 }
11492 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011493 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011494
11495}
11496
11497#ifdef DHCP_SERVER_OFFLOAD
11498static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
11499{
11500 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
11501 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
11502 uint8_t numEntries = 0;
11503 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
11504 uint8_t num;
11505 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011506 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011507 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070011508 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011509 return;
11510 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011511 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
11512 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
11513 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
11514 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
11515 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
11516 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011517 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011518 goto end;
11519 }
11520 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011521 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011522 goto end;
11523 }
11524 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011525 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011526 goto end;
11527 }
11528 for (num = 0; num < numEntries; num++) {
11529 temp = srv_ip[num];
11530 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
11531 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011532 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011533 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011534 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011535 goto end;
11536 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011537 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011538end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011539 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011540 return;
11541}
11542#endif /* DHCP_SERVER_OFFLOAD */
11543
11544static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11545 struct net_device *dev,
11546 struct bss_parameters *params)
11547{
11548 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11549 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11550 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011551 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011552
11553 ENTER();
11554
Anurag Chouhan6d760662016-02-20 16:05:43 +053011555 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011556 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011557 return -EINVAL;
11558 }
11559
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011560 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11561 hdd_err("invalid session id: %d", pAdapter->sessionId);
11562 return -EINVAL;
11563 }
11564
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011565 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011566 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
11567 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011568 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011569 hdd_device_mode_to_string(pAdapter->device_mode),
11570 pAdapter->device_mode, params->ap_isolate);
11571
11572 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11573 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011574 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011575 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011576
Krunal Sonib4326f22016-03-10 13:05:51 -080011577 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
11578 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011579 return -EOPNOTSUPP;
11580 }
11581
11582 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011583 * want to update this parameter
11584 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011585 if (-1 != params->ap_isolate) {
11586 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
11587 !!params->ap_isolate;
11588
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011589 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011590 pAdapter->sessionId,
11591 pAdapter->sessionCtx.
11592 ap.
11593 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011594 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011595 ret = -EINVAL;
11596 }
11597 }
11598
11599 EXIT();
11600 return ret;
11601}
11602
Krunal Soni8c37e322016-02-03 16:08:37 -080011603/**
11604 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
11605 * @ndev: pointer to net device provided by supplicant
11606 * @type: type of the interface, upper layer wanted to change
11607 *
11608 * Upper layer provides the new interface mode that needs to be changed
11609 * for given net device
11610 *
11611 * Return: success or failure in terms of integer value
11612 */
11613static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011614 enum nl80211_iftype type)
11615{
Krunal Soni8c37e322016-02-03 16:08:37 -080011616 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11617 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11618 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011619 hdd_wext_state_t *wext;
11620 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011621 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011622
11623 ENTER();
11624
Krunal Soni8c37e322016-02-03 16:08:37 -080011625 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011626 hdd_warn("ACS is in progress, don't change iface!");
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011627 return -EBUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011628 }
11629
11630 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011631 hdd_stop_adapter(hdd_ctx, adapter, true);
11632 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011633 wdev->iftype = type;
11634 /*Check for sub-string p2p to confirm its a p2p interface */
11635 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011636 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011637 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011638 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011639 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011640 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011642 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011643 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011644 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011645 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011646 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11647 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011648 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11649 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011650 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011651 adapter->scan_info.scanAddIE.length;
11652 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011653 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011654 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11655 wext->roamProfile.phyMode =
11656 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11657 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658 EXIT();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011659
11660 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011661}
11662
11663static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11664 struct net_device *dev,
11665 struct bss_parameters *params)
11666{
11667 int ret;
11668
11669 cds_ssr_protect(__func__);
11670 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11671 cds_ssr_unprotect(__func__);
11672
11673 return ret;
11674}
11675
11676/* FUNCTION: wlan_hdd_change_country_code_cd
11677 * to wait for contry code completion
11678 */
11679void *wlan_hdd_change_country_code_cb(void *pAdapter)
11680{
11681 hdd_adapter_t *call_back_pAdapter = pAdapter;
11682 complete(&call_back_pAdapter->change_country_code);
11683 return NULL;
11684}
11685
Rajeev Kumar98edb772016-01-19 12:42:19 -080011686/**
11687 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11688 * @wiphy: Pointer to the wiphy structure
11689 * @ndev: Pointer to the net device
11690 * @type: Interface type
11691 * @flags: Flags for change interface
11692 * @params: Pointer to change interface parameters
11693 *
11694 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011695 */
11696static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11697 struct net_device *ndev,
11698 enum nl80211_iftype type,
11699 u32 *flags,
11700 struct vif_params *params)
11701{
11702 struct wireless_dev *wdev;
11703 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11704 hdd_context_t *pHddCtx;
11705 tCsrRoamProfile *pRoamProfile = NULL;
11706 eCsrRoamBssType LastBSSType;
11707 struct hdd_config *pConfig = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011708 int status;
11709
11710 ENTER();
11711
Anurag Chouhan6d760662016-02-20 16:05:43 +053011712 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011713 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011714 return -EINVAL;
11715 }
11716
11717 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11718 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011719 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011720 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011721
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011722 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011723 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11724 pAdapter->sessionId, type));
11725
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011726 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011727 pAdapter->device_mode, type);
11728
Arun Khandavallifae92942016-08-01 13:31:08 +053011729 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11730 if (status) {
11731 hdd_err("Failed to start modules");
11732 return -EINVAL;
11733 }
11734
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011735 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011736 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11737 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011738 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011739 return -EINVAL;
11740 }
11741
11742 pConfig = pHddCtx->config;
11743 wdev = ndev->ieee80211_ptr;
11744
11745 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011746 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11747 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011748
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011749 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011750 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011751 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11752 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11753 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11754 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011755 hdd_wext_state_t *pWextState =
11756 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11757
11758 pRoamProfile = &pWextState->roamProfile;
11759 LastBSSType = pRoamProfile->BSSType;
11760
11761 switch (type) {
11762 case NL80211_IFTYPE_STATION:
11763 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011764 case NL80211_IFTYPE_ADHOC:
11765 if (type == NL80211_IFTYPE_ADHOC) {
11766 wlan_hdd_tdls_exit(pAdapter);
11767 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011768 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011769 }
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011770 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
Krunal Soni8c37e322016-02-03 16:08:37 -080011771 type);
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070011772 if (status) {
11773 hdd_err("Failed to change iface to new mode:%d status %d",
11774 type, status);
11775 return status;
11776 }
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011777 if (hdd_start_adapter(pAdapter)) {
11778 hdd_err("Failed to start adapter :%d",
11779 pAdapter->device_mode);
11780 return -EINVAL;
11781 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011782 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011783 case NL80211_IFTYPE_AP:
11784 case NL80211_IFTYPE_P2P_GO:
11785 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011786 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011787 (type ==
11788 NL80211_IFTYPE_AP) ? "SoftAP" :
11789 "P2pGo");
11790
11791 /* Cancel any remain on channel for GO mode */
11792 if (NL80211_IFTYPE_P2P_GO == type) {
11793 wlan_hdd_cancel_existing_remain_on_channel
11794 (pAdapter);
11795 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011796
Arun Khandavallifae92942016-08-01 13:31:08 +053011797 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011798 /* De-init the adapter */
11799 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11800 memset(&pAdapter->sessionCtx, 0,
11801 sizeof(pAdapter->sessionCtx));
11802 pAdapter->device_mode =
11803 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011804 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11805 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011806
11807 /*
11808 * Fw will take care incase of concurrency
11809 */
11810
Krunal Sonib4326f22016-03-10 13:05:51 -080011811 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011812 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011813 /* To meet Android requirements create
11814 * a randomized MAC address of the
11815 * form 02:1A:11:Fx:xx:xx
11816 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011817 get_random_bytes(&ndev->dev_addr[3], 3);
11818 ndev->dev_addr[0] = 0x02;
11819 ndev->dev_addr[1] = 0x1A;
11820 ndev->dev_addr[2] = 0x11;
11821 ndev->dev_addr[3] |= 0xF0;
11822 memcpy(pAdapter->macAddressCurrent.
11823 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011824 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011825 pr_info("wlan: Generated HotSpot BSSID "
11826 MAC_ADDRESS_STR "\n",
11827 MAC_ADDR_ARRAY(ndev->dev_addr));
11828 }
11829
11830 hdd_set_ap_ops(pAdapter->dev);
11831
Arun Khandavallifae92942016-08-01 13:31:08 +053011832 if (hdd_start_adapter(pAdapter)) {
11833 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 return -EINVAL;
11835 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011836 /* Interface type changed update in wiphy structure */
11837 if (wdev) {
11838 wdev->iftype = type;
11839 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011840 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011841 return -EINVAL;
11842 }
11843 goto done;
11844 }
11845
11846 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011847 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011848 return -EOPNOTSUPP;
11849 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011850 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11851 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011852 switch (type) {
11853 case NL80211_IFTYPE_STATION:
11854 case NL80211_IFTYPE_P2P_CLIENT:
11855 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011856 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11857 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011858 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011859 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011860 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011861 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011862 pAdapter->device_mode);
11863 return -EINVAL;
11864 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011865 goto done;
11866
11867 case NL80211_IFTYPE_AP:
11868 case NL80211_IFTYPE_P2P_GO:
11869 wdev->iftype = type;
11870 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011871 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011872 goto done;
11873
11874 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011875 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011876 return -EOPNOTSUPP;
11877 }
11878 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011879 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011880 pAdapter->device_mode);
11881 return -EOPNOTSUPP;
11882 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011883done:
11884 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011885 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11886 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011887
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011888 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011889
11890 EXIT();
11891 return 0;
11892}
11893
Rajeev Kumar98edb772016-01-19 12:42:19 -080011894/**
11895 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11896 * @wiphy: Pointer to the wiphy structure
11897 * @ndev: Pointer to the net device
11898 * @type: Interface type
11899 * @flags: Flags for change interface
11900 * @params: Pointer to change interface parameters
11901 *
11902 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011903 */
11904static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11905 struct net_device *ndev,
11906 enum nl80211_iftype type,
11907 u32 *flags,
11908 struct vif_params *params)
11909{
11910 int ret;
11911
11912 cds_ssr_protect(__func__);
11913 ret =
11914 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11915 cds_ssr_unprotect(__func__);
11916
11917 return ret;
11918}
11919
Frank Liud4b2fa02017-03-29 11:46:48 +080011920#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011921static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11922 int index, uint8_t match)
11923{
11924 int i;
11925 for (i = 0; i < index; i++) {
11926 if (arr[i] == match)
11927 return true;
11928 }
11929 return false;
11930}
11931#endif
11932
11933/**
11934 * __wlan_hdd_change_station() - change station
11935 * @wiphy: Pointer to the wiphy structure
11936 * @dev: Pointer to the net device.
11937 * @mac: bssid
11938 * @params: Pointer to station parameters
11939 *
11940 * Return: 0 for success, error number on failure.
11941 */
11942#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11943static int __wlan_hdd_change_station(struct wiphy *wiphy,
11944 struct net_device *dev,
11945 const uint8_t *mac,
11946 struct station_parameters *params)
11947#else
11948static int __wlan_hdd_change_station(struct wiphy *wiphy,
11949 struct net_device *dev,
11950 uint8_t *mac,
11951 struct station_parameters *params)
11952#endif
11953{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011954 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011955 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11956 hdd_context_t *pHddCtx;
11957 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011958 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011959#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011960 tCsrStaParams StaParams = { 0 };
11961 uint8_t isBufSta = 0;
11962 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011963 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011964#endif
11965 int ret;
11966
11967 ENTER();
11968
Anurag Chouhan6d760662016-02-20 16:05:43 +053011969 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011970 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011971 return -EINVAL;
11972 }
11973
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011974 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011975 TRACE_CODE_HDD_CHANGE_STATION,
11976 pAdapter->sessionId, params->listen_interval));
11977
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011978 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11979 hdd_err("invalid session id: %d", pAdapter->sessionId);
11980 return -EINVAL;
11981 }
11982
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011983 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11984 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011985 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011986 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011987
11988 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11989
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011990 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011991
Krunal Sonib4326f22016-03-10 13:05:51 -080011992 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11993 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011994 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11995 status =
11996 hdd_softap_change_sta_state(pAdapter,
11997 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011998 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011999
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012000 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012001 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012002 return -EINVAL;
12003 }
12004 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012005 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
12006 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012007 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080012008#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
12009 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
12010 dev, mac, params);
12011#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070012012
12013 if (cds_is_sub_20_mhz_enabled()) {
12014 hdd_err("TDLS not allowed with sub 20 MHz");
12015 return -EINVAL;
12016 }
12017
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012018 StaParams.capability = params->capability;
12019 StaParams.uapsd_queues = params->uapsd_queues;
12020 StaParams.max_sp = params->max_sp;
12021
12022 /* Convert (first channel , number of channels) tuple to
12023 * the total list of channels. This goes with the assumption
12024 * that if the first channel is < 14, then the next channels
12025 * are an incremental of 1 else an incremental of 4 till the number
12026 * of channels.
12027 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012028 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012029 if (0 != params->supported_channels_len) {
12030 int i = 0, j = 0, k = 0, no_of_channels = 0;
12031 int num_unique_channels;
12032 int next;
12033 for (i = 0;
12034 i < params->supported_channels_len
12035 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
12036 int wifi_chan_index;
12037 if (!wlan_hdd_is_duplicate_channel
12038 (StaParams.supported_channels, j,
12039 params->supported_channels[i])) {
12040 StaParams.
12041 supported_channels[j] =
12042 params->
12043 supported_channels[i];
12044 } else {
12045 continue;
12046 }
12047 wifi_chan_index =
12048 ((StaParams.supported_channels[j] <=
12049 HDD_CHANNEL_14) ? 1 : 4);
12050 no_of_channels =
12051 params->supported_channels[i + 1];
12052
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012053 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 -080012054 StaParams.
12055 supported_channels[j],
12056 wifi_chan_index,
12057 no_of_channels);
12058 for (k = 1; k <= no_of_channels &&
12059 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
12060 k++) {
12061 next =
12062 StaParams.
12063 supported_channels[j] +
12064 wifi_chan_index;
12065 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
12066 StaParams.
12067 supported_channels[j
12068 +
12069 1]
12070 = next;
12071 } else {
12072 continue;
12073 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012074 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012075 j + 1,
12076 StaParams.
12077 supported_channels[j +
12078 1]);
12079 j += 1;
12080 }
12081 }
12082 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012083 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012084 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012085 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012086 StaParams.
12087 supported_channels[i]);
12088 }
12089 if (MAX_CHANNEL < num_unique_channels)
12090 num_unique_channels = MAX_CHANNEL;
12091 StaParams.supported_channels_len =
12092 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012093 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012094 StaParams.supported_channels_len);
12095 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012096 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012097 params->supported_oper_classes,
12098 params->supported_oper_classes_len);
12099 StaParams.supported_oper_classes_len =
12100 params->supported_oper_classes_len;
12101
12102 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012103 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012104 params->ext_capab,
12105 sizeof(StaParams.extn_capability));
12106
12107 if (NULL != params->ht_capa) {
12108 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012109 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012110 sizeof(tSirHTCap));
12111 }
12112
12113 StaParams.supported_rates_len =
12114 params->supported_rates_len;
12115
12116 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
12117 * The supported_rates array , for all the structures propogating till Add Sta
12118 * to the firmware has to be modified , if the supplicant (ieee80211) is
12119 * modified to send more rates.
12120 */
12121
12122 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
12123 */
12124 if (StaParams.supported_rates_len >
12125 SIR_MAC_MAX_SUPP_RATES)
12126 StaParams.supported_rates_len =
12127 SIR_MAC_MAX_SUPP_RATES;
12128
12129 if (0 != StaParams.supported_rates_len) {
12130 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012131 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012132 params->supported_rates,
12133 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012134 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012135 StaParams.supported_rates_len);
12136 for (i = 0; i < StaParams.supported_rates_len;
12137 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012138 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012139 StaParams.supported_rates[i]);
12140 }
12141
12142 if (NULL != params->vht_capa) {
12143 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012144 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012145 params->vht_capa,
12146 sizeof(tSirVHTCap));
12147 }
12148
12149 if (0 != params->ext_capab_len) {
12150 /*Define A Macro : TODO Sunil */
12151 if ((1 << 4) & StaParams.extn_capability[3]) {
12152 isBufSta = 1;
12153 }
12154 /* TDLS Channel Switching Support */
12155 if ((1 << 6) & StaParams.extn_capability[3]) {
12156 isOffChannelSupported = 1;
12157 }
12158 }
12159
Nitesh Shah99934ac2016-09-05 15:54:08 +053012160 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053012161 (params->ht_capa || params->vht_capa ||
12162 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053012163 is_qos_wmm_sta = true;
12164
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012165 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053012166 " is_qos_wmm_sta= %d HTcapPresent = %d",
12167 __func__, is_qos_wmm_sta,
12168 StaParams.htcap_present);
12169
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012170 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053012171 &StaParams,
12172 isBufSta,
12173 isOffChannelSupported,
12174 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012175 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012176 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012177 return -EINVAL;
12178 }
12179
12180 status =
12181 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
12182 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012183 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012184 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012185 return -EINVAL;
12186 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012187#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080012188 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012189 }
12190 EXIT();
12191 return ret;
12192}
12193
12194/**
12195 * wlan_hdd_change_station() - cfg80211 change station handler function
12196 * @wiphy: Pointer to the wiphy structure
12197 * @dev: Pointer to the net device.
12198 * @mac: bssid
12199 * @params: Pointer to station parameters
12200 *
12201 * This is the cfg80211 change station handler function which invokes
12202 * the internal function @__wlan_hdd_change_station with
12203 * SSR protection.
12204 *
12205 * Return: 0 for success, error number on failure.
12206 */
12207#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
12208static int wlan_hdd_change_station(struct wiphy *wiphy,
12209 struct net_device *dev,
12210 const u8 *mac,
12211 struct station_parameters *params)
12212#else
12213static int wlan_hdd_change_station(struct wiphy *wiphy,
12214 struct net_device *dev,
12215 u8 *mac,
12216 struct station_parameters *params)
12217#endif
12218{
12219 int ret;
12220
12221 cds_ssr_protect(__func__);
12222 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
12223 cds_ssr_unprotect(__func__);
12224
12225 return ret;
12226}
12227
12228/*
12229 * FUNCTION: __wlan_hdd_cfg80211_add_key
12230 * This function is used to initialize the key information
12231 */
12232static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12233 struct net_device *ndev,
12234 u8 key_index, bool pairwise,
12235 const u8 *mac_addr,
12236 struct key_params *params)
12237{
12238 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12239 tCsrRoamSetKey setKey;
12240 int status;
12241 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012242 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012243 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012244 hdd_context_t *pHddCtx;
12245 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12246
12247 ENTER();
12248
Anurag Chouhan6d760662016-02-20 16:05:43 +053012249 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012250 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012251 return -EINVAL;
12252 }
12253
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012254 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012255 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012256 return -EINVAL;
12257 }
12258
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012259 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012260 TRACE_CODE_HDD_CFG80211_ADD_KEY,
12261 pAdapter->sessionId, params->key_len));
12262 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12263 status = wlan_hdd_validate_context(pHddCtx);
12264
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012265 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012266 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012267
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012268 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012269 hdd_device_mode_to_string(pAdapter->device_mode),
12270 pAdapter->device_mode);
12271
12272 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012273 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012274
12275 return -EINVAL;
12276 }
12277
12278 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012279 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012280
12281 return -EINVAL;
12282 }
12283
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012284 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012285
12286 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012287 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012288 setKey.keyId = key_index;
12289 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012290 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012291
12292 switch (params->cipher) {
12293 case WLAN_CIPHER_SUITE_WEP40:
12294 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12295 break;
12296
12297 case WLAN_CIPHER_SUITE_WEP104:
12298 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
12299 break;
12300
12301 case WLAN_CIPHER_SUITE_TKIP:
12302 {
12303 u8 *pKey = &setKey.Key[0];
12304 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
12305
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012306 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012307
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012308 /* Supplicant sends the 32bytes key in this order
12309 *
12310 * |--------------|----------|----------|
12311 * | Tk1 |TX-MIC | RX Mic |
12312 * |--------------|----------|----------|
12313 * <---16bytes---><--8bytes--><--8bytes-->
12314 *
12315 * Sme expects the 32 bytes key to be in the below order
12316 *
12317 * |--------------|----------|----------|
12318 * | Tk1 |RX-MIC | TX Mic |
12319 * |--------------|----------|----------|
12320 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012321 */
12322 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012323 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324
12325 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012326 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012327
12328 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012329 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012330
12331 break;
12332 }
12333
12334 case WLAN_CIPHER_SUITE_CCMP:
12335 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
12336 break;
12337
12338#ifdef FEATURE_WLAN_WAPI
12339 case WLAN_CIPHER_SUITE_SMS4:
12340 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012341 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012342 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
12343 mac_addr, params->key,
12344 params->key_len);
12345 return 0;
12346 }
12347#endif
12348
12349#ifdef FEATURE_WLAN_ESE
12350 case WLAN_CIPHER_SUITE_KRK:
12351 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
12352 break;
12353#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12354 case WLAN_CIPHER_SUITE_BTK:
12355 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
12356 break;
12357#endif
12358#endif
12359
12360#ifdef WLAN_FEATURE_11W
12361 case WLAN_CIPHER_SUITE_AES_CMAC:
12362 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
12363 break;
12364#endif
12365
12366 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012367 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012368 return -EOPNOTSUPP;
12369 }
12370
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012371 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012372
12373 if (!pairwise) {
12374 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012375 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012376 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012377 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012378 } else {
12379 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012380 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012381 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012382 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012383 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012384 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012385 /* if a key is already installed, block all subsequent ones */
12386 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012387 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012388 return 0;
12389 }
12390
12391 setKey.keyDirection = eSIR_TX_RX;
12392 /*Set the group key */
12393 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12394 pAdapter->sessionId, &setKey, &roamId);
12395
12396 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012397 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012398 return -EINVAL;
12399 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012400 /* Save the keys here and call sme_roam_set_key for setting
12401 * the PTK after peer joins the IBSS network
12402 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012403 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012404 &setKey, sizeof(tCsrRoamSetKey));
12405
12406 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
12407 return status;
12408 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012409 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
12410 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012411 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
12412 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070012413 status = wlansap_set_key_sta(
12414 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012415 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012416 hdd_err("wlansap_set_key_sta failed status: %d",
12417 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012418 }
12419 }
12420
12421 /* Save the key in ap ctx for use on START_BASS and restart */
12422 if (pairwise ||
12423 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
12424 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012425 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012426 sizeof(tCsrRoamSetKey));
12427 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012428 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012429 sizeof(tCsrRoamSetKey));
12430
Krunal Sonib4326f22016-03-10 13:05:51 -080012431 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
12432 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012433 hdd_wext_state_t *pWextState =
12434 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12435 hdd_station_ctx_t *pHddStaCtx =
12436 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12437
12438 if (!pairwise) {
12439 /* set group key */
12440 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012441 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012442 __func__, __LINE__);
12443 hdd_perform_roam_set_key_complete(pAdapter);
12444 }
12445 }
12446
12447 pWextState->roamProfile.Keys.KeyLength[key_index] =
12448 (u8) params->key_len;
12449
12450 pWextState->roamProfile.Keys.defaultIndex = key_index;
12451
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012452 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012453 KeyMaterial[key_index][0], params->key,
12454 params->key_len);
12455
12456 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
12457
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012458 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012459 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12460 setKey.keyDirection);
12461
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012462 /* The supplicant may attempt to set the PTK once
12463 * pre-authentication is done. Save the key in the
12464 * UMAC and include it in the ADD BSS request
12465 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012466 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012467 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012468 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012469 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012470 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012471 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012472 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012473 return -EINVAL;
12474 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012475
12476 /* issue set key request to SME */
12477 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12478 pAdapter->sessionId, &setKey, &roamId);
12479
12480 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012481 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012482 pHddStaCtx->roam_info.roamingState =
12483 HDD_ROAM_STATE_NONE;
12484 return -EINVAL;
12485 }
12486
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012487 /* in case of IBSS as there was no information
12488 * available about WEP keys during IBSS join, group
12489 * key intialized with NULL key, so re-initialize
12490 * group key with correct value
12491 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012492 if ((eCSR_BSS_TYPE_START_IBSS ==
12493 pWextState->roamProfile.BSSType)
12494 &&
12495 !((IW_AUTH_KEY_MGMT_802_1X ==
12496 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
12497 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
12498 pHddStaCtx->conn_info.authType)
12499 )
12500 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
12501 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
12502 )
12503 ) {
12504 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053012505 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012506
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012507 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012508 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
12509 setKey.keyDirection);
12510
12511 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12512 pAdapter->sessionId, &setKey,
12513 &roamId);
12514
12515 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012516 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012517 pHddStaCtx->roam_info.roamingState =
12518 HDD_ROAM_STATE_NONE;
12519 return -EINVAL;
12520 }
12521 }
12522 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012523 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012524 return 0;
12525}
12526
12527static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
12528 struct net_device *ndev,
12529 u8 key_index, bool pairwise,
12530 const u8 *mac_addr,
12531 struct key_params *params)
12532{
12533 int ret;
12534 cds_ssr_protect(__func__);
12535 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
12536 mac_addr, params);
12537 cds_ssr_unprotect(__func__);
12538
12539 return ret;
12540}
12541
12542/*
12543 * FUNCTION: __wlan_hdd_cfg80211_get_key
12544 * This function is used to get the key information
12545 */
12546static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12547 struct net_device *ndev,
12548 u8 key_index, bool pairwise,
12549 const u8 *mac_addr, void *cookie,
12550 void (*callback)(void *cookie,
12551 struct key_params *)
12552 )
12553{
12554 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12555 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12556 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
12557 struct key_params params;
12558
12559 ENTER();
12560
Anurag Chouhan6d760662016-02-20 16:05:43 +053012561 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012562 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012563 return -EINVAL;
12564 }
12565
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012566 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012567 hdd_device_mode_to_string(pAdapter->device_mode),
12568 pAdapter->device_mode);
12569
12570 memset(&params, 0, sizeof(params));
12571
12572 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012573 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012574 return -EINVAL;
12575 }
12576
12577 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
12578 case eCSR_ENCRYPT_TYPE_NONE:
12579 params.cipher = IW_AUTH_CIPHER_NONE;
12580 break;
12581
12582 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
12583 case eCSR_ENCRYPT_TYPE_WEP40:
12584 params.cipher = WLAN_CIPHER_SUITE_WEP40;
12585 break;
12586
12587 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
12588 case eCSR_ENCRYPT_TYPE_WEP104:
12589 params.cipher = WLAN_CIPHER_SUITE_WEP104;
12590 break;
12591
12592 case eCSR_ENCRYPT_TYPE_TKIP:
12593 params.cipher = WLAN_CIPHER_SUITE_TKIP;
12594 break;
12595
12596 case eCSR_ENCRYPT_TYPE_AES:
12597 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
12598 break;
12599
12600 default:
12601 params.cipher = IW_AUTH_CIPHER_NONE;
12602 break;
12603 }
12604
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012605 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012606 TRACE_CODE_HDD_CFG80211_GET_KEY,
12607 pAdapter->sessionId, params.cipher));
12608
12609 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12610 params.seq_len = 0;
12611 params.seq = NULL;
12612 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12613 callback(cookie, &params);
12614
12615 EXIT();
12616 return 0;
12617}
12618
12619static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12620 struct net_device *ndev,
12621 u8 key_index, bool pairwise,
12622 const u8 *mac_addr, void *cookie,
12623 void (*callback)(void *cookie,
12624 struct key_params *)
12625 )
12626{
12627 int ret;
12628
12629 cds_ssr_protect(__func__);
12630 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12631 mac_addr, cookie, callback);
12632 cds_ssr_unprotect(__func__);
12633
12634 return ret;
12635}
12636
12637/**
12638 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12639 * @wiphy: wiphy interface context
12640 * @ndev: pointer to net device
12641 * @key_index: Key index used in 802.11 frames
12642 * @unicast: true if it is unicast key
12643 * @multicast: true if it is multicast key
12644 *
12645 * This function is required for cfg80211_ops API.
12646 * It is used to delete the key information
12647 * Underlying hardware implementation does not have API to delete the
12648 * encryption key. It is automatically deleted when the peer is
12649 * removed. Hence this function currently does nothing.
12650 * Future implementation may interprete delete key operation to
12651 * replacing the key with a random junk value, effectively making it
12652 * useless.
12653 *
12654 * Return: status code, always 0.
12655 */
12656
12657static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12658 struct net_device *ndev,
12659 u8 key_index,
12660 bool pairwise, const u8 *mac_addr)
12661{
12662 EXIT();
12663 return 0;
12664}
12665
12666/**
12667 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12668 * @wiphy: Pointer to wiphy structure.
12669 * @dev: Pointer to net_device structure.
12670 * @key_index: key index
12671 * @pairwise: pairwise
12672 * @mac_addr: mac address
12673 *
12674 * This is the cfg80211 delete key handler function which invokes
12675 * the internal function @__wlan_hdd_cfg80211_del_key with
12676 * SSR protection.
12677 *
12678 * Return: 0 for success, error number on failure.
12679 */
12680static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12681 struct net_device *dev,
12682 u8 key_index,
12683 bool pairwise, const u8 *mac_addr)
12684{
12685 int ret;
12686
12687 cds_ssr_protect(__func__);
12688 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12689 pairwise, mac_addr);
12690 cds_ssr_unprotect(__func__);
12691
12692 return ret;
12693}
12694
12695/*
12696 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12697 * This function is used to set the default tx key index
12698 */
12699static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12700 struct net_device *ndev,
12701 u8 key_index,
12702 bool unicast, bool multicast)
12703{
12704 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12705 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12706 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12707 hdd_context_t *pHddCtx;
12708 int status;
12709
12710 ENTER();
12711
Anurag Chouhan6d760662016-02-20 16:05:43 +053012712 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012713 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012714 return -EINVAL;
12715 }
12716
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012717 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012718 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012719 return -EINVAL;
12720 }
12721
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012722 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012723 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12724 pAdapter->sessionId, key_index));
12725
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012726 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012727 hdd_device_mode_to_string(pAdapter->device_mode),
12728 pAdapter->device_mode, key_index);
12729
12730 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012731 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012732 return -EINVAL;
12733 }
12734
12735 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12736 status = wlan_hdd_validate_context(pHddCtx);
12737
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012738 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012739 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012740
Krunal Sonib4326f22016-03-10 13:05:51 -080012741 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12742 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012743 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12744 pHddStaCtx->conn_info.ucEncryptionType) &&
12745 (eCSR_ENCRYPT_TYPE_AES !=
12746 pHddStaCtx->conn_info.ucEncryptionType)) {
12747 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012748 * then update the default key index
12749 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012750
12751 tCsrRoamSetKey setKey;
12752 uint32_t roamId = 0xFF;
12753 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12754
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012755 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012756
12757 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012758 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012759 setKey.keyId = key_index;
12760 setKey.keyLength = Keys->KeyLength[key_index];
12761
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012762 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012763 &Keys->KeyMaterial[key_index][0],
12764 Keys->KeyLength[key_index]);
12765
12766 setKey.keyDirection = eSIR_TX_RX;
12767
Anurag Chouhanc5548422016-02-24 18:33:27 +053012768 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012769 &pHddStaCtx->conn_info.bssId);
12770
12771 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12772 pWextState->roamProfile.EncryptionType.
12773 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012774 /* In the case of dynamic wep
12775 * supplicant hardcodes DWEP type to
12776 * eCSR_ENCRYPT_TYPE_WEP104 even
12777 * though ap is configured for WEP-40
12778 * encryption. In this canse the key
12779 * length is 5 but the encryption type
12780 * is 104 hence checking the key
12781 * lenght(5) and encryption type(104)
12782 * and switching encryption type to 40
12783 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012784 pWextState->roamProfile.EncryptionType.
12785 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12786 pWextState->roamProfile.mcEncryptionType.
12787 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12788 }
12789
12790 setKey.encType =
12791 pWextState->roamProfile.EncryptionType.
12792 encryptionType[0];
12793
12794 /* Issue set key request */
12795 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12796 pAdapter->sessionId, &setKey,
12797 &roamId);
12798
12799 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012800 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012801 status);
12802 return -EINVAL;
12803 }
12804 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012805 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012806 /* In SoftAp mode setting key direction for default mode */
12807 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12808 pWextState->roamProfile.EncryptionType.encryptionType[0])
12809 && (eCSR_ENCRYPT_TYPE_AES !=
12810 pWextState->roamProfile.EncryptionType.
12811 encryptionType[0])) {
12812 /* Saving key direction for default key index to TX default */
12813 hdd_ap_ctx_t *pAPCtx =
12814 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12815 pAPCtx->wepKey[key_index].keyDirection =
12816 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012817 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012818 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012819 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012820 }
12821 }
12822
12823 EXIT();
12824 return status;
12825}
12826
12827static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12828 struct net_device *ndev,
12829 u8 key_index,
12830 bool unicast, bool multicast)
12831{
12832 int ret;
12833 cds_ssr_protect(__func__);
12834 ret =
12835 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12836 multicast);
12837 cds_ssr_unprotect(__func__);
12838
12839 return ret;
12840}
12841
Abhishek Singhc9941602016-08-09 16:06:22 +053012842/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012843 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12844 * interface that BSS might have been lost.
12845 * @pAdapter: adaptor
12846 * @bssid: bssid which might have been lost
12847 *
12848 * Return: bss which is unlinked from kernel cache
12849 */
12850struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12851 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012852{
12853 struct net_device *dev = pAdapter->dev;
12854 struct wireless_dev *wdev = dev->ieee80211_ptr;
12855 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012856 struct cfg80211_bss *bss = NULL;
12857
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012858 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012859 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012860 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012861 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012862 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012863 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012864 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012865 cfg80211_unlink_bss(wiphy, bss);
12866 }
12867 return bss;
12868}
12869
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012870#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12871 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12872static struct cfg80211_bss *
12873wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12874 struct ieee80211_channel *chan,
12875 struct ieee80211_mgmt *mgmt,
12876 size_t frame_len,
12877 int rssi, gfp_t gfp,
12878 uint64_t boottime_ns)
12879{
12880 struct cfg80211_bss *bss_status = NULL;
12881 struct cfg80211_inform_bss data = {0};
12882
12883 data.chan = chan;
12884 data.boottime_ns = boottime_ns;
12885 data.signal = rssi;
12886 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12887 frame_len, gfp);
12888 return bss_status;
12889}
12890#else
12891static struct cfg80211_bss *
12892wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12893 struct ieee80211_channel *chan,
12894 struct ieee80211_mgmt *mgmt,
12895 size_t frame_len,
12896 int rssi, gfp_t gfp,
12897 uint64_t boottime_ns)
12898{
12899 struct cfg80211_bss *bss_status = NULL;
12900
12901 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12902 rssi, gfp);
12903 return bss_status;
12904}
12905#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012907/**
12908 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12909 * @pAdapter: Pointer to adapter
12910 * @bss_desc: Pointer to bss descriptor
12911 *
12912 * This function is used to inform the BSS details to nl80211 interface.
12913 *
12914 * Return: struct cfg80211_bss pointer
12915 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012916struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12917 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012918{
12919 /*
12920 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12921 * already exists in bss data base of cfg80211 for that particular BSS
12922 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12923 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12924 * As of now there is no possibility to get the mgmt(probe response)
12925 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12926 * and passing to cfg80211_inform_bss_frame.
12927 */
12928 struct net_device *dev = pAdapter->dev;
12929 struct wireless_dev *wdev = dev->ieee80211_ptr;
12930 struct wiphy *wiphy = wdev->wiphy;
12931 int chan_no = bss_desc->channelId;
12932#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12933 qcom_ie_age *qie_age = NULL;
12934 int ie_length =
12935 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12936#else
12937 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12938#endif
12939 const char *ie =
12940 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12941 unsigned int freq;
12942 struct ieee80211_channel *chan;
12943 struct ieee80211_mgmt *mgmt = NULL;
12944 struct cfg80211_bss *bss_status = NULL;
12945 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12946 int rssi = 0;
12947 hdd_context_t *pHddCtx;
12948 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012949 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012950 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012951
12952 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12953 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012954 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012955 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012956
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012957 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012958 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012959 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012960 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012961 return NULL;
12962 }
12963
12964 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12965
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012966 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012967 * Instead it wants a monotonic increasing value
12968 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012969 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012970 mgmt->u.probe_resp.timestamp =
12971 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012972
12973 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12974 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12975
12976#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12977 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12978 /* Assuming this is the last IE, copy at the end */
12979 ie_length -= sizeof(qcom_ie_age);
12980 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12981 qie_age->element_id = QCOM_VENDOR_IE_ID;
12982 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12983 qie_age->oui_1 = QCOM_OUI1;
12984 qie_age->oui_2 = QCOM_OUI2;
12985 qie_age->oui_3 = QCOM_OUI3;
12986 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012987 /*
12988 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12989 * all bss related timestamp is in units of ms. Due to this when scan
12990 * results are sent to lowi the scan age is high.To address this,
12991 * send age in units of 1/10 ms.
12992 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012993 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012994 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012995 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012996 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12997 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012998 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12999 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013000#endif
13001
13002 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
13003 if (bss_desc->fProbeRsp) {
13004 mgmt->frame_control |=
13005 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
13006 } else {
13007 mgmt->frame_control |=
13008 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
13009 }
13010
13011 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070013012 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013013 freq =
13014 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070013015 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013016 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070013017 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013018 freq =
13019 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070013020 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013021 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013022 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070013023 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013024 return NULL;
13025 }
13026
13027 chan = __ieee80211_get_channel(wiphy, freq);
13028 /* When the band is changed on the fly using the GUI, three things are done
13029 * 1. scan abort
13030 * 2. flush scan results from cache
13031 * 3. update the band with the new band user specified (refer to the
13032 * hdd_set_band_helper function) as part of the scan abort, message will be
13033 * queued to PE and we proceed with flushing and changinh the band.
13034 * PE will stop the scanning further and report back the results what ever
13035 * it had till now by calling the call back function.
13036 * if the time between update band and scandone call back is sufficient
13037 * enough the band change reflects in SME, SME validates the channels
13038 * and discards the channels correponding to previous band and calls back
13039 * with zero bss results. but if the time between band update and scan done
13040 * callback is very small then band change will not reflect in SME and SME
13041 * reports to HDD all the channels correponding to previous band.this is due
13042 * to race condition.but those channels are invalid to the new band and so
13043 * this function __ieee80211_get_channel will return NULL.Each time we
13044 * report scan result with this pointer null warning kernel trace is printed.
13045 * if the scan results contain large number of APs continuosly kernel
13046 * warning trace is printed and it will lead to apps watch dog bark.
13047 * So drop the bss and continue to next bss.
13048 */
13049 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053013050 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
13051 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070013052 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013053 return NULL;
13054 }
13055
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070013056 /* Based on .ini configuration, raw rssi can be reported for bss.
13057 * Raw rssi is typically used for estimating power.
13058 */
13059
13060 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
13061 bss_desc->rssi;
13062
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013063 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053013064 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013065
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080013066 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013067 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070013068 (int)(rssi / 100),
13069 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013070
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053013071 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
13072 frame_len, rssi,
13073 GFP_KERNEL,
13074 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053013075 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070013076 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013077 return bss_status;
13078}
13079
13080/**
13081 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
13082 * @pAdapter: Pointer to adapter
13083 * @pRoamInfo: Pointer to roam info
13084 *
13085 * This function is used to update the BSS data base of CFG8011
13086 *
13087 * Return: struct cfg80211_bss pointer
13088 */
13089struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
13090 tCsrRoamInfo *pRoamInfo)
13091{
13092 tCsrRoamConnectedProfile roamProfile;
13093 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13094 struct cfg80211_bss *bss = NULL;
13095
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013096 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
13097 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
13098
13099 if (NULL != roamProfile.pBssDesc) {
13100 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
13101 roamProfile.pBssDesc);
13102
13103 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013104 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013105
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080013106 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013107 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013108 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013109 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013110 return bss;
13111}
13112/**
13113 * wlan_hdd_cfg80211_update_bss() - update bss
13114 * @wiphy: Pointer to wiphy
13115 * @pAdapter: Pointer to adapter
13116 * @scan_time: scan request timestamp
13117 *
13118 * Return: zero if success, non-zero otherwise
13119 */
13120int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
13121 hdd_adapter_t *pAdapter,
13122 uint32_t scan_time)
13123{
13124 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13125 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013126 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013127 tScanResultHandle pResult;
13128 struct cfg80211_bss *bss_status = NULL;
13129 hdd_context_t *pHddCtx;
13130 int ret;
13131
13132 ENTER();
13133
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013134 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13135 hdd_err("invalid session id: %d", pAdapter->sessionId);
13136 return -EINVAL;
13137 }
13138
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013139 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013140 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
13141 NO_SESSION, pAdapter->sessionId));
13142
13143 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13144 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013145 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013146 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013147
13148 /* start getting scan results and populate cgf80211 BSS database */
13149 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
13150
13151 /* no scan results */
13152 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013153 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053013154 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013155 }
13156
13157 pScanResult = sme_scan_result_get_first(hHal, pResult);
13158
13159 while (pScanResult) {
13160 /*
13161 * - cfg80211_inform_bss() is not updating ie field of bss
13162 * entry if entry already exists in bss data base of cfg80211
13163 * for that particular BSS ID. Using cfg80211_inform_bss_frame
13164 * to update thebss entry instead of cfg80211_inform_bss,
13165 * But this call expects mgmt packet as input. As of now
13166 * there is no possibility to get the mgmt(probe response)
13167 * frame from PE, converting bss_desc to
13168 * ieee80211_mgmt(probe response) and passing to c
13169 * fg80211_inform_bss_frame.
13170 * - Update BSS only if beacon timestamp is later than
13171 * scan request timestamp.
13172 */
13173 if ((scan_time == 0) ||
13174 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053013175 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013176 bss_status =
13177 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
13178 &pScanResult->BssDescriptor);
13179
13180 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013181 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013182 } else {
13183 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013184 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013185 bss_status);
13186 }
13187 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013188 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013189 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
13190 }
13191 pScanResult = sme_scan_result_get_next(hHal, pResult);
13192 }
13193
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070013194 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013195 /*
13196 * For SAP mode, scan is invoked by hostapd during SAP start
13197 * if hostapd is restarted, we need to flush previous scan
13198 * result so that it will reflect environment change
13199 */
Krunal Sonib4326f22016-03-10 13:05:51 -080013200 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013201#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
13202 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
13203#endif
13204 )
13205 sme_scan_flush_result(hHal);
13206
13207 EXIT();
13208 return 0;
13209}
13210
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013211/**
13212 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
13213 * @pAdapter: Pointer to adapter
13214 * @pRoamInfo: Pointer to roam info
13215 * @index: Index
13216 * @preauth: Preauth flag
13217 *
13218 * This function is used to notify the supplicant of a new PMKSA candidate.
13219 *
13220 * Return: 0 for success, non-zero for failure
13221 */
13222int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
13223 tCsrRoamInfo *pRoamInfo,
13224 int index, bool preauth)
13225{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013226 struct net_device *dev = pAdapter->dev;
13227 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
13228
13229 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013230 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013231
13232 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013233 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013234 return -EINVAL;
13235 }
13236
13237 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013238 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013239 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
13240 cfg80211_pmksa_candidate_notify(dev, index,
13241 pRoamInfo->bssid.bytes,
13242 preauth, GFP_KERNEL);
13243 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013244 return 0;
13245}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013246
13247#ifdef FEATURE_WLAN_LFR_METRICS
13248/**
13249 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
13250 * @pAdapter: Pointer to adapter
13251 * @pRoamInfo: Pointer to roam info
13252 *
13253 * 802.11r/LFR metrics reporting function to report preauth initiation
13254 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013255 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013256 */
13257#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013258QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013259 tCsrRoamInfo *pRoamInfo)
13260{
13261 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13262 union iwreq_data wrqu;
13263
13264 ENTER();
13265
13266 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013267 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013268 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013269 }
13270
13271 /* create the event */
13272 memset(&wrqu, 0, sizeof(wrqu));
13273 memset(metrics_notification, 0, sizeof(metrics_notification));
13274
13275 wrqu.data.pointer = metrics_notification;
13276 wrqu.data.length = scnprintf(metrics_notification,
13277 sizeof(metrics_notification),
13278 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013279 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013280
13281 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13282 metrics_notification);
13283
13284 EXIT();
13285
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013286 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013287}
13288
13289/**
13290 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
13291 * @pAdapter: Pointer to adapter
13292 * @pRoamInfo: Pointer to roam info
13293 * @preauth_status: Preauth status
13294 *
13295 * 802.11r/LFR metrics reporting function to report handover initiation
13296 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013297 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013298 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013299QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013300wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
13301 tCsrRoamInfo *pRoamInfo,
13302 bool preauth_status)
13303{
13304 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13305 union iwreq_data wrqu;
13306
13307 ENTER();
13308
13309 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013310 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013311 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013312 }
13313
13314 /* create the event */
13315 memset(&wrqu, 0, sizeof(wrqu));
13316 memset(metrics_notification, 0, sizeof(metrics_notification));
13317
13318 scnprintf(metrics_notification, sizeof(metrics_notification),
13319 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013320 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013321
13322 if (1 == preauth_status)
13323 strlcat(metrics_notification, " true",
13324 sizeof(metrics_notification));
13325 else
13326 strlcat(metrics_notification, " false",
13327 sizeof(metrics_notification));
13328
13329 wrqu.data.pointer = metrics_notification;
13330 wrqu.data.length = strlen(metrics_notification);
13331
13332 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13333 metrics_notification);
13334
13335 EXIT();
13336
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013337 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013338}
13339
13340/**
13341 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
13342 * @pAdapter: Pointer to adapter
13343 * @pRoamInfo: Pointer to roam info
13344 *
13345 * 802.11r/LFR metrics reporting function to report handover initiation
13346 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013347 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013348 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013349QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013350 tCsrRoamInfo *pRoamInfo)
13351{
13352 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
13353 union iwreq_data wrqu;
13354
13355 ENTER();
13356
13357 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013358 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013359 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013360 }
13361
13362 /* create the event */
13363 memset(&wrqu, 0, sizeof(wrqu));
13364 memset(metrics_notification, 0, sizeof(metrics_notification));
13365
13366 wrqu.data.pointer = metrics_notification;
13367 wrqu.data.length = scnprintf(metrics_notification,
13368 sizeof(metrics_notification),
13369 "QCOM: LFR_PREAUTH_HANDOVER "
13370 MAC_ADDRESS_STR,
Sreelakshmi Konamkic931b372017-05-30 14:38:27 +053013371 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013372
13373 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
13374 metrics_notification);
13375
13376 EXIT();
13377
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013378 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013379}
13380#endif
13381
13382/**
13383 * hdd_select_cbmode() - select channel bonding mode
13384 * @pAdapter: Pointer to adapter
13385 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013386 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013387 *
13388 * Return: none
13389 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013390void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080013391 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013392{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013393 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013394 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013395 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013396 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013397
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013398 /*
13399 * CDS api expects secondary channel for calculating
13400 * the channel params
13401 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013402 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013403 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013404 if (operationChannel >= 1 && operationChannel <= 5)
13405 sec_ch = operationChannel + 4;
13406 else if (operationChannel >= 6 && operationChannel <= 13)
13407 sec_ch = operationChannel - 4;
13408 }
13409
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013410 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013411 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
13412 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013413
13414 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070013415 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013416 uint8_t iniDot11Mode =
13417 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
13418
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013419 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013420 switch (iniDot11Mode) {
13421 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080013422 case eHDD_DOT11_MODE_11ax:
13423 case eHDD_DOT11_MODE_11ax_ONLY:
13424 if (sme_is_feature_supported_by_fw(DOT11AX))
13425 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
13426 else if (sme_is_feature_supported_by_fw(DOT11AC))
13427 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13428 else
13429 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13430 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013431 case eHDD_DOT11_MODE_11ac:
13432 case eHDD_DOT11_MODE_11ac_ONLY:
13433 if (sme_is_feature_supported_by_fw(DOT11AC))
13434 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
13435 else
13436 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13437 break;
13438 case eHDD_DOT11_MODE_11n:
13439 case eHDD_DOT11_MODE_11n_ONLY:
13440 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
13441 break;
13442 default:
13443 hdd_dot11_mode = iniDot11Mode;
13444 break;
13445 }
13446 ch_info->channel_width = ch_params->ch_width;
13447 ch_info->phy_mode =
13448 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013449 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013450 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013451 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013452 ch_info->channel_width, ch_info->phy_mode,
13453 ch_info->channel);
13454 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013455}
13456
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013457/**
13458 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
13459 * @adapter: STA adapter
13460 * @roam_profile: STA roam profile
13461 *
13462 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
13463 *
13464 * Return: false if sta-sap conc is not allowed, else return true
13465 */
13466static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
13467 tCsrRoamProfile *roam_profile)
13468{
13469 hdd_context_t *hdd_ctx;
13470 hdd_adapter_t *ap_adapter;
13471 hdd_ap_ctx_t *hdd_ap_ctx;
13472 hdd_hostapd_state_t *hostapd_state;
13473 uint8_t channel = 0;
13474 QDF_STATUS status;
13475
13476 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
13477 if (!hdd_ctx) {
13478 hdd_err("HDD context is NULL");
13479 return true;
13480 }
13481
13482 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
13483 /* probably no sap running, no handling required */
13484 if (ap_adapter == NULL)
13485 return true;
13486
13487 /*
13488 * sap is not in started state, so it is fine to go ahead with sta.
13489 * if sap is currently doing CAC then don't allow sta to go further.
13490 */
13491 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
13492 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
13493 return true;
13494
13495 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
13496 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
13497 return false;
13498 }
13499
13500 /*
13501 * log and return error, if we allow STA to go through, we don't
13502 * know what is going to happen better stop sta connection
13503 */
13504 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
13505 if (NULL == hdd_ap_ctx) {
13506 hdd_err("AP context not found");
13507 return false;
13508 }
13509
13510 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013511 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
13512 hdd_ap_ctx->operatingChannel)) {
13513 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013514 return true;
13515 }
13516 /*
13517 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053013518 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013519 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013520 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013521 roam_profile, &channel);
13522
Nitesh Shah59774522016-09-16 15:14:21 +053013523 /*
13524 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
13525 * channels for roaming case.
13526 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013527 if (WLAN_REG_IS_24GHZ_CH(channel)) {
13528 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053013529 return true;
13530 }
13531
13532 /*
13533 * If channel is 0 or DFS then better to call pcl and find out the
13534 * best channel. If channel is non-dfs 5 GHz then better move SAP
13535 * to STA's channel to make scc, so we have room for 3port MCC
13536 * scenario.
13537 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013538 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013539 channel = policy_mgr_get_nondfs_preferred_channel(
13540 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013541
13542 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
13543 qdf_event_reset(&hostapd_state->qdf_event);
13544 status = wlansap_set_channel_change_with_csa(
13545 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
13546 hdd_ap_ctx->sapConfig.ch_width_orig);
13547
13548 if (QDF_STATUS_SUCCESS != status) {
13549 hdd_err("Set channel with CSA IE failed, can't allow STA");
13550 return false;
13551 }
13552
13553 /*
13554 * wait here for SAP to finish the channel switch. When channel
13555 * switch happens, SAP sends few beacons with CSA_IE. After
13556 * successfully Transmission of those beacons, it will move its
13557 * state from started to disconnected and move to new channel.
13558 * once it moves to new channel, sap again moves its state
13559 * machine from disconnected to started and set this event.
13560 * wait for 10 secs to finish this.
13561 */
13562 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
13563 if (!QDF_IS_STATUS_SUCCESS(status)) {
13564 hdd_err("wait for qdf_event failed, STA not allowed!!");
13565 return false;
13566 }
13567
13568 return true;
13569}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013570
Abhishek Singhcfb44482017-03-10 12:42:37 +053013571#ifdef WLAN_FEATURE_11W
13572/**
13573 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
13574 * @roam_profile: pointer to roam profile
13575 *
13576 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13577 * or pmf=2 is an explicit configuration in the supplicant
13578 * configuration, drop the connection request.
13579 *
13580 * Return: 0 if check result is valid, otherwise return error code
13581 */
13582static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13583{
13584 if (roam_profile->MFPEnabled &&
13585 !(roam_profile->MFPRequired ||
13586 roam_profile->MFPCapable)) {
13587 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13588 roam_profile->MFPEnabled,
13589 roam_profile->MFPRequired,
13590 roam_profile->MFPCapable);
13591 return -EINVAL;
13592 }
13593 return 0;
13594}
13595#else
13596static inline
13597int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13598{
13599 return 0;
13600}
13601#endif
13602
Krunal Soni31949422016-07-29 17:17:53 -070013603/**
13604 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013605 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070013606 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013607 * @ssid_len: Length of ssid
13608 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070013609 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013610 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013611 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013612 *
13613 * This function is used to start the association process
13614 *
13615 * Return: 0 for success, non-zero for failure
13616 */
Krunal Soni31949422016-07-29 17:17:53 -070013617static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013618 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013619 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013620 u8 operatingChannel,
13621 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013622{
13623 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013624 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013625 hdd_wext_state_t *pWextState;
13626 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013627 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013628 uint32_t roamId;
13629 tCsrRoamProfile *pRoamProfile;
13630 eCsrAuthType RSNAuthType;
13631 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013632 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013633
13634 ENTER();
13635
13636 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13637 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013638 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639
13640 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013641 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013642 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013643
13644 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013645 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013646 status = -EINVAL;
13647 goto ret_status;
13648 }
13649
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013650 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013651 hdd_err("Connection refused: conn in progress");
13652 status = -EINVAL;
13653 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013654 }
13655
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013656 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013657 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13658
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013659 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013660 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13661 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013662
13663 if (pRoamProfile) {
13664 hdd_station_ctx_t *pHddStaCtx;
13665 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13666
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013667 /* Restart the opportunistic timer
13668 *
13669 * If hw_mode_change_in_progress is true, then wait
13670 * till firmware sends the callback for hw_mode change.
13671 *
13672 * Else set connect_in_progress as true and proceed.
13673 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013674 policy_mgr_restart_opportunistic_timer(
13675 pHddCtx->hdd_psoc, false);
13676 if (policy_mgr_is_hw_mode_change_in_progress(
13677 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013678 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013679 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013680 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013681 hdd_err("qdf wait for event failed!!");
13682 status = -EINVAL;
13683 goto ret_status;
13684 }
13685 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013686 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013687
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013688 if (HDD_WMM_USER_MODE_NO_QOS ==
13689 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13690 /*QoS not enabled in cfg file */
13691 pRoamProfile->uapsd_mask = 0;
13692 } else {
13693 /*QoS enabled, update uapsd mask from cfg file */
13694 pRoamProfile->uapsd_mask =
13695 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13696 }
13697
13698 pRoamProfile->SSIDs.numOfSSIDs = 1;
13699 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013700 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013701 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013702 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013703 ssid, ssid_len);
13704
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013705 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013706 /* cleanup bssid hint */
13707 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13708 QDF_MAC_ADDR_SIZE);
13709 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13710 QDF_MAC_ADDR_SIZE);
13711
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013712 if (bssid) {
13713 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013714 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013715 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013716 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013717 /*
13718 * Save BSSID in seperate variable as
13719 * pRoamProfile's BSSID is getting zeroed out in the
13720 * association process. In case of join failure
13721 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013722 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013723 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013724 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013725 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013726 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013727 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13728 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013729 /*
13730 * Save BSSID in a separate variable as
13731 * pRoamProfile's BSSID is getting zeroed out in the
13732 * association process. In case of join failure
13733 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013734 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013735 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013736 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013737 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013738 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013739 }
13740
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013741 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013742 pRoamProfile->SSIDs.SSIDList->SSID.length,
13743 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13744 operatingChannel);
13745
13746 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13747 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013748 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013749 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13750 }
13751#ifdef FEATURE_WLAN_WAPI
13752 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013753 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013754 switch (pAdapter->wapi_info.wapiAuthMode) {
13755 case WAPI_AUTH_MODE_PSK:
13756 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013757 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013758 pAdapter->wapi_info.wapiAuthMode);
13759 pRoamProfile->AuthType.authType[0] =
13760 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13761 break;
13762 }
13763 case WAPI_AUTH_MODE_CERT:
13764 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013765 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013766 pAdapter->wapi_info.wapiAuthMode);
13767 pRoamProfile->AuthType.authType[0] =
13768 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13769 break;
13770 }
13771 } /* End of switch */
13772 if (pAdapter->wapi_info.wapiAuthMode ==
13773 WAPI_AUTH_MODE_PSK
13774 || pAdapter->wapi_info.wapiAuthMode ==
13775 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013776 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013777 pRoamProfile->AuthType.numEntries = 1;
13778 pRoamProfile->EncryptionType.numEntries = 1;
13779 pRoamProfile->EncryptionType.encryptionType[0] =
13780 eCSR_ENCRYPT_TYPE_WPI;
13781 pRoamProfile->mcEncryptionType.numEntries = 1;
13782 pRoamProfile->mcEncryptionType.
13783 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13784 }
13785 }
Krunal Soni31949422016-07-29 17:17:53 -070013786#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013787 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013788 pRoamProfile->csrPersona = pAdapter->device_mode;
13789
13790 if (operatingChannel) {
13791 pRoamProfile->ChannelInfo.ChannelList =
13792 &operatingChannel;
13793 pRoamProfile->ChannelInfo.numOfChannels = 1;
13794 } else {
13795 pRoamProfile->ChannelInfo.ChannelList = NULL;
13796 pRoamProfile->ChannelInfo.numOfChannels = 0;
13797 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013798 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013799 && operatingChannel) {
13800 /*
13801 * Need to post the IBSS power save parameters
13802 * to WMA. WMA will configure this parameters
13803 * to firmware if power save is enabled by the
13804 * firmware.
13805 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013806 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013807
Abhishek Singh471652b2017-04-14 12:28:32 +053013808 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013809 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013810 status = -EINVAL;
13811 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013812 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013813 pRoamProfile->ch_params.ch_width =
13814 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013815 /*
13816 * In IBSS mode while operating in 2.4 GHz,
13817 * the device supports only 20 MHz.
13818 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013819 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013820 pRoamProfile->ch_params.ch_width =
13821 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013822 hdd_select_cbmode(pAdapter, operatingChannel,
13823 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013824 }
13825
Abhishek Singhcfb44482017-03-10 12:42:37 +053013826 if (wlan_hdd_cfg80211_check_pmf_valid(
13827 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013828 status = -EINVAL;
13829 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013830 }
13831
Krunal Soni31949422016-07-29 17:17:53 -070013832 /*
13833 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013834 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013835 * enhancements, the supplicant is not issuing the scan command
13836 * now. So the unicast frames which are sent from the host are
13837 * not having the additional IEs. If it is P2P CLIENT and there
13838 * is no additional IE present in roamProfile, then use the
13839 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013840 */
13841
Krunal Sonib4326f22016-03-10 13:05:51 -080013842 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013843 (!pRoamProfile->pAddIEScan)) {
13844 pRoamProfile->pAddIEScan =
13845 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13846 pRoamProfile->nAddIEScanLength =
13847 pAdapter->scan_info.scanAddIE.length;
13848 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013849
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013850 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13851 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013852 pRoamProfile))) {
13853 hdd_err("sap-sta conc will fail, can't allow sta");
13854 hdd_conn_set_connection_state(pAdapter,
13855 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013856 status = -ENOMEM;
13857 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013858 }
13859
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013860 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013861 if (!sme_config) {
13862 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013863 hdd_conn_set_connection_state(pAdapter,
13864 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013865 status = -ENOMEM;
13866 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013867 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013868 sme_get_config_param(pHddCtx->hHal, sme_config);
13869 /* These values are not sessionized. So, any change in these SME
13870 * configs on an older or parallel interface will affect the
13871 * cb mode. So, restoring the default INI params before starting
13872 * interfaces such as sta, cli etc.,
13873 */
13874 sme_config->csrConfig.channelBondingMode5GHz =
13875 pHddCtx->config->nChannelBondingMode5GHz;
13876 sme_config->csrConfig.channelBondingMode24GHz =
13877 pHddCtx->config->nChannelBondingMode24GHz;
13878 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013879 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013880 /*
13881 * Change conn_state to connecting before sme_roam_connect(),
13882 * because sme_roam_connect() has a direct path to call
13883 * hdd_sme_roam_callback(), which will change the conn_state
13884 * If direct path, conn_state will be accordingly changed to
13885 * NotConnected or Associated by either
13886 * hdd_association_completion_handler() or
13887 * hdd_dis_connect_handler() in sme_RoamCallback()if
13888 * sme_RomConnect is to be queued,
13889 * Connecting state will remain until it is completed.
13890 *
13891 * If connection state is not changed, connection state will
13892 * remain in eConnectionState_NotConnected state.
13893 * In hdd_association_completion_handler, "hddDisconInProgress"
13894 * is set to true if conn state is
13895 * eConnectionState_NotConnected.
13896 * If "hddDisconInProgress" is set to true then cfg80211 layer
13897 * is not informed of connect result indication which
13898 * is an issue.
13899 */
13900 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013901 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013902 hdd_conn_set_connection_state(pAdapter,
13903 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013904
Komal Seelama89be8d2016-09-29 11:09:26 +053013905 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13906 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013907 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013908 pAdapter->sessionId, pRoamProfile,
13909 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013910 if (QDF_IS_STATUS_ERROR(qdf_status))
13911 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013912
Rajeev Kumard31e1542017-01-13 14:37:42 -080013913 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013914 (QDF_STA_MODE == pAdapter->device_mode ||
13915 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013916 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013917 "qdf_status %d. -> NotConnected",
13918 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013919 /* change back to NotAssociated */
13920 hdd_conn_set_connection_state(pAdapter,
13921 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013922 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13923 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013924 }
13925
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013926 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013927 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013928
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013929 pRoamProfile->ChannelInfo.ChannelList = NULL;
13930 pRoamProfile->ChannelInfo.numOfChannels = 0;
13931
Nitesh Shah044fd672016-10-13 18:53:25 +053013932 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013933 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13934 && !policy_mgr_is_hw_dbs_2x2_capable(
13935 pHddCtx->hdd_psoc)) {
13936 policy_mgr_get_channel_from_scan_result(
13937 pHddCtx->hdd_psoc,
13938 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013939 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013940 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013941 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13942 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013943 }
13944
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013945 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013946 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013947 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013948 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013949 goto ret_status;
13950
13951conn_failure:
13952 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013953 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013954
13955ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013956 EXIT();
13957 return status;
13958}
13959
13960/**
13961 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13962 * @pAdapter: Pointer to adapter
13963 * @auth_type: Auth type
13964 *
13965 * This function is used to set the authentication type (OPEN/SHARED).
13966 *
13967 * Return: 0 for success, non-zero for failure
13968 */
13969static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13970 enum nl80211_auth_type auth_type)
13971{
13972 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13973 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13974
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013975 /*set authentication type */
13976 switch (auth_type) {
13977 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013978 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013979 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13980 break;
13981
13982 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013983 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013984 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013985 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13986 break;
13987
13988 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013989 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013990 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13991 break;
13992#ifdef FEATURE_WLAN_ESE
13993 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013994 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013995 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13996 break;
13997#endif
13998
13999 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014000 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014001 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
14002 return -EINVAL;
14003 }
14004
14005 pWextState->roamProfile.AuthType.authType[0] =
14006 pHddStaCtx->conn_info.authType;
14007 return 0;
14008}
14009
14010/**
14011 * wlan_hdd_set_akm_suite() - set key management type
14012 * @pAdapter: Pointer to adapter
14013 * @key_mgmt: Key management type
14014 *
14015 * This function is used to set the key mgmt type(PSK/8021x).
14016 *
14017 * Return: 0 for success, non-zero for failure
14018 */
14019static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
14020{
14021 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14022
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053014023#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014024#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053014025#endif
14026#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014027#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053014028#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014029 /*set key mgmt type */
14030 switch (key_mgmt) {
14031 case WLAN_AKM_SUITE_PSK:
14032 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014033 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014034 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014035 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
14036 break;
14037
14038 case WLAN_AKM_SUITE_8021X_SHA256:
14039 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014040 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014041 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014042 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
14043 break;
14044#ifdef FEATURE_WLAN_ESE
14045#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
14046#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
14047 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014048 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014049 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
14050 break;
14051#endif
14052#ifndef WLAN_AKM_SUITE_OSEN
14053#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
14054#endif
14055 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014056 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014057 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
14058 break;
14059
14060 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014061 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014062 return -EINVAL;
14063
14064 }
14065 return 0;
14066}
14067
14068/**
14069 * wlan_hdd_cfg80211_set_cipher() - set encryption type
14070 * @pAdapter: Pointer to adapter
14071 * @cipher: Cipher type
14072 * @ucast: Unicast flag
14073 *
14074 * This function is used to set the encryption type
14075 * (NONE/WEP40/WEP104/TKIP/CCMP).
14076 *
14077 * Return: 0 for success, non-zero for failure
14078 */
14079static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
14080 u32 cipher, bool ucast)
14081{
14082 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14083 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14084 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14085
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014086 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014087 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014088 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14089 } else {
14090
14091 /*set encryption method */
14092 switch (cipher) {
14093 case IW_AUTH_CIPHER_NONE:
14094 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14095 break;
14096
14097 case WLAN_CIPHER_SUITE_WEP40:
14098 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
14099 break;
14100
14101 case WLAN_CIPHER_SUITE_WEP104:
14102 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
14103 break;
14104
14105 case WLAN_CIPHER_SUITE_TKIP:
14106 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
14107 break;
14108
14109 case WLAN_CIPHER_SUITE_CCMP:
14110 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14111 break;
14112#ifdef FEATURE_WLAN_WAPI
14113 case WLAN_CIPHER_SUITE_SMS4:
14114 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
14115 break;
14116#endif
14117
14118#ifdef FEATURE_WLAN_ESE
14119 case WLAN_CIPHER_SUITE_KRK:
14120 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
14121 break;
14122#ifdef WLAN_FEATURE_ROAM_OFFLOAD
14123 case WLAN_CIPHER_SUITE_BTK:
14124 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
14125 break;
14126#endif
14127#endif
14128 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014129 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014130 return -EOPNOTSUPP;
14131 }
14132 }
14133
14134 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014135 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014136 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14137 pWextState->roamProfile.EncryptionType.numEntries = 1;
14138 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14139 encryptionType;
14140 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014141 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014142 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
14143 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
14144 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
14145 encryptionType;
14146 }
14147
14148 return 0;
14149}
14150
14151/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014152 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
14153 * @wext_state: Pointer to wext state
14154 * @gen_ie: Pointer to IE data
14155 * @len: length of IE data
14156 *
14157 * Return: 0 for success, non-zero for failure
14158 */
14159static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
14160 const uint8_t *gen_ie, uint16_t len)
14161{
14162 uint16_t cur_add_ie_len =
14163 wext_state->assocAddIE.length;
14164
14165 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14166 (wext_state->assocAddIE.length + len)) {
14167 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
14168 QDF_ASSERT(0);
14169 return -ENOMEM;
14170 }
14171 memcpy(wext_state->assocAddIE.addIEdata +
14172 cur_add_ie_len, gen_ie, len);
14173 wext_state->assocAddIE.length += len;
14174
14175 wext_state->roamProfile.pAddIEAssoc =
14176 wext_state->assocAddIE.addIEdata;
14177 wext_state->roamProfile.nAddIEAssocLength =
14178 wext_state->assocAddIE.length;
14179 return 0;
14180}
14181
14182/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014183 * wlan_hdd_cfg80211_set_ie() - set IEs
14184 * @pAdapter: Pointer to adapter
14185 * @ie: Pointer ot ie
14186 * @ie: IE length
14187 *
14188 * Return: 0 for success, non-zero for failure
14189 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014190static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014191 size_t ie_len)
14192{
14193 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14194 const uint8_t *genie = ie;
14195 uint16_t remLen = ie_len;
14196#ifdef FEATURE_WLAN_WAPI
14197 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
14198 u16 *tmp;
14199 uint16_t akmsuiteCount;
14200 int *akmlist;
14201#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014202 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014203
14204 /* clear previous assocAddIE */
14205 pWextState->assocAddIE.length = 0;
14206 pWextState->roamProfile.bWPSAssociation = false;
14207 pWextState->roamProfile.bOSENAssociation = false;
14208
14209 while (remLen >= 2) {
14210 uint16_t eLen = 0;
14211 uint8_t elementId;
14212 elementId = *genie++;
14213 eLen = *genie++;
14214 remLen -= 2;
14215
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014216 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014217
14218 switch (elementId) {
14219 case DOT11F_EID_WPA:
14220 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 -070014221 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014222 return -EINVAL;
14223 } else if (0 ==
14224 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
14225 uint16_t curAddIELen =
14226 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014227 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014228
14229 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14230 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014231 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014232 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014233 return -ENOMEM;
14234 }
14235 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
14236 memcpy(pWextState->assocAddIE.addIEdata +
14237 curAddIELen, genie - 2, eLen + 2);
14238 pWextState->assocAddIE.length += eLen + 2;
14239
14240 pWextState->roamProfile.bWPSAssociation = true;
14241 pWextState->roamProfile.pAddIEAssoc =
14242 pWextState->assocAddIE.addIEdata;
14243 pWextState->roamProfile.nAddIEAssocLength =
14244 pWextState->assocAddIE.length;
14245 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014246 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014247 memset(pWextState->WPARSNIE, 0,
14248 MAX_WPA_RSN_IE_LEN);
14249 memcpy(pWextState->WPARSNIE, genie - 2,
14250 (eLen + 2));
14251 pWextState->roamProfile.pWPAReqIE =
14252 pWextState->WPARSNIE;
14253 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
14254 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
14255 P2P_OUI_TYPE_SIZE))) {
14256 uint16_t curAddIELen =
14257 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014258 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014259
14260 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14261 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014262 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014263 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014264 return -ENOMEM;
14265 }
14266 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
14267 memcpy(pWextState->assocAddIE.addIEdata +
14268 curAddIELen, genie - 2, eLen + 2);
14269 pWextState->assocAddIE.length += eLen + 2;
14270
14271 pWextState->roamProfile.pAddIEAssoc =
14272 pWextState->assocAddIE.addIEdata;
14273 pWextState->roamProfile.nAddIEAssocLength =
14274 pWextState->assocAddIE.length;
14275 }
14276#ifdef WLAN_FEATURE_WFD
14277 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
14278 WFD_OUI_TYPE_SIZE)) &&
14279 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080014280 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014281 pAdapter->device_mode)) {
14282 uint16_t curAddIELen =
14283 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014284 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014285
14286 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14287 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014288 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014289 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014290 return -ENOMEM;
14291 }
14292 /* WFD IE is saved to Additional IE ; it should
14293 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014294 * WFD IE
14295 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014296 memcpy(pWextState->assocAddIE.addIEdata +
14297 curAddIELen, genie - 2, eLen + 2);
14298 pWextState->assocAddIE.length += eLen + 2;
14299
14300 pWextState->roamProfile.pAddIEAssoc =
14301 pWextState->assocAddIE.addIEdata;
14302 pWextState->roamProfile.nAddIEAssocLength =
14303 pWextState->assocAddIE.length;
14304 }
14305#endif
14306 /* Appending HS 2.0 Indication Element in Assiciation Request */
14307 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
14308 HS20_OUI_TYPE_SIZE))) {
14309 uint16_t curAddIELen =
14310 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014311 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014312
14313 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14314 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014315 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014316 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014317 return -ENOMEM;
14318 }
14319 memcpy(pWextState->assocAddIE.addIEdata +
14320 curAddIELen, genie - 2, eLen + 2);
14321 pWextState->assocAddIE.length += eLen + 2;
14322
14323 pWextState->roamProfile.pAddIEAssoc =
14324 pWextState->assocAddIE.addIEdata;
14325 pWextState->roamProfile.nAddIEAssocLength =
14326 pWextState->assocAddIE.length;
14327 }
14328 /* Appending OSEN Information Element in Assiciation Request */
14329 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
14330 OSEN_OUI_TYPE_SIZE))) {
14331 uint16_t curAddIELen =
14332 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014333 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014334
14335 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14336 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014337 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014338 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014339 return -ENOMEM;
14340 }
14341 memcpy(pWextState->assocAddIE.addIEdata +
14342 curAddIELen, genie - 2, eLen + 2);
14343 pWextState->assocAddIE.length += eLen + 2;
14344
14345 pWextState->roamProfile.bOSENAssociation = true;
14346 pWextState->roamProfile.pAddIEAssoc =
14347 pWextState->assocAddIE.addIEdata;
14348 pWextState->roamProfile.nAddIEAssocLength =
14349 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014350 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
14351 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014352 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014353 status = wlan_hdd_add_assoc_ie(pWextState,
14354 genie - 2, eLen + 2);
14355 if (status)
14356 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014357 } else {
14358 uint16_t add_ie_len =
14359 pWextState->assocAddIE.length;
14360
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014361 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014362
14363 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14364 (pWextState->assocAddIE.length + eLen)) {
14365 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014366 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014367 return -ENOMEM;
14368 }
14369
14370 memcpy(pWextState->assocAddIE.addIEdata +
14371 add_ie_len, genie - 2, eLen + 2);
14372 pWextState->assocAddIE.length += eLen + 2;
14373
14374 pWextState->roamProfile.pAddIEAssoc =
14375 pWextState->assocAddIE.addIEdata;
14376 pWextState->roamProfile.nAddIEAssocLength =
14377 pWextState->assocAddIE.length;
14378 }
14379 break;
14380 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014381 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014382 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
14383 memcpy(pWextState->WPARSNIE, genie - 2,
14384 (eLen + 2));
14385 pWextState->roamProfile.pRSNReqIE =
14386 pWextState->WPARSNIE;
14387 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
14388 break;
14389 /*
14390 * Appending Extended Capabilities with Interworking bit set
14391 * in Assoc Req.
14392 *
14393 * In assoc req this EXT Cap will only be taken into account if
14394 * interworkingService bit is set to 1. Currently
14395 * driver is only interested in interworkingService capability
14396 * from supplicant. If in future any other EXT Cap info is
14397 * required from supplicat, it needs to be handled while
14398 * sending Assoc Req in LIM.
14399 */
14400 case DOT11F_EID_EXTCAP:
14401 {
14402 uint16_t curAddIELen =
14403 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014404 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014405
14406 if (SIR_MAC_MAX_ADD_IE_LENGTH <
14407 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070014408 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014409 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014410 return -ENOMEM;
14411 }
14412 memcpy(pWextState->assocAddIE.addIEdata +
14413 curAddIELen, genie - 2, eLen + 2);
14414 pWextState->assocAddIE.length += eLen + 2;
14415
14416 pWextState->roamProfile.pAddIEAssoc =
14417 pWextState->assocAddIE.addIEdata;
14418 pWextState->roamProfile.nAddIEAssocLength =
14419 pWextState->assocAddIE.length;
14420 break;
14421 }
14422#ifdef FEATURE_WLAN_WAPI
14423 case WLAN_EID_WAPI:
14424 /* Setting WAPI Mode to ON=1 */
14425 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014426 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014427 tmp = (u16 *) ie;
14428 tmp = tmp + 2; /* Skip element Id and Len, Version */
14429 akmsuiteCount = WPA_GET_LE16(tmp);
14430 tmp = tmp + 1;
14431 akmlist = (int *)(tmp);
14432 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
14433 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
14434 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014435 hdd_err("Invalid akmSuite count: %u",
14436 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014437 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014438 return -EINVAL;
14439 }
14440
14441 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014442 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014443 pAdapter->wapi_info.wapiAuthMode =
14444 WAPI_AUTH_MODE_PSK;
14445 }
14446 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014447 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014448 pAdapter->wapi_info.wapiAuthMode =
14449 WAPI_AUTH_MODE_CERT;
14450 }
14451 break;
14452#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014453 case DOT11F_EID_SUPPOPERATINGCLASSES:
14454 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014455 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053014456 status = wlan_hdd_add_assoc_ie(pWextState,
14457 genie - 2, eLen + 2);
14458 if (status)
14459 return status;
14460 break;
14461 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014462 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014463 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014464 /* when Unknown IE is received we break
14465 * and continue to the next IE in the buffer
14466 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014467 break;
14468 }
14469 genie += eLen;
14470 remLen -= eLen;
14471 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014472 return 0;
14473}
14474
14475/**
14476 * hdd_is_wpaie_present() - check for WPA ie
14477 * @ie: Pointer to ie
14478 * @ie_len: Ie length
14479 *
14480 * Parse the received IE to find the WPA IE
14481 *
14482 * Return: true if wpa ie is found else false
14483 */
14484static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
14485{
14486 uint8_t eLen = 0;
14487 uint16_t remLen = ie_len;
14488 uint8_t elementId = 0;
14489
14490 while (remLen >= 2) {
14491 elementId = *ie++;
14492 eLen = *ie++;
14493 remLen -= 2;
14494 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014495 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014496 return false;
14497 }
14498 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
14499 /* OUI - 0x00 0X50 0XF2
14500 * WPA Information Element - 0x01
14501 * WPA version - 0x01
14502 */
14503 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
14504 return true;
14505 }
14506 ie += eLen;
14507 remLen -= eLen;
14508 }
14509 return false;
14510}
14511
14512/**
14513 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
14514 * @pAdapter: Pointer to adapter
14515 * @req: Pointer to security parameters
14516 *
14517 * Return: 0 for success, non-zero for failure
14518 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014519static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
14520 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014521{
14522 int status = 0;
14523 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14524 ENTER();
14525
14526 /*set wpa version */
14527 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
14528
14529 if (req->crypto.wpa_versions) {
14530 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
14531 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
14532 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
14533 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14534 }
14535 }
14536
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014537 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014538
14539 /*set authentication type */
14540 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
14541
14542 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014543 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014544 return status;
14545 }
14546
14547 /*set key mgmt type */
14548 if (req->crypto.n_akm_suites) {
14549 status =
14550 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
14551 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014552 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014553 return status;
14554 }
14555 }
14556
14557 /*set pairwise cipher type */
14558 if (req->crypto.n_ciphers_pairwise) {
14559 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
14560 req->crypto.
14561 ciphers_pairwise[0],
14562 true);
14563 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014564 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014565 return status;
14566 }
14567 } else {
14568 /*Reset previous cipher suite to none */
14569 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
14570 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014571 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014572 return status;
14573 }
14574 }
14575
14576 /*set group cipher type */
14577 status =
14578 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
14579 false);
14580
14581 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014582 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014583 return status;
14584 }
14585#ifdef WLAN_FEATURE_11W
14586 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
14587#endif
14588
14589 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
14590 if (req->ie_len) {
14591 status =
14592 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
14593 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014594 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014595 return status;
14596 }
14597 }
14598
14599 /*incase of WEP set default key information */
14600 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080014601 u8 key_len = req->key_len;
14602 u8 key_idx = req->key_idx;
14603
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014604 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
14605 || (WLAN_CIPHER_SUITE_WEP104 ==
14606 req->crypto.ciphers_pairwise[0])
14607 ) {
14608 if (IW_AUTH_KEY_MGMT_802_1X
14609 ==
14610 (pWextState->
14611 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014612 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014613 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014614 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014615
Jeff Johnson68755312017-02-10 11:46:55 -080014616 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14617 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014618 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014619 key_idx, key_len);
14620 qdf_mem_copy(&pWextState->roamProfile.
14621 Keys.
14622 KeyMaterial[key_idx][0],
14623 req->key, key_len);
14624 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014625 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014626 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014627 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014628 }
14629 }
14630 }
14631
14632 return status;
14633}
14634
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014635int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014636{
14637 unsigned long rc;
14638 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014639 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014640 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014641
14642 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014643 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14644 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014645 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014646 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14647 }
14648 /*
14649 * If firmware has already started roaming process, driver
14650 * needs to defer the processing of this disconnect request.
14651 *
14652 */
14653 if (hdd_is_roaming_in_progress(pAdapter)) {
14654 /*
14655 * Defer the disconnect action until firmware roaming
14656 * result is received. If STA is in connected state after
14657 * that, send the disconnect command to CSR, otherwise
14658 * CSR would have already sent disconnect event to upper
14659 * layer.
14660 */
14661
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014662 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014663 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14664 pAdapter->cfg80211_disconnect_reason =
14665 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14666 return 0;
14667 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014668
Jeff Johnson9edf9572016-10-03 15:24:49 -070014669 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014670 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14671 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14672 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014673 hdd_conn_set_connection_state(pAdapter,
14674 eConnectionState_Disconnecting);
14675 /* Issue disconnect to CSR */
14676 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014677
14678 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14679 pAdapter->sessionId,
14680 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14681 /*
14682 * Wait here instead of returning directly, this will block the
14683 * next connect command and allow processing of the scan for
14684 * ssid and the previous connect command in CSR. Else we might
14685 * hit some race conditions leading to SME and HDD out of sync.
14686 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014687 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014688 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014689 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014690 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014691 (int)status);
14692 pHddStaCtx->staDebugState = status;
14693 result = -EINVAL;
14694 goto disconnected;
14695 }
14696
14697 rc = wait_for_completion_timeout(
14698 &pAdapter->disconnect_comp_var,
14699 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014700 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014701 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014702 pAdapter->sessionId, pHddStaCtx->staDebugState);
14703 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014704 }
14705 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014706 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014707 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014708 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014709 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014710 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014711 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014712 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014713 }
14714 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014715disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014716 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14717 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014718}
14719
14720/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014721 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14722 * @adapter: Pointer to the HDD adapter
14723 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014724 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014725 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014726 * This function will start reassociation if prev_bssid is set and bssid/
14727 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014728 *
Naveen Rawat07332902016-07-27 09:13:17 -070014729 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014730 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014731#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14732 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014733static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14734 struct cfg80211_connect_params *req,
14735 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014736{
Naveen Rawat07332902016-07-27 09:13:17 -070014737 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014738 const uint8_t *bssid = NULL;
14739 uint16_t channel = 0;
Arif Hussain43354e62017-05-24 11:24:25 -070014740 hdd_wext_state_t *wext_state = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014741
14742 if (req->bssid)
14743 bssid = req->bssid;
14744 else if (req->bssid_hint)
14745 bssid = req->bssid_hint;
14746
14747 if (req->channel)
14748 channel = req->channel->hw_value;
14749 else if (req->channel_hint)
14750 channel = req->channel_hint->hw_value;
14751
14752 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014753 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014754 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014755 channel, MAC_ADDR_ARRAY(bssid));
Arif Hussain43354e62017-05-24 11:24:25 -070014756 /*
14757 * Save BSSID in a separate variable as
14758 * pRoamProfile's BSSID is getting zeroed out in the
14759 * association process. In case of join failure
14760 * we should send valid BSSID to supplicant
14761 */
14762 qdf_mem_copy(wext_state->req_bssId.bytes, bssid,
14763 QDF_MAC_ADDR_SIZE);
14764
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014765 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014766 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014767 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014768 }
Naveen Rawat07332902016-07-27 09:13:17 -070014769 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014770}
14771#else
Naveen Rawat07332902016-07-27 09:13:17 -070014772static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14773 struct cfg80211_connect_params *req,
14774 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014775{
Naveen Rawat07332902016-07-27 09:13:17 -070014776 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014777}
14778#endif
14779
14780/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014781 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14782 * @wiphy: Pointer to wiphy
14783 * @dev: Pointer to network device
14784 * @req: Pointer to cfg80211 connect request
14785 *
14786 * This function is used to start the association process
14787 *
14788 * Return: 0 for success, non-zero for failure
14789 */
14790static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14791 struct net_device *ndev,
14792 struct cfg80211_connect_params *req)
14793{
14794 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014795 u16 channel;
14796#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14797 const u8 *bssid_hint = req->bssid_hint;
14798#else
14799 const u8 *bssid_hint = NULL;
14800#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014801 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14802 hdd_context_t *pHddCtx;
14803
14804 ENTER();
14805
Anurag Chouhan6d760662016-02-20 16:05:43 +053014806 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014807 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014808 return -EINVAL;
14809 }
14810
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014811 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14812 hdd_err("invalid session id: %d", pAdapter->sessionId);
14813 return -EINVAL;
14814 }
14815
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014816 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014817 TRACE_CODE_HDD_CFG80211_CONNECT,
14818 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014819 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014820 hdd_device_mode_to_string(pAdapter->device_mode),
14821 pAdapter->device_mode);
14822
Krunal Sonib4326f22016-03-10 13:05:51 -080014823 if (pAdapter->device_mode != QDF_STA_MODE &&
14824 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014825 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014826 hdd_device_mode_to_string(pAdapter->device_mode),
14827 pAdapter->device_mode);
14828 return -EINVAL;
14829 }
14830
14831 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14832 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014833 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014834 return -EINVAL;
14835 }
14836
14837 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014838 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014839 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014840
Naveen Rawat07332902016-07-27 09:13:17 -070014841 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014842 return status;
14843
Agrawal Ashishf156e942016-08-04 14:54:47 +053014844 /* Try disconnecting if already in connected state */
14845 status = wlan_hdd_try_disconnect(pAdapter);
14846 if (0 > status) {
14847 hdd_err("Failed to disconnect the existing connection");
14848 return -EALREADY;
14849 }
14850
14851 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014852 if (req->channel) {
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053014853 bool ok;
14854
14855 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
14856 pHddCtx->hdd_psoc,
14857 req->channel->hw_value,
14858 &ok)) {
14859 hdd_warn("Unable to get channel:%d eligibility for DNBS",
14860 req->channel->hw_value);
14861 return -EINVAL;
14862 }
14863 /**
14864 * Send connection timedout, so that Android framework does not
14865 * blacklist us.
14866 */
14867 if (!ok) {
14868 struct ieee80211_channel *chan =
14869 __ieee80211_get_channel(wiphy,
14870 wlan_chan_to_freq(req->channel->hw_value));
14871 struct cfg80211_bss *bss;
14872
14873 hdd_warn("Channel:%d not OK for DNBS",
14874 req->channel->hw_value);
14875 if (chan) {
14876 bss = hdd_cfg80211_get_bss(wiphy,
14877 chan,
14878 req->bssid, req->ssid,
14879 req->ssid_len);
14880 if (bss) {
14881 cfg80211_assoc_timeout(ndev, bss);
14882 return -ETIMEDOUT;
14883 }
14884 }
14885 return -EINVAL;
14886 }
14887
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014888 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14889 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014890 pAdapter->device_mode),
14891 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014892 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014893 return -ECONNREFUSED;
14894 }
14895 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014896 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14897 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014898 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014899 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014900 return -ECONNREFUSED;
14901 }
14902 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014903
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014904 /*initialise security parameters */
14905 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14906
14907 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014908 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014909 return status;
14910 }
14911
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014912 if (req->channel)
14913 channel = req->channel->hw_value;
14914 else
14915 channel = 0;
14916 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14917 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014918 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014919 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014920 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014921 return status;
14922 }
14923 EXIT();
14924 return status;
14925}
14926
14927/**
14928 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14929 * @wiphy: Pointer to wiphy
14930 * @dev: Pointer to network device
14931 * @req: Pointer to cfg80211 connect request
14932 *
14933 * Return: 0 for success, non-zero for failure
14934 */
14935static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14936 struct net_device *ndev,
14937 struct cfg80211_connect_params *req)
14938{
14939 int ret;
14940 cds_ssr_protect(__func__);
14941 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14942 cds_ssr_unprotect(__func__);
14943
14944 return ret;
14945}
14946
14947/**
14948 * wlan_hdd_disconnect() - hdd disconnect api
14949 * @pAdapter: Pointer to adapter
14950 * @reason: Disconnect reason code
14951 *
14952 * This function is used to issue a disconnect request to SME
14953 *
14954 * Return: 0 for success, non-zero for failure
14955 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014956static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014957{
14958 int status, result = 0;
14959 unsigned long rc;
14960 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14961 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014962 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014963 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014964
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014965 ENTER();
14966
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014967 status = wlan_hdd_validate_context(pHddCtx);
14968
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014969 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014970 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014971 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014972 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014973 status = sme_stop_roaming(hal, pAdapter->sessionId,
14974 eCsrHddIssued);
14975 }
14976 /*
14977 * If firmware has already started roaming process, driver
14978 * needs to defer the processing of this disconnect request.
14979 */
14980 if (hdd_is_roaming_in_progress(pAdapter)) {
14981 /*
14982 * Defer the disconnect action until firmware roaming
14983 * result is received. If STA is in connected state after
14984 * that, send the disconnect command to CSR, otherwise
14985 * CSR would have already sent disconnect event to upper
14986 * layer.
14987 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014988 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014989 pAdapter->defer_disconnect =
14990 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14991 pAdapter->cfg80211_disconnect_reason = reason;
14992 return 0;
14993 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014994
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014995 prev_conn_state = pHddStaCtx->conn_info.connState;
14996
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014997 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014998 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014999 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053015000 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015001 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015002 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
15003 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15004
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080015005 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015006
15007 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15008 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053015009 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
15010 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015011 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053015012 result = 0;
15013 goto disconnected;
15014 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
15015 /*
15016 * Wait here instead of returning directly, this will block the
15017 * next connect command and allow processing of the scan for
15018 * ssid and the previous connect command in CSR. Else we might
15019 * hit some race conditions leading to SME and HDD out of sync.
15020 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015021 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015022 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015023 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015024 pHddStaCtx->staDebugState = status;
15025 result = -EINVAL;
15026 goto disconnected;
15027 }
15028 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15029 msecs_to_jiffies
15030 (WLAN_WAIT_TIME_DISCONNECT));
15031
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015032 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015033 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015034 result = -ETIMEDOUT;
15035 }
15036disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015037 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
15038#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
15039 /* Sending disconnect event to userspace for kernel version < 3.11
15040 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
15041 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015042 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053015043 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
15044 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015045#endif
15046
15047 return result;
15048}
15049
15050/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080015051 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
15052 * @reason: ieee80211 reason code.
15053 *
15054 * This utility function helps log string conversion of reason code.
15055 *
15056 * Return: string conversion of reason code, if match found;
15057 * "Unknown" otherwise.
15058 */
15059static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
15060{
15061 switch (reason) {
15062 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
15063 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
15064 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
15065 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
15066 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
15067 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
15068 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
15069 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
15070 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
15071 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
15072 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
15073 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
15074 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
15075 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
15076 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
15077 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
15078 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
15079 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
15080 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
15081 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
15082 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
15083 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
15084 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
15085 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
15086 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
15087 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
15088 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
15089 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
15090 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
15091 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
15092 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
15093 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
15094 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
15095 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
15096 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
15097 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
15098 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
15099 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
15100 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
15101 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
15102 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
15103 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
15104 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
15105 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
15106 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
15107 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
15108 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
15109 default:
15110 return "Unknown";
15111 }
15112}
15113
15114/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015115 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
15116 * @wiphy: Pointer to wiphy
15117 * @dev: Pointer to network device
15118 * @reason: Disconnect reason code
15119 *
15120 * This function is used to issue a disconnect request to SME
15121 *
15122 * Return: 0 for success, non-zero for failure
15123 */
15124static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
15125 struct net_device *dev, u16 reason)
15126{
15127 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15128 int status;
15129 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15130 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15131#ifdef FEATURE_WLAN_TDLS
15132 uint8_t staIdx;
15133#endif
15134
15135 ENTER();
15136
Anurag Chouhan6d760662016-02-20 16:05:43 +053015137 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015138 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015139 return -EINVAL;
15140 }
15141
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015142 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015143 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015144 return -EINVAL;
15145 }
15146
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015147 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015148 TRACE_CODE_HDD_CFG80211_DISCONNECT,
15149 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015150 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015151 hdd_device_mode_to_string(pAdapter->device_mode),
15152 pAdapter->device_mode, reason);
15153
15154 status = wlan_hdd_validate_context(pHddCtx);
15155
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015156 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015157 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015158
15159 /* Issue disconnect request to SME, if station is in connected state */
15160 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
15161 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
15162 eCsrRoamDisconnectReason reasonCode =
15163 eCSR_DISCONNECT_REASON_UNSPECIFIED;
15164 hdd_scaninfo_t *pScanInfo;
15165
15166 switch (reason) {
15167 case WLAN_REASON_MIC_FAILURE:
15168 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
15169 break;
15170
15171 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
15172 case WLAN_REASON_DISASSOC_AP_BUSY:
15173 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
15174 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
15175 break;
15176
15177 case WLAN_REASON_PREV_AUTH_NOT_VALID:
15178 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
15179 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
15180 break;
15181
15182 case WLAN_REASON_DEAUTH_LEAVING:
15183 reasonCode =
15184 pHddCtx->config->
15185 gEnableDeauthToDisassocMap ?
15186 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
15187 eCSR_DISCONNECT_REASON_DEAUTH;
15188 break;
15189 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
15190 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
15191 break;
15192 default:
15193 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
15194 break;
15195 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015196 pScanInfo = &pAdapter->scan_info;
15197 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015198 hdd_debug("Disconnect is in progress, Aborting Scan");
Abhishek Singh69ccb512017-04-25 11:58:16 +053015199 wlan_abort_scan(pHddCtx->hdd_pdev, INVAL_PDEV_ID,
15200 pAdapter->sessionId, INVALID_SCAN_ID, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015201 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053015202 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015203#ifdef FEATURE_WLAN_TDLS
15204 /* First clean up the tdls peers if any */
15205 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
15206 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
15207 pAdapter->sessionId)
15208 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
15209 uint8_t *mac;
15210 mac =
15211 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015212 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015213 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015214 pHddCtx->tdlsConnInfo[staIdx].staId,
15215 pAdapter->sessionId,
15216 MAC_ADDR_ARRAY(mac));
15217 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
15218 (pAdapter),
15219 pAdapter->sessionId, mac);
15220 }
15221 }
Kabilan Kannanaad2f032017-05-08 13:25:37 -070015222 hdd_notify_sta_disconnect(pAdapter->sessionId,
15223 true, pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015224#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070015225 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
15226 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015227 status = wlan_hdd_disconnect(pAdapter, reasonCode);
15228 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015229 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015230 return -EINVAL;
15231 }
15232 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015233 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015234 pHddStaCtx->conn_info.connState);
15235 }
15236
15237 return status;
15238}
15239
15240/**
15241 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
15242 * @wiphy: Pointer to wiphy
15243 * @dev: Pointer to network device
15244 * @reason: Disconnect reason code
15245 *
15246 * Return: 0 for success, non-zero for failure
15247 */
15248static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
15249 struct net_device *dev, u16 reason)
15250{
15251 int ret;
15252 cds_ssr_protect(__func__);
15253 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
15254 cds_ssr_unprotect(__func__);
15255
15256 return ret;
15257}
15258
15259/**
15260 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
15261 * @pAdapter: Pointer to adapter
15262 * @param: Pointer to IBSS parameters
15263 *
15264 * This function is used to initialize the security settings in IBSS mode
15265 *
15266 * Return: 0 for success, non-zero for failure
15267 */
15268static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
15269 struct cfg80211_ibss_params
15270 *params)
15271{
15272 int status = 0;
15273 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15274 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
15275 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15276
15277 ENTER();
15278
15279 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015280 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015281 pHddStaCtx->ibss_enc_key_installed = 0;
15282
15283 if (params->ie_len && (NULL != params->ie)) {
15284 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
15285 params->ie_len, WLAN_EID_RSN)) {
15286 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
15287 encryptionType = eCSR_ENCRYPT_TYPE_AES;
15288 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
15289 tDot11fIEWPA dot11WPAIE;
15290 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15291 u8 *ie;
15292
15293 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
15294 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
15295 params->ie_len,
15296 DOT11F_EID_WPA);
15297 if (NULL != ie) {
15298 pWextState->wpaVersion =
15299 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015300 /* Unpack the WPA IE
15301 * Skip past the EID byte and length byte
15302 * and four byte WiFi OUI
15303 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015304 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053015305 &ie[2 + 4], ie[1] - 4,
15306 &dot11WPAIE, false);
15307 /*
15308 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015309 * encType for unicast cipher for
15310 * wpa-none is none
15311 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015312 encryptionType =
15313 hdd_translate_wpa_to_csr_encryption_type
15314 (dot11WPAIE.multicast_cipher);
15315 }
15316 }
15317
15318 status =
15319 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
15320 params->ie_len);
15321
15322 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015323 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015324 return status;
15325 }
15326 }
15327
15328 pWextState->roamProfile.AuthType.authType[0] =
15329 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
15330
15331 if (params->privacy) {
15332 /* Security enabled IBSS, At this time there is no information
15333 * available about the security paramters, so initialise the
15334 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
15335 * The correct security parameters will be updated later in
15336 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
15337 * set inorder enable privacy bit in beacons
15338 */
15339
15340 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
15341 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015342 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015343 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
15344 pWextState->roamProfile.EncryptionType.numEntries = 1;
15345 pWextState->roamProfile.EncryptionType.encryptionType[0] =
15346 encryptionType;
15347 return status;
15348}
15349
15350/**
15351 * __wlan_hdd_cfg80211_join_ibss() - join ibss
15352 * @wiphy: Pointer to wiphy
15353 * @dev: Pointer to network device
15354 * @param: Pointer to IBSS join parameters
15355 *
15356 * This function is used to create/join an IBSS network
15357 *
15358 * Return: 0 for success, non-zero for failure
15359 */
15360static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15361 struct net_device *dev,
15362 struct cfg80211_ibss_params *params)
15363{
15364 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15365 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15366 tCsrRoamProfile *pRoamProfile;
15367 int status;
15368 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15369 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053015370 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015371 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015372
15373 ENTER();
15374
Anurag Chouhan6d760662016-02-20 16:05:43 +053015375 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015376 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015377 return -EINVAL;
15378 }
15379
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015380 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015381 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015382 return -EINVAL;
15383 }
15384
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015385 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015386 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
15387 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015388 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015389 hdd_device_mode_to_string(pAdapter->device_mode),
15390 pAdapter->device_mode);
15391
15392 status = wlan_hdd_validate_context(pHddCtx);
15393
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015394 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015395 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015396
15397 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053015398 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015399 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
15400 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
15401 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15402 int indx;
15403
15404 /* Get channel number */
15405 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015406 params->
15407 chandef.
15408 chan->
15409 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015410
15411 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
15412 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015413 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015414 return -EOPNOTSUPP;
15415 }
15416
15417 for (indx = 0; indx < numChans; indx++) {
15418 if (channelNum == validChan[indx]) {
15419 break;
15420 }
15421 }
15422 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015423 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015424 return -EINVAL;
15425 }
15426 }
15427
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015428 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
15429 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015430 hdd_err("This concurrency combination is not allowed");
15431 return -ECONNREFUSED;
15432 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015433
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015434 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015435 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015436 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015437
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015438 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
15439 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070015440 SIR_UPDATE_REASON_JOIN_IBSS);
15441 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015442 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070015443 return -EINVAL;
15444 }
15445
15446 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080015447 status = policy_mgr_wait_for_connection_update(
15448 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070015449 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015450 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015451 return -EINVAL;
15452 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015453 }
15454
15455 /*Try disconnecting if already in connected state */
15456 status = wlan_hdd_try_disconnect(pAdapter);
15457 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015458 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015459 return -EALREADY;
15460 }
15461
15462 pRoamProfile = &pWextState->roamProfile;
15463
15464 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015465 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015466 return -EINVAL;
15467 }
15468
15469 /* enable selected protection checks in IBSS mode */
15470 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
15471
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015472 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015473 WNI_CFG_IBSS_ATIM_WIN_SIZE,
15474 pHddCtx->config->
15475 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015476 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015477 }
15478
15479 /* BSSID is provided by upper layers hence no need to AUTO generate */
15480 if (NULL != params->bssid) {
15481 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015482 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015483 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015484 return -EIO;
15485 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015486 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015487 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
15488 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015489 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015490 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015491 return -EIO;
15492 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053015493 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015494 }
15495 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
15496 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
15497 pRoamProfile->beaconInterval = params->beacon_interval;
15498 else {
15499 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015500 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015501 params->beacon_interval, pRoamProfile->beaconInterval);
15502 }
15503
15504 /* Set Channel */
15505 if (channelNum) {
15506 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015507 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015508 pRoamProfile->ChannelInfo.numOfChannels = 1;
15509 pHddStaCtx->conn_info.operationChannel = channelNum;
15510 pRoamProfile->ChannelInfo.ChannelList =
15511 &pHddStaCtx->conn_info.operationChannel;
15512 }
15513
15514 /* Initialize security parameters */
15515 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
15516 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015517 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015518 return status;
15519 }
15520
15521 /* Issue connect start */
15522 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
15523 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015524 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015525 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015526 operationChannel,
15527 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015528
15529 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015530 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015531 return status;
15532 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015533 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015534 return 0;
15535}
15536
15537/**
15538 * wlan_hdd_cfg80211_join_ibss() - join ibss
15539 * @wiphy: Pointer to wiphy
15540 * @dev: Pointer to network device
15541 * @param: Pointer to IBSS join parameters
15542 *
15543 * This function is used to create/join an IBSS network
15544 *
15545 * Return: 0 for success, non-zero for failure
15546 */
15547static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
15548 struct net_device *dev,
15549 struct cfg80211_ibss_params *params)
15550{
15551 int ret = 0;
15552
15553 cds_ssr_protect(__func__);
15554 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
15555 cds_ssr_unprotect(__func__);
15556
15557 return ret;
15558}
15559
15560/**
15561 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
15562 * @wiphy: Pointer to wiphy
15563 * @dev: Pointer to network device
15564 *
15565 * This function is used to leave an IBSS network
15566 *
15567 * Return: 0 for success, non-zero for failure
15568 */
15569static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15570 struct net_device *dev)
15571{
15572 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15573 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
15574 tCsrRoamProfile *pRoamProfile;
15575 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15576 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015577 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015578 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015579 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015580
15581 ENTER();
15582
Anurag Chouhan6d760662016-02-20 16:05:43 +053015583 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015584 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015585 return -EINVAL;
15586 }
15587
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015588 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015589 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015590 return -EINVAL;
15591 }
15592
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015593 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015594 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
15595 pAdapter->sessionId,
15596 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
15597 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015598 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015599 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015600
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015601 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015602 hdd_device_mode_to_string(pAdapter->device_mode),
15603 pAdapter->device_mode);
15604 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015605 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015606 return -EIO;
15607 }
15608
15609 pRoamProfile = &pWextState->roamProfile;
15610
15611 /* Issue disconnect only if interface type is set to IBSS */
15612 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015613 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015614 return -EINVAL;
15615 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015616 /* Clearing add IE of beacon */
15617 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
15618 sizeof(tSirMacAddr));
15619 updateIE.smeSessionId = pAdapter->sessionId;
15620 updateIE.ieBufferlength = 0;
15621 updateIE.pAdditionIEBuffer = NULL;
15622 updateIE.append = true;
15623 updateIE.notify = true;
15624 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
15625 &updateIE,
15626 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015627 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015628 }
15629
15630 /* Reset WNI_CFG_PROBE_RSP Flags */
15631 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015632
15633 /* Issue Disconnect request */
15634 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15635 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15636 pAdapter->sessionId,
15637 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015638 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015639 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015640 hal_status);
15641 return -EAGAIN;
15642 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015643
15644 /* wait for mc thread to cleanup and then return to upper stack
15645 * so by the time upper layer calls the change interface, we are
15646 * all set to proceed further
15647 */
15648 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15649 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
15650 if (!rc) {
15651 hdd_err("Failed to disconnect, timed out");
15652 return -ETIMEDOUT;
15653 }
15654
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015655 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015656 return 0;
15657}
15658
15659/**
15660 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15661 * @wiphy: Pointer to wiphy
15662 * @dev: Pointer to network device
15663 *
15664 * This function is used to leave an IBSS network
15665 *
15666 * Return: 0 for success, non-zero for failure
15667 */
15668static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15669 struct net_device *dev)
15670{
15671 int ret = 0;
15672
15673 cds_ssr_protect(__func__);
15674 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15675 cds_ssr_unprotect(__func__);
15676
15677 return ret;
15678}
15679
15680/**
15681 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15682 * @wiphy: Pointer to wiphy
15683 * @changed: Parameters changed
15684 *
15685 * This function is used to set the phy parameters. RTS Threshold/FRAG
15686 * Threshold/Retry Count etc.
15687 *
15688 * Return: 0 for success, non-zero for failure
15689 */
15690static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15691 u32 changed)
15692{
15693 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15694 tHalHandle hHal = pHddCtx->hHal;
15695 int status;
15696
15697 ENTER();
15698
Anurag Chouhan6d760662016-02-20 16:05:43 +053015699 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015700 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015701 return -EINVAL;
15702 }
15703
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015704 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015705 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15706 NO_SESSION, wiphy->rts_threshold));
15707 status = wlan_hdd_validate_context(pHddCtx);
15708
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015709 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015710 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015711
15712 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15713 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15714 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15715
15716 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15717 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015718 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015719 rts_threshold);
15720 return -EINVAL;
15721 }
15722
15723 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15724 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015725 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015726 rts_threshold);
15727 return -EIO;
15728 }
15729
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015730 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015731 }
15732
15733 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15734 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15735 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15736 wiphy->frag_threshold;
15737
15738 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15739 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015740 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015741 frag_threshold);
15742 return -EINVAL;
15743 }
15744
15745 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15746 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015747 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015748 frag_threshold);
15749 return -EIO;
15750 }
15751
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015752 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015753 }
15754
15755 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15756 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15757 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15758 wiphy->retry_short : wiphy->retry_long;
15759
15760 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15761 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015762 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015763 return -EINVAL;
15764 }
15765
15766 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15767 if (0 != sme_cfg_set_int(hHal,
15768 WNI_CFG_LONG_RETRY_LIMIT,
15769 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015770 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015771 retry_value);
15772 return -EIO;
15773 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015774 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015775 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15776 if (0 != sme_cfg_set_int(hHal,
15777 WNI_CFG_SHORT_RETRY_LIMIT,
15778 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015779 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015780 retry_value);
15781 return -EIO;
15782 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015783 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015784 }
15785 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015786 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015787 return 0;
15788}
15789
15790/**
15791 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15792 * @wiphy: Pointer to wiphy
15793 * @changed: Parameters changed
15794 *
15795 * Return: 0 for success, non-zero for failure
15796 */
15797static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15798{
15799 int ret;
15800
15801 cds_ssr_protect(__func__);
15802 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15803 cds_ssr_unprotect(__func__);
15804
15805 return ret;
15806}
15807
15808/**
15809 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15810 * key
15811 * @wiphy: Pointer to wiphy
15812 * @dev: Pointer to network device
15813 * @key_index: Key index
15814 *
15815 * Return: 0
15816 */
15817static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15818 struct net_device *netdev,
15819 u8 key_index)
15820{
15821 ENTER();
15822 return 0;
15823}
15824
15825/**
15826 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15827 * wlan_hdd_set_default_mgmt_key
15828 * @wiphy: pointer to wiphy
15829 * @netdev: pointer to net_device structure
15830 * @key_index: key index
15831 *
15832 * Return: 0 on success, error number on failure
15833 */
15834static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15835 struct net_device *netdev,
15836 u8 key_index)
15837{
15838 int ret;
15839
15840 cds_ssr_protect(__func__);
15841 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15842 cds_ssr_unprotect(__func__);
15843
15844 return ret;
15845}
15846
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015847/**
15848 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15849 * @wiphy: Pointer to wiphy
15850 * @dev: Pointer to network device
15851 * @params: Pointer to tx queue parameters
15852 *
15853 * Return: 0
15854 */
15855static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15856 struct net_device *dev,
15857 struct ieee80211_txq_params *params)
15858{
15859 ENTER();
15860 return 0;
15861}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015862
15863/**
15864 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15865 * @wiphy: pointer to wiphy
15866 * @netdev: pointer to net_device structure
15867 * @params: pointer to ieee80211_txq_params
15868 *
15869 * Return: 0 on success, error number on failure
15870 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015871static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15872 struct net_device *dev,
15873 struct ieee80211_txq_params *params)
15874{
15875 int ret;
15876
15877 cds_ssr_protect(__func__);
15878 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15879 cds_ssr_unprotect(__func__);
15880
15881 return ret;
15882}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015883
15884/**
15885 * __wlan_hdd_cfg80211_del_station() - delete station v2
15886 * @wiphy: Pointer to wiphy
15887 * @param: Pointer to delete station parameter
15888 *
15889 * Return: 0 for success, non-zero for failure
15890 */
15891static
15892int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15893 struct net_device *dev,
15894 struct tagCsrDelStaParams *pDelStaParams)
15895{
15896 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15897 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015898 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015899 hdd_hostapd_state_t *hapd_state;
15900 int status;
15901 uint8_t staId;
15902 uint8_t *mac;
15903
15904 ENTER();
15905
Anurag Chouhan6d760662016-02-20 16:05:43 +053015906 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015907 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015908 return -EINVAL;
15909 }
15910
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015911 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015912 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015913 return -EINVAL;
15914 }
15915
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015916 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015917 TRACE_CODE_HDD_CFG80211_DEL_STA,
15918 pAdapter->sessionId, pAdapter->device_mode));
15919
15920 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15921 status = wlan_hdd_validate_context(pHddCtx);
15922
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015923 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015924 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015925
15926 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15927
Krunal Sonib4326f22016-03-10 13:05:51 -080015928 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15929 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015930
15931 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15932 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015933 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015934 return 0;
15935 }
15936
Anurag Chouhanc5548422016-02-24 18:33:27 +053015937 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015938 uint16_t i;
15939 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15940 if ((pAdapter->aStaInfo[i].isUsed) &&
15941 (!pAdapter->aStaInfo[i].
15942 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015943 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015944 mac,
15945 pAdapter->aStaInfo[i].
15946 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015947 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015948 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15949 hdd_ipa_wlan_evt(pAdapter,
15950 pAdapter->
15951 aStaInfo[i].
15952 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015953 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015954 mac);
15955 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015956 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015957 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015958 MAC_ADDR_ARRAY(mac));
15959
15960 if (pHddCtx->dev_dfs_cac_status ==
15961 DFS_CAC_IN_PROGRESS)
15962 goto fn_end;
15963
Wei Song2f76f642016-11-18 16:32:53 +080015964 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015965 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015966 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015967 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015968 hdd_softap_sta_deauth(pAdapter,
15969 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015970 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015971 pAdapter->aStaInfo[i].
15972 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015973 qdf_status =
15974 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015975 &hapd_state->
15976 qdf_sta_disassoc_event,
15977 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015978 if (!QDF_IS_STATUS_SUCCESS(
15979 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015980 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015981 }
15982 }
15983 }
15984 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015985 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015986 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015987 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015988 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015989 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015990 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015991 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015992 MAC_ADDR_ARRAY(mac));
15993 return -ENOENT;
15994 }
15995
15996 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15997 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015998 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015999 }
16000
16001 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
16002 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016003 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016004 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016005 MAC_ADDR_ARRAY(mac));
16006 return -ENOENT;
16007 }
16008
16009 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
16010
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016011 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016012 MAC_ADDR_ARRAY(mac));
16013
16014 /* Case: SAP in ACS selected DFS ch and client connected
16015 * Now Radar detected. Then if random channel is another
16016 * DFS ch then new CAC is initiated and no TX allowed.
16017 * So do not send any mgmt frames as it will timeout
16018 * during CAC.
16019 */
16020
16021 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
16022 goto fn_end;
16023
Wei Song2f76f642016-11-18 16:32:53 +080016024 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053016025 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
16026 (pAdapter), pAdapter->sessionId,
16027 (uint8_t *)&pDelStaParams->peerMacAddr,
16028 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016029 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016030 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016031 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016032 pAdapter->aStaInfo[staId].isDeauthInProgress =
16033 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016034 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016035 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016036 MAC_ADDR_ARRAY(mac));
16037 return -ENOENT;
16038 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053016039 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080016040 &hapd_state->
16041 qdf_sta_disassoc_event,
16042 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053016043 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016044 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016045 }
16046 }
16047 }
16048
16049fn_end:
16050 EXIT();
16051 return 0;
16052}
16053
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080016054#if defined(USE_CFG80211_DEL_STA_V2)
16055/**
16056 * wlan_hdd_del_station() - delete station wrapper
16057 * @adapter: pointer to the hdd adapter
16058 *
16059 * Return: None
16060 */
16061void wlan_hdd_del_station(hdd_adapter_t *adapter)
16062{
16063 struct station_del_parameters del_sta;
16064 del_sta.mac = NULL;
16065 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
16066 del_sta.reason_code = eCsrForcedDeauthSta;
16067
16068 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
16069 &del_sta);
16070}
16071#else
16072void wlan_hdd_del_station(hdd_adapter_t *adapter)
16073{
16074 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
16075}
16076#endif
16077
16078#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016079/**
16080 * wlan_hdd_cfg80211_del_station() - delete station v2
16081 * @wiphy: Pointer to wiphy
16082 * @param: Pointer to delete station parameter
16083 *
16084 * Return: 0 for success, non-zero for failure
16085 */
16086int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
16087 struct net_device *dev,
16088 struct station_del_parameters *param)
16089#else
16090/**
16091 * wlan_hdd_cfg80211_del_station() - delete station
16092 * @wiphy: Pointer to wiphy
16093 * @mac: Pointer to station mac address
16094 *
16095 * Return: 0 for success, non-zero for failure
16096 */
16097#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
16098int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
16099 struct net_device *dev,
16100 const uint8_t *mac)
16101#else
16102int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
16103 struct net_device *dev,
16104 uint8_t *mac)
16105#endif
16106#endif
16107{
16108 int ret;
16109 struct tagCsrDelStaParams delStaParams;
16110
16111 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080016112#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016113 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080016114 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016115 return -EINVAL;
16116 }
16117 wlansap_populate_del_sta_params(param->mac, param->reason_code,
16118 param->subtype, &delStaParams);
16119#else
16120 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
16121 (SIR_MAC_MGMT_DEAUTH >> 4),
16122 &delStaParams);
16123#endif
16124 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
16125 cds_ssr_unprotect(__func__);
16126
16127 return ret;
16128}
16129
16130/**
16131 * __wlan_hdd_cfg80211_add_station() - add station
16132 * @wiphy: Pointer to wiphy
16133 * @mac: Pointer to station mac address
16134 * @pmksa: Pointer to add station parameter
16135 *
16136 * Return: 0 for success, non-zero for failure
16137 */
16138static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
16139 struct net_device *dev,
16140 const uint8_t *mac,
16141 struct station_parameters *params)
16142{
16143 int status = -EPERM;
16144#ifdef FEATURE_WLAN_TDLS
16145 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16146 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16147 u32 mask, set;
16148
16149 ENTER();
16150
Anurag Chouhan6d760662016-02-20 16:05:43 +053016151 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016152 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016153 return -EINVAL;
16154 }
16155
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016156 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016157 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016158 return -EINVAL;
16159 }
16160
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016161 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016162 TRACE_CODE_HDD_CFG80211_ADD_STA,
16163 pAdapter->sessionId, params->listen_interval));
16164
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016165 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016166 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016167
16168 mask = params->sta_flags_mask;
16169
16170 set = params->sta_flags_set;
16171
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016172 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016173 MAC_ADDR_ARRAY(mac));
16174
16175 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
16176 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080016177#if defined(CONVERGED_TDLS_ENABLE)
16178 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
16179 dev, mac);
16180#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016181 status =
16182 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080016183#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016184 }
16185 }
16186#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016187 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016188 return status;
16189}
16190
16191/**
16192 * wlan_hdd_cfg80211_add_station() - add station
16193 * @wiphy: Pointer to wiphy
16194 * @mac: Pointer to station mac address
16195 * @pmksa: Pointer to add station parameter
16196 *
16197 * Return: 0 for success, non-zero for failure
16198 */
16199#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
16200static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
16201 struct net_device *dev,
16202 const uint8_t *mac,
16203 struct station_parameters *params)
16204#else
16205static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
16206 struct net_device *dev, uint8_t *mac,
16207 struct station_parameters *params)
16208#endif
16209{
16210 int ret;
16211
16212 cds_ssr_protect(__func__);
16213 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
16214 cds_ssr_unprotect(__func__);
16215
16216 return ret;
16217}
16218
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016219/**
16220 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
16221 * @wiphy: Pointer to wiphy
16222 * @dev: Pointer to network device
16223 * @pmksa: Pointer to set pmksa parameter
16224 *
16225 * Return: 0 for success, non-zero for failure
16226 */
16227static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
16228 struct net_device *dev,
16229 struct cfg80211_pmksa *pmksa)
16230{
16231 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16232 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16233 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016234 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016235 int status;
16236 tPmkidCacheInfo pmk_id;
16237
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016238 ENTER();
16239
Anurag Chouhan6d760662016-02-20 16:05:43 +053016240 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016241 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016242 return -EINVAL;
16243 }
16244
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016245 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016246 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016247 return -EINVAL;
16248 }
16249
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016250 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016251 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016252 return -EINVAL;
16253 }
16254
16255 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016256 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016257 pmksa->bssid, pmksa->pmkid);
16258 return -EINVAL;
16259 }
16260
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016261 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016262 MAC_ADDR_ARRAY(pmksa->bssid));
16263
16264 status = wlan_hdd_validate_context(pHddCtx);
16265
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016266 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016267 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016268
16269 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16270
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016271 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
16272 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016273
16274 /* Add to the PMKSA ID Cache in CSR */
16275 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
16276 &pmk_id, 1, false);
16277
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016278 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016279 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
16280 pAdapter->sessionId, result));
16281
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016282 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016283 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016284}
16285
16286/**
16287 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
16288 * @wiphy: Pointer to wiphy
16289 * @dev: Pointer to network device
16290 * @pmksa: Pointer to set pmksa parameter
16291 *
16292 * Return: 0 for success, non-zero for failure
16293 */
16294static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
16295 struct net_device *dev,
16296 struct cfg80211_pmksa *pmksa)
16297{
16298 int ret;
16299
16300 cds_ssr_protect(__func__);
16301 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
16302 cds_ssr_unprotect(__func__);
16303
16304 return ret;
16305}
16306
16307/**
16308 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
16309 * @wiphy: Pointer to wiphy
16310 * @dev: Pointer to network device
16311 * @pmksa: Pointer to pmksa parameter
16312 *
16313 * Return: 0 for success, non-zero for failure
16314 */
16315static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16316 struct net_device *dev,
16317 struct cfg80211_pmksa *pmksa)
16318{
16319 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16320 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16321 tHalHandle halHandle;
16322 int status = 0;
16323
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016324 ENTER();
16325
Anurag Chouhan6d760662016-02-20 16:05:43 +053016326 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016327 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016328 return -EINVAL;
16329 }
16330
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016331 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16332 hdd_err("invalid session id: %d", pAdapter->sessionId);
16333 return -EINVAL;
16334 }
16335
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016336 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016337 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016338 return -EINVAL;
16339 }
16340
16341 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016342 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016343 return -EINVAL;
16344 }
16345
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016346 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016347 MAC_ADDR_ARRAY(pmksa->bssid));
16348
16349 status = wlan_hdd_validate_context(pHddCtx);
16350
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016351 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016352 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016353
16354 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16355
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016356 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016357 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
16358 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016359 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016360 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016361 sme_roam_del_pmkid_from_cache(halHandle,
16362 pAdapter->sessionId, pmksa->bssid,
16363 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016364 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016365 MAC_ADDR_ARRAY(pmksa->bssid));
16366 status = -EINVAL;
16367 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016368 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016369 return status;
16370}
16371
16372/**
16373 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
16374 * @wiphy: Pointer to wiphy
16375 * @dev: Pointer to network device
16376 * @pmksa: Pointer to pmksa parameter
16377 *
16378 * Return: 0 for success, non-zero for failure
16379 */
16380static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
16381 struct net_device *dev,
16382 struct cfg80211_pmksa *pmksa)
16383{
16384 int ret;
16385
16386 cds_ssr_protect(__func__);
16387 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
16388 cds_ssr_unprotect(__func__);
16389
16390 return ret;
16391
16392}
16393
16394/**
16395 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16396 * @wiphy: Pointer to wiphy
16397 * @dev: Pointer to network device
16398 *
16399 * Return: 0 for success, non-zero for failure
16400 */
16401static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16402 struct net_device *dev)
16403{
16404 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16405 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16406 tHalHandle halHandle;
16407 int status = 0;
16408
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016409 ENTER();
16410
Anurag Chouhan6d760662016-02-20 16:05:43 +053016411 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016412 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016413 return -EINVAL;
16414 }
16415
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016416 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16417 hdd_err("invalid session id: %d", pAdapter->sessionId);
16418 return -EINVAL;
16419 }
16420
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016421 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016422
16423 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16424 status = wlan_hdd_validate_context(pHddCtx);
16425
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016426 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016427 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016428
16429 /* Retrieve halHandle */
16430 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
16431
16432 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016433 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016434 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
16435 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016436 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016437 status = -EINVAL;
16438 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016439 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016440 return status;
16441}
16442
16443/**
16444 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
16445 * @wiphy: Pointer to wiphy
16446 * @dev: Pointer to network device
16447 *
16448 * Return: 0 for success, non-zero for failure
16449 */
16450static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
16451 struct net_device *dev)
16452{
16453 int ret;
16454
16455 cds_ssr_protect(__func__);
16456 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
16457 cds_ssr_unprotect(__func__);
16458
16459 return ret;
16460}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016461
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016462#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016463/**
16464 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16465 * @wiphy: Pointer to wiphy
16466 * @dev: Pointer to network device
16467 * @ftie: Pointer to fast transition ie parameter
16468 *
16469 * Return: 0 for success, non-zero for failure
16470 */
16471static int
16472__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16473 struct net_device *dev,
16474 struct cfg80211_update_ft_ies_params *ftie)
16475{
16476 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16477 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16478 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
16479 int status;
16480
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016481 ENTER();
16482
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016483 status = wlan_hdd_validate_context(hdd_ctx);
16484 if (status)
16485 return status;
16486
Anurag Chouhan6d760662016-02-20 16:05:43 +053016487 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016488 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016489 return -EINVAL;
16490 }
16491
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016492 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16493 hdd_err("invalid session id: %d", pAdapter->sessionId);
16494 return -EINVAL;
16495 }
16496
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016497 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016498 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
16499 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
16500 /* Added for debug on reception of Re-assoc Req. */
16501 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016502 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016503 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016504 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016505 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016506 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016507 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016508
16509 /* Pass the received FT IEs to SME */
16510 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
16511 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016512 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016513 return 0;
16514}
16515
16516/**
16517 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
16518 * @wiphy: Pointer to wiphy
16519 * @dev: Pointer to network device
16520 * @ftie: Pointer to fast transition ie parameter
16521 *
16522 * Return: 0 for success, non-zero for failure
16523 */
16524static int
16525wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
16526 struct net_device *dev,
16527 struct cfg80211_update_ft_ies_params *ftie)
16528{
16529 int ret;
16530
16531 cds_ssr_protect(__func__);
16532 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
16533 cds_ssr_unprotect(__func__);
16534
16535 return ret;
16536}
16537#endif
16538
Mukul Sharma3d36c392017-01-18 18:39:12 +053016539void wlan_hdd_cfg80211_update_replay_counter_callback(
16540 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
16541
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016542{
Mukul Sharma3d36c392017-01-18 18:39:12 +053016543 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
16544 uint8_t temp_replay_counter[8];
16545 int i;
16546 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016547
16548 ENTER();
16549
Mukul Sharma3d36c392017-01-18 18:39:12 +053016550 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016551 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016552 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016553 }
16554
Mukul Sharma3d36c392017-01-18 18:39:12 +053016555 if (!gtk_rsp_param) {
16556 hdd_err("gtk_rsp_param is Null");
16557 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016558 }
16559
Mukul Sharma3d36c392017-01-18 18:39:12 +053016560 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016561 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016562 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016563 }
16564
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016565 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016566 gtk_rsp_param->replay_counter);
16567 /* convert little to big endian since supplicant works on big endian */
16568 p = (uint8_t *)&gtk_rsp_param->replay_counter;
16569 for (i = 0; i < 8; i++)
16570 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016571
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016572 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016573 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080016574 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016575 gtk_rsp_param->bssid.bytes,
16576 temp_replay_counter, GFP_KERNEL);
16577out:
16578 EXIT();
16579
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016580}
16581
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016582static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016583int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016584 struct net_device *dev,
16585 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016586{
16587 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016588 int result, i;
16589 struct pmo_gtk_req *gtk_req = NULL;
16590 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
16591 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016592 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016593
16594 ENTER();
16595
Anurag Chouhan6d760662016-02-20 16:05:43 +053016596 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016597 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016598 result = -EINVAL;
16599 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016600 }
16601
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016602 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16603 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016604 result = -EINVAL;
16605 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016606 }
16607
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016608 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016609 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
16610 pAdapter->sessionId, pAdapter->device_mode));
16611
Mukul Sharma3d36c392017-01-18 18:39:12 +053016612 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016613 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053016614 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016615
Mukul Sharma3d36c392017-01-18 18:39:12 +053016616 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
16617 if (!gtk_req) {
16618 hdd_err("cannot allocate gtk_req");
16619 result = -ENOMEM;
16620 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016621 }
16622
Mukul Sharma3d36c392017-01-18 18:39:12 +053016623 /* convert big to little endian since driver work on little endian */
16624 buf = (uint8_t *)&gtk_req->replay_counter;
16625 for (i = 0; i < 8; i++)
16626 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016627
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016628 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016629 gtk_req->replay_counter);
16630 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
16631 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
16632 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
16633 if (status != QDF_STATUS_SUCCESS) {
16634 hdd_err("Failed to cache GTK Offload");
16635 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016636 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053016637out:
16638 if (gtk_req)
16639 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016640 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053016641
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016642 return result;
16643}
16644
16645/**
16646 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
16647 * @wiphy: Pointer to wiphy
16648 * @dev: Pointer to network device
16649 * @data: Pointer to rekey data
16650 *
16651 * This function is used to offload GTK rekeying job to the firmware.
16652 *
16653 * Return: 0 for success, non-zero for failure
16654 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016655static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016656int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16657 struct net_device *dev,
16658 struct cfg80211_gtk_rekey_data *data)
16659{
16660 int ret;
16661
16662 cds_ssr_protect(__func__);
16663 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16664 cds_ssr_unprotect(__func__);
16665
16666 return ret;
16667}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016668
16669/**
16670 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16671 * @wiphy: Pointer to wiphy
16672 * @dev: Pointer to network device
16673 * @param: Pointer to access control parameter
16674 *
16675 * Return: 0 for success, non-zero for failure
16676 */
16677static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16678 struct net_device *dev,
16679 const struct cfg80211_acl_data *params)
16680{
16681 int i;
16682 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16683 hdd_hostapd_state_t *pHostapdState;
16684 tsap_Config_t *pConfig;
16685 v_CONTEXT_t p_cds_context = NULL;
16686 hdd_context_t *pHddCtx;
16687 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016688 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016689
16690 ENTER();
16691
Anurag Chouhan6d760662016-02-20 16:05:43 +053016692 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016693 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016694 return -EINVAL;
16695 }
16696
16697 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016698 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016699 return -EINVAL;
16700 }
16701
16702 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16703 status = wlan_hdd_validate_context(pHddCtx);
16704
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016705 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016706 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016707
16708 p_cds_context = pHddCtx->pcds_context;
16709 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16710
16711 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016712 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016713 return -EINVAL;
16714 }
16715
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016716 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016717 params->n_acl_entries);
16718
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016719 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016720 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16721 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016722 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016723 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16724
16725 /* default value */
16726 pConfig->num_accept_mac = 0;
16727 pConfig->num_deny_mac = 0;
16728
16729 /**
16730 * access control policy
16731 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16732 * listed in hostapd.deny file.
16733 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16734 * listed in hostapd.accept file.
16735 */
16736 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16737 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16738 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16739 params->acl_policy) {
16740 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16741 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016742 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016743 params->acl_policy);
16744 return -ENOTSUPP;
16745 }
16746
16747 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16748 pConfig->num_accept_mac = params->n_acl_entries;
16749 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016750 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016751 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016752 MAC_ADDR_ARRAY(
16753 params->mac_addrs[i].addr));
16754
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016755 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016756 params->mac_addrs[i].addr,
16757 sizeof(qcmacaddr));
16758 }
16759 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16760 pConfig->num_deny_mac = params->n_acl_entries;
16761 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016762 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016763 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016764 MAC_ADDR_ARRAY(
16765 params->mac_addrs[i].addr));
16766
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016767 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016768 params->mac_addrs[i].addr,
16769 sizeof(qcmacaddr));
16770 }
16771 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016772 qdf_status = wlansap_set_mac_acl(
16773 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016774 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016775 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016776 return -EINVAL;
16777 }
16778 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016779 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016780 hdd_device_mode_to_string(pAdapter->device_mode),
16781 pAdapter->device_mode);
16782 return -EINVAL;
16783 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016784 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016785 return 0;
16786}
16787
16788/**
16789 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16790 * __wlan_hdd_cfg80211_set_mac_acl
16791 * @wiphy: pointer to wiphy structure
16792 * @dev: pointer to net_device
16793 * @params: pointer to cfg80211_acl_data
16794 *
16795 * Return; 0 on success, error number otherwise
16796 */
16797static int
16798wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16799 struct net_device *dev,
16800 const struct cfg80211_acl_data *params)
16801{
16802 int ret;
16803
16804 cds_ssr_protect(__func__);
16805 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16806 cds_ssr_unprotect(__func__);
16807
16808 return ret;
16809}
16810
16811#ifdef WLAN_NL80211_TESTMODE
16812#ifdef FEATURE_WLAN_LPHB
16813/**
16814 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16815 * @pHddCtx: Pointer to hdd context
16816 * @lphbInd: Pointer to low power heart beat indication parameter
16817 *
16818 * Return: none
16819 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016820static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016821 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016822{
16823 struct sk_buff *skb;
16824
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016825 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016826
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016827 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016828 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016829
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016830 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016831 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016832 return;
16833 }
16834
16835 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016836 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016837 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016838 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016839 return;
16840 }
16841
16842 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016843 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016844 goto nla_put_failure;
16845 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016846 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016847 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016848 goto nla_put_failure;
16849 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016850 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16851 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016852 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016853 goto nla_put_failure;
16854 }
16855 cfg80211_testmode_event(skb, GFP_ATOMIC);
16856 return;
16857
16858nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016859 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016860 kfree_skb(skb);
16861
16862 return;
16863}
16864#endif /* FEATURE_WLAN_LPHB */
16865
16866/**
16867 * __wlan_hdd_cfg80211_testmode() - test mode
16868 * @wiphy: Pointer to wiphy
16869 * @data: Data pointer
16870 * @len: Data length
16871 *
16872 * Return: 0 for success, non-zero for failure
16873 */
16874static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16875 void *data, int len)
16876{
16877 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16878 int err;
16879 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16880
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016881 ENTER();
16882
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016883 err = wlan_hdd_validate_context(pHddCtx);
16884 if (err)
16885 return err;
16886
16887 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16888 len, wlan_hdd_tm_policy);
16889 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016890 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016891 return err;
16892 }
16893
16894 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016895 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016896 return -EINVAL;
16897 }
16898
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016899 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016900 TRACE_CODE_HDD_CFG80211_TESTMODE,
16901 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016902 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16903#ifdef FEATURE_WLAN_LPHB
16904 /* Low Power Heartbeat configuration request */
16905 case WLAN_HDD_TM_CMD_WLAN_HB:
16906 {
16907 int buf_len;
16908 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016909 struct pmo_lphb_req *hb_params = NULL;
16910 struct pmo_lphb_req *hb_params_temp = NULL;
16911 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016912
16913 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016914 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016915 return -EINVAL;
16916 }
16917
16918 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16919 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16920
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016921 hb_params_temp = (struct pmo_lphb_req *) buf;
16922 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16923 && (hb_params_temp->params.lphb_tcp_params.
16924 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016925 return -EINVAL;
16926
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016927 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16928 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016929 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016930 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016931 return -ENOMEM;
16932 }
16933
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016934 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016935 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16936 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016937 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016938 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016939 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016940
16941 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016942 return 0;
16943 }
16944#endif /* FEATURE_WLAN_LPHB */
16945
16946#if defined(QCA_WIFI_FTM)
16947 case WLAN_HDD_TM_CMD_WLAN_FTM:
16948 {
16949 int buf_len;
16950 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016951 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016952 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016953 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016954 return -EINVAL;
16955 }
16956
16957 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16958 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16959
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016960 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016961
16962 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16963
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016964 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016965 err = -EBUSY;
16966 break;
16967 }
16968#endif
16969
16970 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016971 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016972 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16973 return -EOPNOTSUPP;
16974 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016975 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016976 return err;
16977}
16978
16979/**
16980 * wlan_hdd_cfg80211_testmode() - test mode
16981 * @wiphy: Pointer to wiphy
16982 * @dev: Pointer to network device
16983 * @data: Data pointer
16984 * @len: Data length
16985 *
16986 * Return: 0 for success, non-zero for failure
16987 */
16988static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16989#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16990 struct wireless_dev *wdev,
16991#endif
16992 void *data, int len)
16993{
16994 int ret;
16995
16996 cds_ssr_protect(__func__);
16997 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16998 cds_ssr_unprotect(__func__);
16999
17000 return ret;
17001}
17002
17003#if defined(QCA_WIFI_FTM)
17004/**
17005 * wlan_hdd_testmode_rx_event() - test mode rx event handler
17006 * @buf: Pointer to buffer
17007 * @buf_len: Buffer length
17008 *
17009 * Return: none
17010 */
17011void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
17012{
17013 struct sk_buff *skb;
17014 hdd_context_t *hdd_ctx;
17015
17016 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017017 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017018 return;
17019 }
17020
Anurag Chouhan6d760662016-02-20 16:05:43 +053017021 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017022 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017023 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017024 return;
17025 }
17026
17027 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
17028 buf_len, GFP_KERNEL);
17029 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017030 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017031 return;
17032 }
17033
17034 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
17035 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
17036 goto nla_put_failure;
17037
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017038 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017039
17040 cfg80211_testmode_event(skb, GFP_KERNEL);
17041 return;
17042
17043nla_put_failure:
17044 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017045 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017046}
17047#endif
17048#endif /* CONFIG_NL80211_TESTMODE */
17049
17050#ifdef QCA_HT_2040_COEX
17051/**
17052 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
17053 * @wiphy: Pointer to wiphy
17054 * @dev: Pointer to network device
17055 * @chandef: Pointer to channel definition parameter
17056 *
17057 * Return: 0 for success, non-zero for failure
17058 */
17059static int
17060__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
17061 struct net_device *dev,
17062 struct cfg80211_chan_def *chandef)
17063{
17064 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
17065 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017066 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017067 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053017068 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017069
Anurag Chouhan6d760662016-02-20 16:05:43 +053017070 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017071 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017072 return -EINVAL;
17073 }
17074
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017075 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
17076 hdd_err("invalid session id: %d", pAdapter->sessionId);
17077 return -EINVAL;
17078 }
17079
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017080 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
17081 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053017082 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017083 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017084
Anurag Chouhan600c3a02016-03-01 10:33:54 +053017085 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017086 sme_get_config_param(pHddCtx->hHal, &sme_config);
17087 switch (chandef->width) {
17088 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053017089 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017090 if (sme_config.csrConfig.channelBondingMode24GHz !=
17091 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
17092 sme_config.csrConfig.channelBondingMode24GHz =
17093 eCSR_INI_SINGLE_CHANNEL_CENTERED;
17094 sme_update_config(pHddCtx->hHal, &sme_config);
17095 cbModeChange = true;
17096 }
17097 break;
17098
17099 case NL80211_CHAN_WIDTH_40:
17100 if (sme_config.csrConfig.channelBondingMode24GHz ==
17101 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
17102 if (NL80211_CHAN_HT40MINUS ==
17103 cfg80211_get_chandef_type(chandef))
17104 sme_config.csrConfig.channelBondingMode24GHz =
17105 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
17106 else
17107 sme_config.csrConfig.channelBondingMode24GHz =
17108 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
17109 sme_update_config(pHddCtx->hHal, &sme_config);
17110 cbModeChange = true;
17111 }
17112 break;
17113
17114 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070017115 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017116 return -EINVAL;
17117 }
17118
17119 if (!cbModeChange)
17120 return 0;
17121
Krunal Sonib4326f22016-03-10 13:05:51 -080017122 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017123 return 0;
17124
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017125 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017126 sme_config.csrConfig.channelBondingMode24GHz);
17127
17128 /* Change SAP ht2040 mode */
17129 status = hdd_set_sap_ht2040_mode(pAdapter,
17130 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017131 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017132 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017133 return -EINVAL;
17134 }
17135
17136 return 0;
17137}
17138
17139/**
17140 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
17141 * @wiphy: Pointer to wiphy
17142 * @dev: Pointer to network device
17143 * @chandef: Pointer to channel definition parameter
17144 *
17145 * Return: 0 for success, non-zero for failure
17146 */
17147static int
17148wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
17149 struct net_device *dev,
17150 struct cfg80211_chan_def *chandef)
17151{
17152 int ret;
17153
17154 cds_ssr_protect(__func__);
17155 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
17156 cds_ssr_unprotect(__func__);
17157
17158 return ret;
17159}
17160#endif
17161
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017162#ifdef CHANNEL_SWITCH_SUPPORTED
17163/**
17164 * __wlan_hdd_cfg80211_channel_switch()- function to switch
17165 * channel in SAP/GO
17166 * @wiphy: wiphy pointer
17167 * @dev: dev pointer.
17168 * @csa_params: Change channel params
17169 *
17170 * This function is called to switch channel in SAP/GO
17171 *
17172 * Return: 0 if success else return non zero
17173 */
17174static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
17175 struct net_device *dev,
17176 struct cfg80211_csa_settings *csa_params)
17177{
17178 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
17179 hdd_context_t *hdd_ctx;
17180 uint8_t channel;
17181 uint16_t freq;
17182 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080017183 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017184
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017185 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017186 csa_params->chandef.chan->center_freq);
17187
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017188 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
17189 hdd_err("invalid session id: %d", adapter->sessionId);
17190 return -EINVAL;
17191 }
17192
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017193 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17194 ret = wlan_hdd_validate_context(hdd_ctx);
17195
17196 if (0 != ret)
17197 return ret;
17198
Krunal Sonib4326f22016-03-10 13:05:51 -080017199 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
17200 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017201 return -ENOTSUPP;
17202
17203 freq = csa_params->chandef.chan->center_freq;
17204 channel = cds_freq_to_chan(freq);
17205
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053017206 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
17207
17208 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017209 return ret;
17210}
17211
17212/**
17213 * wlan_hdd_cfg80211_channel_switch()- function to switch
17214 * channel in SAP/GO
17215 * @wiphy: wiphy pointer
17216 * @dev: dev pointer.
17217 * @csa_params: Change channel params
17218 *
17219 * This function is called to switch channel in SAP/GO
17220 *
17221 * Return: 0 if success else return non zero
17222 */
17223static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
17224 struct net_device *dev,
17225 struct cfg80211_csa_settings *csa_params)
17226{
17227 int ret;
17228
17229 cds_ssr_protect(__func__);
17230 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
17231 cds_ssr_unprotect(__func__);
17232 return ret;
17233}
17234#endif
17235
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017236/**
17237 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
17238 * translation from NL to policy manager type
17239 * @type: Generic connection mode type defined in NL
17240 *
17241 *
17242 * This function provides the type translation
17243 *
17244 * Return: cds_con_mode enum
17245 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017246enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017247 enum nl80211_iftype type)
17248{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017249 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017250 switch (type) {
17251 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017252 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017253 break;
17254 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017255 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017256 break;
17257 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017258 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017259 break;
17260 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017261 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017262 break;
17263 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017264 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017265 break;
17266 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017267 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017268 }
17269 return mode;
17270}
17271
17272/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017273 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
17274 * @wiphy: Handle to struct wiphy to get handle to module context.
17275 * @chandef: Contains information about the capture channel to be set.
17276 *
17277 * This interface is called if and only if monitor mode interface alone is
17278 * active.
17279 *
17280 * Return: 0 success or error code on failure.
17281 */
17282static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
17283 struct cfg80211_chan_def *chandef)
17284{
17285 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
17286 hdd_adapter_t *adapter;
17287 hdd_station_ctx_t *sta_ctx;
17288 struct hdd_mon_set_ch_info *ch_info;
17289 QDF_STATUS status;
17290 tHalHandle hal_hdl;
17291 struct qdf_mac_addr bssid;
17292 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080017293 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017294 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017295 int ret;
17296 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
17297
17298 ENTER();
17299
17300 ret = wlan_hdd_validate_context(hdd_ctx);
17301 if (ret)
17302 return ret;
17303
17304 hal_hdl = hdd_ctx->hHal;
17305
17306 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
17307 if (!adapter)
17308 return -EIO;
17309
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017310 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017311 adapter->dev->name, chan_num, chandef->chan->center_freq);
17312
17313 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17314 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017315 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
17316 roam_profile.ChannelInfo.numOfChannels = 1;
17317 roam_profile.phyMode = ch_info->phy_mode;
17318 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017319 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017320
17321 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
17322 QDF_MAC_ADDR_SIZE);
17323
17324 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017325 /*
17326 * CDS api expects secondary channel for calculating
17327 * the channel params
17328 */
17329 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017330 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017331 if (chan_num >= 1 && chan_num <= 5)
17332 sec_ch = chan_num + 4;
17333 else if (chan_num >= 6 && chan_num <= 13)
17334 sec_ch = chan_num - 4;
17335 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017336 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
17337 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017338 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
17339 &roam_profile);
17340 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017341 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017342 status);
17343 ret = qdf_status_to_os_return(status);
17344 return ret;
17345 }
17346 EXIT();
17347 return 0;
17348}
17349
17350/**
17351 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
17352 * @wiphy: Handle to struct wiphy to get handle to module context.
17353 * @chandef: Contains information about the capture channel to be set.
17354 *
17355 * This interface is called if and only if monitor mode interface alone is
17356 * active.
17357 *
17358 * Return: 0 success or error code on failure.
17359 */
17360static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
17361 struct cfg80211_chan_def *chandef)
17362{
17363 int ret;
17364
17365 cds_ssr_protect(__func__);
17366 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
17367 cds_ssr_unprotect(__func__);
17368 return ret;
17369}
17370
17371/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017372 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
17373 * @adapter: pointer to adapter
17374 *
17375 * Wrapper function to clear link layer stats.
17376 * return - void
17377 */
17378void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
17379{
17380 tSirLLStatsClearReq link_layer_stats_clear_req;
17381 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
17382
Mukul Sharma491021c2016-09-29 21:39:19 +053017383 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
17384 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017385 link_layer_stats_clear_req.stopReq = 0;
17386 link_layer_stats_clear_req.reqId = 1;
17387 link_layer_stats_clear_req.staId = adapter->sessionId;
17388 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
17389
17390 return;
17391}
17392
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017393/**
17394 * hdd_process_defer_disconnect() - Handle the deferred disconnect
17395 * @adapter: HDD Adapter
17396 *
17397 * If roaming is in progress and there is a request to
17398 * disconnect the session, then it is deferred. Once
17399 * roaming is complete/aborted, then this routine is
17400 * used to resume the disconnect that was deferred
17401 *
17402 * Return: None
17403 */
17404void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
17405{
17406 switch (adapter->defer_disconnect) {
17407 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
17408 adapter->defer_disconnect = 0;
17409 wlan_hdd_disconnect(adapter,
17410 adapter->cfg80211_disconnect_reason);
17411 break;
17412 case DEFER_DISCONNECT_TRY_DISCONNECT:
17413 wlan_hdd_try_disconnect(adapter);
17414 adapter->defer_disconnect = 0;
17415 break;
17416 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017417 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080017418 adapter->defer_disconnect);
17419 break;
17420 }
17421}
17422
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017423#define CNT_DIFF(cur, prev) \
17424 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
17425#define MAX_COUNT 0xffffffff
17426static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
17427 struct scan_chan_info *chan,
17428 struct scan_chan_info *info, uint32_t cmd_flag)
17429{
17430 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
17431 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
17432 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
17433
17434 mutex_lock(&hdd_ctx->chan_info_lock);
17435
17436 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
17437 qdf_mem_zero(chan, sizeof(*chan));
17438
17439 chan->freq = info->freq;
17440 chan->noise_floor = info->noise_floor;
17441 chan->clock_freq = info->clock_freq;
17442 chan->cmd_flag = info->cmd_flag;
17443 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
17444
17445 chan->rx_clear_count =
17446 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
17447
17448 chan->tx_frame_count =
17449 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
17450
17451 mutex_unlock(&hdd_ctx->chan_info_lock);
17452
17453}
17454#undef CNT_DIFF
17455#undef MAX_COUNT
17456
17457/**
17458 * wlan_hdd_chan_info_cb() - channel info callback
17459 * @chan_info: struct scan_chan_info
17460 *
17461 * Store channel info into HDD context
17462 *
17463 * Return: None.
17464 */
17465static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
17466{
17467 hdd_context_t *hdd_ctx;
17468 struct scan_chan_info *chan;
17469 uint8_t idx;
17470
17471 ENTER();
17472
17473 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17474 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
17475 hdd_err("hdd_ctx is invalid");
17476 return;
17477 }
17478
17479 if (!hdd_ctx->chan_info) {
17480 hdd_err("chan_info is NULL");
17481 return;
17482 }
17483
17484 chan = hdd_ctx->chan_info;
17485 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
17486 if (chan[idx].freq == info->freq) {
17487 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
17488 info->cmd_flag);
17489 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
17490 chan[idx].cmd_flag, chan[idx].freq,
17491 chan[idx].noise_floor,
17492 chan[idx].cycle_count, chan[idx].rx_clear_count,
17493 chan[idx].clock_freq, chan[idx].cmd_flag,
17494 chan[idx].tx_frame_count, idx);
17495 if (chan[idx].freq == 0)
17496 break;
17497
17498 }
17499 }
17500
17501 EXIT();
17502}
17503
17504/**
17505 * wlan_hdd_init_chan_info() - init chan info in hdd context
17506 * @hdd_ctx: HDD context pointer
17507 *
17508 * Return: none
17509 */
17510void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
17511{
17512 uint8_t num_2g, num_5g, index = 0;
17513
17514 if (!hdd_ctx->config->fEnableSNRMonitoring) {
17515 hdd_info("SNR monitoring is disabled");
17516 return;
17517 }
17518
17519 hdd_ctx->chan_info =
17520 qdf_mem_malloc(sizeof(struct scan_chan_info)
17521 * QDF_MAX_NUM_CHAN);
17522 if (hdd_ctx->chan_info == NULL) {
17523 hdd_err("Failed to malloc for chan info");
17524 return;
17525 }
17526 mutex_init(&hdd_ctx->chan_info_lock);
17527
17528 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
17529 for (; index < num_2g; index++) {
17530 hdd_ctx->chan_info[index].freq =
17531 hdd_channels_2_4_ghz[index].center_freq;
17532 }
17533
17534 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
17535 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017536 if (WLAN_REG_IS_11P_CH(
17537 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053017538 continue;
17539 hdd_ctx->chan_info[index].freq =
17540 hdd_channels_5_ghz[index - num_2g].center_freq;
17541 }
17542 sme_set_chan_info_callback(hdd_ctx->hHal,
17543 &wlan_hdd_chan_info_cb);
17544}
17545
17546/**
17547 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
17548 * @hdd_ctx: hdd context pointer
17549 *
17550 * Return: none
17551 */
17552void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
17553{
17554 struct scan_chan_info *chan;
17555
17556 chan = hdd_ctx->chan_info;
17557 hdd_ctx->chan_info = NULL;
17558 if (chan)
17559 qdf_mem_free(chan);
17560}
17561
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053017562/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017563 * struct cfg80211_ops - cfg80211_ops
17564 *
17565 * @add_virtual_intf: Add virtual interface
17566 * @del_virtual_intf: Delete virtual interface
17567 * @change_virtual_intf: Change virtual interface
17568 * @change_station: Change station
17569 * @add_beacon: Add beacon in sap mode
17570 * @del_beacon: Delete beacon in sap mode
17571 * @set_beacon: Set beacon in sap mode
17572 * @start_ap: Start ap
17573 * @change_beacon: Change beacon
17574 * @stop_ap: Stop ap
17575 * @change_bss: Change bss
17576 * @add_key: Add key
17577 * @get_key: Get key
17578 * @del_key: Delete key
17579 * @set_default_key: Set default key
17580 * @set_channel: Set channel
17581 * @scan: Scan
17582 * @connect: Connect
17583 * @disconnect: Disconnect
17584 * @join_ibss = Join ibss
17585 * @leave_ibss = Leave ibss
17586 * @set_wiphy_params = Set wiphy params
17587 * @set_tx_power = Set tx power
17588 * @get_tx_power = get tx power
17589 * @remain_on_channel = Remain on channel
17590 * @cancel_remain_on_channel = Cancel remain on channel
17591 * @mgmt_tx = Tx management frame
17592 * @mgmt_tx_cancel_wait = Cancel management tx wait
17593 * @set_default_mgmt_key = Set default management key
17594 * @set_txq_params = Set tx queue parameters
17595 * @get_station = Get station
17596 * @set_power_mgmt = Set power management
17597 * @del_station = Delete station
17598 * @add_station = Add station
17599 * @set_pmksa = Set pmksa
17600 * @del_pmksa = Delete pmksa
17601 * @flush_pmksa = Flush pmksa
17602 * @update_ft_ies = Update FT IEs
17603 * @tdls_mgmt = Tdls management
17604 * @tdls_oper = Tdls operation
17605 * @set_rekey_data = Set rekey data
17606 * @sched_scan_start = Scheduled scan start
17607 * @sched_scan_stop = Scheduled scan stop
17608 * @resume = Resume wlan
17609 * @suspend = Suspend wlan
17610 * @set_mac_acl = Set mac acl
17611 * @testmode_cmd = Test mode command
17612 * @set_ap_chanwidth = Set AP channel bandwidth
17613 * @dump_survey = Dump survey
17614 * @key_mgmt_set_pmk = Set pmk key management
17615 */
17616static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
17617 .add_virtual_intf = wlan_hdd_add_virtual_intf,
17618 .del_virtual_intf = wlan_hdd_del_virtual_intf,
17619 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
17620 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017621 .start_ap = wlan_hdd_cfg80211_start_ap,
17622 .change_beacon = wlan_hdd_cfg80211_change_beacon,
17623 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017624 .change_bss = wlan_hdd_cfg80211_change_bss,
17625 .add_key = wlan_hdd_cfg80211_add_key,
17626 .get_key = wlan_hdd_cfg80211_get_key,
17627 .del_key = wlan_hdd_cfg80211_del_key,
17628 .set_default_key = wlan_hdd_cfg80211_set_default_key,
17629 .scan = wlan_hdd_cfg80211_scan,
17630 .connect = wlan_hdd_cfg80211_connect,
17631 .disconnect = wlan_hdd_cfg80211_disconnect,
17632 .join_ibss = wlan_hdd_cfg80211_join_ibss,
17633 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
17634 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
17635 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
17636 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
17637 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
17638 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
17639 .mgmt_tx = wlan_hdd_mgmt_tx,
17640 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
17641 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
17642 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053017643 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017644 .get_station = wlan_hdd_cfg80211_get_station,
17645 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
17646 .del_station = wlan_hdd_cfg80211_del_station,
17647 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017648 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
17649 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
17650 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080017651#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017652 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
17653#endif
17654#ifdef FEATURE_WLAN_TDLS
17655 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17656 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17657#endif
17658#ifdef WLAN_FEATURE_GTK_OFFLOAD
17659 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17660#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17661#ifdef FEATURE_WLAN_SCAN_PNO
17662 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17663 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17664#endif /*FEATURE_WLAN_SCAN_PNO */
17665 .resume = wlan_hdd_cfg80211_resume_wlan,
17666 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17667 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17668#ifdef WLAN_NL80211_TESTMODE
17669 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17670#endif
17671#ifdef QCA_HT_2040_COEX
17672 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17673#endif
17674 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017675#ifdef CHANNEL_SWITCH_SUPPORTED
17676 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17677#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017678 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017679#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17680 defined(CFG80211_ABORT_SCAN)
17681 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17682#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017683};