blob: 5dcfbe59c959398a5112f40e24adda9b9ece91fd [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"
Paul Zhang3a210c52016-12-08 10:18:12 +080077#ifdef WLAN_UMAC_CONVERGENCE
78#include "wlan_cfg80211.h"
79#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080080#include <cdp_txrx_handle.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081
82#ifdef FEATURE_WLAN_EXTSCAN
83#include "wlan_hdd_ext_scan.h"
84#endif
85
86#ifdef WLAN_FEATURE_LINK_LAYER_STATS
87#include "wlan_hdd_stats.h"
88#endif
89#include "cds_concurrency.h"
90#include "qwlan_version.h"
91#include "wlan_hdd_memdump.h"
92
93#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070094#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095
Ravi Joshideb5a8d2015-11-09 19:11:43 -080096#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053097#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070098#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070099#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530100#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800101#include "wlan_hdd_request_manager.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800102
Leo Changfdb45c32016-10-28 11:09:23 -0700103#include <cdp_txrx_cmn.h>
104#include <cdp_txrx_misc.h>
105
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800106#define g_mode_rates_size (12)
107#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800108#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
109 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
110
111/*
112 * Android CTS verifier needs atleast this much wait time (in msec)
113 */
114#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
115
116/*
117 * Refer @tCfgProtection structure for definition of the bit map.
118 * below value is obtained by setting the following bit-fields.
119 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
120 */
121#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
122
123#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700124 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800125 .center_freq = (freq), \
126 .hw_value = (chan), \
127 .flags = (flag), \
128 .max_antenna_gain = 0, \
129 .max_power = 30, \
130}
131
132#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700133 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800134 .center_freq = (freq), \
135 .hw_value = (chan), \
136 .flags = (flag), \
137 .max_antenna_gain = 0, \
138 .max_power = 30, \
139}
140
141#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
142 { \
143 .bitrate = rate, \
144 .hw_value = rate_id, \
145 .flags = flag, \
146 }
147
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
149#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800150
151#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800152
Agrawal Ashish65634612016-08-18 13:24:32 +0530153#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
154 mode <= DFS_MODE_DEPRIORITIZE))
155#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
156 || (channel >= 36 && channel <= 184))
157
Peng Xu4d67c8f2015-10-16 16:02:26 -0700158#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530159#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700160
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800161static const u32 hdd_cipher_suites[] = {
162 WLAN_CIPHER_SUITE_WEP40,
163 WLAN_CIPHER_SUITE_WEP104,
164 WLAN_CIPHER_SUITE_TKIP,
165#ifdef FEATURE_WLAN_ESE
166#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
167#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
168 WLAN_CIPHER_SUITE_BTK,
169 WLAN_CIPHER_SUITE_KRK,
170 WLAN_CIPHER_SUITE_CCMP,
171#else
172 WLAN_CIPHER_SUITE_CCMP,
173#endif
174#ifdef FEATURE_WLAN_WAPI
175 WLAN_CIPHER_SUITE_SMS4,
176#endif
177#ifdef WLAN_FEATURE_11W
178 WLAN_CIPHER_SUITE_AES_CMAC,
179#endif
180};
181
Abhishek Singhf512bf32016-05-04 16:47:46 +0530182static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800183 HDD2GHZCHAN(2412, 1, 0),
184 HDD2GHZCHAN(2417, 2, 0),
185 HDD2GHZCHAN(2422, 3, 0),
186 HDD2GHZCHAN(2427, 4, 0),
187 HDD2GHZCHAN(2432, 5, 0),
188 HDD2GHZCHAN(2437, 6, 0),
189 HDD2GHZCHAN(2442, 7, 0),
190 HDD2GHZCHAN(2447, 8, 0),
191 HDD2GHZCHAN(2452, 9, 0),
192 HDD2GHZCHAN(2457, 10, 0),
193 HDD2GHZCHAN(2462, 11, 0),
194 HDD2GHZCHAN(2467, 12, 0),
195 HDD2GHZCHAN(2472, 13, 0),
196 HDD2GHZCHAN(2484, 14, 0),
197};
198
Abhishek Singhf512bf32016-05-04 16:47:46 +0530199static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800200 HDD5GHZCHAN(5180, 36, 0),
201 HDD5GHZCHAN(5200, 40, 0),
202 HDD5GHZCHAN(5220, 44, 0),
203 HDD5GHZCHAN(5240, 48, 0),
204 HDD5GHZCHAN(5260, 52, 0),
205 HDD5GHZCHAN(5280, 56, 0),
206 HDD5GHZCHAN(5300, 60, 0),
207 HDD5GHZCHAN(5320, 64, 0),
208 HDD5GHZCHAN(5500, 100, 0),
209 HDD5GHZCHAN(5520, 104, 0),
210 HDD5GHZCHAN(5540, 108, 0),
211 HDD5GHZCHAN(5560, 112, 0),
212 HDD5GHZCHAN(5580, 116, 0),
213 HDD5GHZCHAN(5600, 120, 0),
214 HDD5GHZCHAN(5620, 124, 0),
215 HDD5GHZCHAN(5640, 128, 0),
216 HDD5GHZCHAN(5660, 132, 0),
217 HDD5GHZCHAN(5680, 136, 0),
218 HDD5GHZCHAN(5700, 140, 0),
219 HDD5GHZCHAN(5720, 144, 0),
220 HDD5GHZCHAN(5745, 149, 0),
221 HDD5GHZCHAN(5765, 153, 0),
222 HDD5GHZCHAN(5785, 157, 0),
223 HDD5GHZCHAN(5805, 161, 0),
224 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800225 HDD5GHZCHAN(5852, 170, 0),
226 HDD5GHZCHAN(5855, 171, 0),
227 HDD5GHZCHAN(5860, 172, 0),
228 HDD5GHZCHAN(5865, 173, 0),
229 HDD5GHZCHAN(5870, 174, 0),
230 HDD5GHZCHAN(5875, 175, 0),
231 HDD5GHZCHAN(5880, 176, 0),
232 HDD5GHZCHAN(5885, 177, 0),
233 HDD5GHZCHAN(5890, 178, 0),
234 HDD5GHZCHAN(5895, 179, 0),
235 HDD5GHZCHAN(5900, 180, 0),
236 HDD5GHZCHAN(5905, 181, 0),
237 HDD5GHZCHAN(5910, 182, 0),
238 HDD5GHZCHAN(5915, 183, 0),
239 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800240};
241
242static struct ieee80211_rate g_mode_rates[] = {
243 HDD_G_MODE_RATETAB(10, 0x1, 0),
244 HDD_G_MODE_RATETAB(20, 0x2, 0),
245 HDD_G_MODE_RATETAB(55, 0x4, 0),
246 HDD_G_MODE_RATETAB(110, 0x8, 0),
247 HDD_G_MODE_RATETAB(60, 0x10, 0),
248 HDD_G_MODE_RATETAB(90, 0x20, 0),
249 HDD_G_MODE_RATETAB(120, 0x40, 0),
250 HDD_G_MODE_RATETAB(180, 0x80, 0),
251 HDD_G_MODE_RATETAB(240, 0x100, 0),
252 HDD_G_MODE_RATETAB(360, 0x200, 0),
253 HDD_G_MODE_RATETAB(480, 0x400, 0),
254 HDD_G_MODE_RATETAB(540, 0x800, 0),
255};
256
257static struct ieee80211_rate a_mode_rates[] = {
258 HDD_G_MODE_RATETAB(60, 0x10, 0),
259 HDD_G_MODE_RATETAB(90, 0x20, 0),
260 HDD_G_MODE_RATETAB(120, 0x40, 0),
261 HDD_G_MODE_RATETAB(180, 0x80, 0),
262 HDD_G_MODE_RATETAB(240, 0x100, 0),
263 HDD_G_MODE_RATETAB(360, 0x200, 0),
264 HDD_G_MODE_RATETAB(480, 0x400, 0),
265 HDD_G_MODE_RATETAB(540, 0x800, 0),
266};
267
268static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530269 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800270 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700271 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800272 .bitrates = g_mode_rates,
273 .n_bitrates = g_mode_rates_size,
274 .ht_cap.ht_supported = 1,
275 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
276 | IEEE80211_HT_CAP_GRN_FLD
277 | IEEE80211_HT_CAP_DSSSCCK40
278 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
279 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
280 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
281 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
282 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
283 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
284 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
285};
286
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800287static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530288 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800289 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700290 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800291 .bitrates = a_mode_rates,
292 .n_bitrates = a_mode_rates_size,
293 .ht_cap.ht_supported = 1,
294 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
295 | IEEE80211_HT_CAP_GRN_FLD
296 | IEEE80211_HT_CAP_DSSSCCK40
297 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
298 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
299 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
300 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
301 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
302 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
303 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
304 .vht_cap.vht_supported = 1,
305};
306
307/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800308 * TX/RX direction for each kind of interface
309 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800310static const struct ieee80211_txrx_stypes
311 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
312 [NL80211_IFTYPE_STATION] = {
313 .tx = 0xffff,
314 .rx = BIT(SIR_MAC_MGMT_ACTION) |
315 BIT(SIR_MAC_MGMT_PROBE_REQ),
316 },
317 [NL80211_IFTYPE_AP] = {
318 .tx = 0xffff,
319 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
320 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
321 BIT(SIR_MAC_MGMT_PROBE_REQ) |
322 BIT(SIR_MAC_MGMT_DISASSOC) |
323 BIT(SIR_MAC_MGMT_AUTH) |
324 BIT(SIR_MAC_MGMT_DEAUTH) |
325 BIT(SIR_MAC_MGMT_ACTION),
326 },
327 [NL80211_IFTYPE_ADHOC] = {
328 .tx = 0xffff,
329 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
331 BIT(SIR_MAC_MGMT_PROBE_REQ) |
332 BIT(SIR_MAC_MGMT_DISASSOC) |
333 BIT(SIR_MAC_MGMT_AUTH) |
334 BIT(SIR_MAC_MGMT_DEAUTH) |
335 BIT(SIR_MAC_MGMT_ACTION),
336 },
337 [NL80211_IFTYPE_P2P_CLIENT] = {
338 .tx = 0xffff,
339 .rx = BIT(SIR_MAC_MGMT_ACTION) |
340 BIT(SIR_MAC_MGMT_PROBE_REQ),
341 },
342 [NL80211_IFTYPE_P2P_GO] = {
343 /* This is also same as for SoftAP */
344 .tx = 0xffff,
345 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
346 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
347 BIT(SIR_MAC_MGMT_PROBE_REQ) |
348 BIT(SIR_MAC_MGMT_DISASSOC) |
349 BIT(SIR_MAC_MGMT_AUTH) |
350 BIT(SIR_MAC_MGMT_DEAUTH) |
351 BIT(SIR_MAC_MGMT_ACTION),
352 },
353};
354
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800355/* Interface limits and combinations registered by the driver */
356
357/* STA ( + STA ) combination */
358static const struct ieee80211_iface_limit
359 wlan_hdd_sta_iface_limit[] = {
360 {
361 .max = 3, /* p2p0 is a STA as well */
362 .types = BIT(NL80211_IFTYPE_STATION),
363 },
364};
365
366/* ADHOC (IBSS) limit */
367static const struct ieee80211_iface_limit
368 wlan_hdd_adhoc_iface_limit[] = {
369 {
370 .max = 1,
371 .types = BIT(NL80211_IFTYPE_STATION),
372 },
373 {
374 .max = 1,
375 .types = BIT(NL80211_IFTYPE_ADHOC),
376 },
377};
378
379/* AP ( + AP ) combination */
380static const struct ieee80211_iface_limit
381 wlan_hdd_ap_iface_limit[] = {
382 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530383 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800384 .types = BIT(NL80211_IFTYPE_AP),
385 },
386};
387
388/* P2P limit */
389static const struct ieee80211_iface_limit
390 wlan_hdd_p2p_iface_limit[] = {
391 {
392 .max = 1,
393 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
394 },
395 {
396 .max = 1,
397 .types = BIT(NL80211_IFTYPE_P2P_GO),
398 },
399};
400
401static const struct ieee80211_iface_limit
402 wlan_hdd_sta_ap_iface_limit[] = {
403 {
404 /* We need 1 extra STA interface for OBSS scan when SAP starts
405 * with HT40 in STA+SAP concurrency mode
406 */
407 .max = (1 + SAP_MAX_OBSS_STA_CNT),
408 .types = BIT(NL80211_IFTYPE_STATION),
409 },
410 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530411 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800412 .types = BIT(NL80211_IFTYPE_AP),
413 },
414};
415
416/* STA + P2P combination */
417static const struct ieee80211_iface_limit
418 wlan_hdd_sta_p2p_iface_limit[] = {
419 {
420 /* One reserved for dedicated P2PDEV usage */
421 .max = 2,
422 .types = BIT(NL80211_IFTYPE_STATION)
423 },
424 {
425 /* Support for two identical (GO + GO or CLI + CLI)
426 * or dissimilar (GO + CLI) P2P interfaces
427 */
428 .max = 2,
429 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
430 },
431};
432
433/* STA + AP + P2PGO combination */
434static const struct ieee80211_iface_limit
435wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
436 /* Support for AP+P2PGO interfaces */
437 {
438 .max = 2,
439 .types = BIT(NL80211_IFTYPE_STATION)
440 },
441 {
442 .max = 1,
443 .types = BIT(NL80211_IFTYPE_P2P_GO)
444 },
445 {
446 .max = 1,
447 .types = BIT(NL80211_IFTYPE_AP)
448 }
449};
450
451/* SAP + P2P combination */
452static const struct ieee80211_iface_limit
453wlan_hdd_sap_p2p_iface_limit[] = {
454 {
455 /* 1 dedicated for p2p0 which is a STA type */
456 .max = 1,
457 .types = BIT(NL80211_IFTYPE_STATION)
458 },
459 {
460 /* The p2p interface in SAP+P2P can be GO/CLI.
461 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
462 */
463 .max = 1,
464 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
465 },
466 {
467 /* SAP+GO to support only one SAP interface */
468 .max = 1,
469 .types = BIT(NL80211_IFTYPE_AP)
470 }
471};
472
473/* P2P + P2P combination */
474static const struct ieee80211_iface_limit
475wlan_hdd_p2p_p2p_iface_limit[] = {
476 {
477 /* 1 dedicated for p2p0 which is a STA type */
478 .max = 1,
479 .types = BIT(NL80211_IFTYPE_STATION)
480 },
481 {
482 /* The p2p interface in P2P+P2P can be GO/CLI.
483 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
484 */
485 .max = 2,
486 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
487 },
488};
489
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700490static const struct ieee80211_iface_limit
491 wlan_hdd_mon_iface_limit[] = {
492 {
493 .max = 3, /* Monitor interface */
494 .types = BIT(NL80211_IFTYPE_MONITOR),
495 },
496};
497
498static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800499 wlan_hdd_iface_combination[] = {
500 /* STA */
501 {
502 .limits = wlan_hdd_sta_iface_limit,
503 .num_different_channels = 2,
504 .max_interfaces = 3,
505 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
506 },
507 /* ADHOC */
508 {
509 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700510 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800511 .max_interfaces = 2,
512 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
513 },
514 /* AP */
515 {
516 .limits = wlan_hdd_ap_iface_limit,
517 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530518 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800519 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
520 },
521 /* P2P */
522 {
523 .limits = wlan_hdd_p2p_iface_limit,
524 .num_different_channels = 2,
525 .max_interfaces = 2,
526 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
527 },
528 /* STA + AP */
529 {
530 .limits = wlan_hdd_sta_ap_iface_limit,
531 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530532 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800533 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
534 .beacon_int_infra_match = true,
535 },
536 /* STA + P2P */
537 {
538 .limits = wlan_hdd_sta_p2p_iface_limit,
539 .num_different_channels = 2,
540 /* one interface reserved for P2PDEV dedicated usage */
541 .max_interfaces = 4,
542 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
543 .beacon_int_infra_match = true,
544 },
545 /* STA + P2P GO + SAP */
546 {
547 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
548 /* we can allow 3 channels for three different persona
549 * but due to firmware limitation, allow max 2 concrnt channels.
550 */
551 .num_different_channels = 2,
552 /* one interface reserved for P2PDEV dedicated usage */
553 .max_interfaces = 4,
554 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
555 .beacon_int_infra_match = true,
556 },
557 /* SAP + P2P */
558 {
559 .limits = wlan_hdd_sap_p2p_iface_limit,
560 .num_different_channels = 2,
561 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
562 .max_interfaces = 3,
563 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
564 .beacon_int_infra_match = true,
565 },
566 /* P2P + P2P */
567 {
568 .limits = wlan_hdd_p2p_p2p_iface_limit,
569 .num_different_channels = 2,
570 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
571 .max_interfaces = 3,
572 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
573 .beacon_int_infra_match = true,
574 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530575 /* Monitor */
576 {
577 .limits = wlan_hdd_mon_iface_limit,
578 .max_interfaces = 3,
579 .num_different_channels = 2,
580 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
581 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800583
584static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585
586#ifdef WLAN_NL80211_TESTMODE
587enum wlan_hdd_tm_attr {
588 WLAN_HDD_TM_ATTR_INVALID = 0,
589 WLAN_HDD_TM_ATTR_CMD = 1,
590 WLAN_HDD_TM_ATTR_DATA = 2,
591 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
592 WLAN_HDD_TM_ATTR_TYPE = 4,
593 /* keep last */
594 WLAN_HDD_TM_ATTR_AFTER_LAST,
595 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
596};
597
598enum wlan_hdd_tm_cmd {
599 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
600 WLAN_HDD_TM_CMD_WLAN_HB = 1,
601};
602
603#define WLAN_HDD_TM_DATA_MAX_LEN 5000
604
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530605enum wlan_hdd_vendor_ie_access_policy {
606 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
607 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
608};
609
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
611 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
612 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
613 .len = WLAN_HDD_TM_DATA_MAX_LEN},
614};
615#endif /* WLAN_NL80211_TESTMODE */
616
617#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
618static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
619 .flags = WIPHY_WOWLAN_MAGIC_PKT,
620 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
621 .pattern_min_len = 1,
622 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
623};
624#endif
625
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530627 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
628 * @flags: Pointer to the flags to Add channel switch flag.
629 *
630 * This Function adds Channel Switch support flag, if channel switch is
631 * supported by kernel.
632 * Return: void.
633 */
634#ifdef CHANNEL_SWITCH_SUPPORTED
635static inline void hdd_add_channel_switch_support(uint32_t *flags)
636{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800637 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530638 return;
639}
640#else
641static inline void hdd_add_channel_switch_support(uint32_t *flags)
642{
643 return;
644}
645#endif
646
Manikandan Mohan22b83722015-12-15 15:03:23 -0800647#ifdef FEATURE_WLAN_TDLS
648
649/* TDLS capabilities params */
650#define PARAM_MAX_TDLS_SESSION \
651 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
652#define PARAM_TDLS_FEATURE_SUPPORT \
653 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
654
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530655/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
657 * @wiphy: WIPHY structure pointer
658 * @wdev: Wireless device structure pointer
659 * @data: Pointer to the data received
660 * @data_len: Length of the data received
661 *
662 * This function provides TDLS capabilities
663 *
664 * Return: 0 on success and errno on failure
665 */
666static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
667 struct wireless_dev *wdev,
668 const void *data,
669 int data_len)
670{
671 int status;
672 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
673 struct sk_buff *skb;
674 uint32_t set = 0;
675
Jeff Johnson1f61b612016-02-12 16:28:33 -0800676 ENTER_DEV(wdev->netdev);
677
Anurag Chouhan6d760662016-02-20 16:05:43 +0530678 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679 hdd_err("Command not allowed in FTM mode");
680 return -EPERM;
681 }
682
683 status = wlan_hdd_validate_context(hdd_ctx);
684 if (status)
685 return status;
686
687 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
688 NLMSG_HDRLEN);
689 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700690 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691 goto fail;
692 }
693
694 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700695 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
697 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700698 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 goto fail;
700 }
701 } else {
702 set = set | WIFI_TDLS_SUPPORT;
703 set = set | (hdd_ctx->config->fTDLSExternalControl ?
704 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
705 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
706 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700707 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
709 hdd_ctx->max_num_tdls_sta) ||
710 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
711 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700712 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800713 goto fail;
714 }
715 }
716 return cfg80211_vendor_cmd_reply(skb);
717fail:
718 if (skb)
719 kfree_skb(skb);
720 return -EINVAL;
721}
722
723/**
724 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
725 * @wiphy: WIPHY structure pointer
726 * @wdev: Wireless device structure pointer
727 * @data: Pointer to the data received
728 * @data_len: Length of the data received
729 *
730 * This function provides TDLS capabilities
731 *
732 * Return: 0 on success and errno on failure
733 */
734static int
735wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
736 struct wireless_dev *wdev,
737 const void *data,
738 int data_len)
739{
740 int ret;
741
742 cds_ssr_protect(__func__);
743 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
744 data, data_len);
745 cds_ssr_unprotect(__func__);
746
747 return ret;
748}
749#endif
750
751#ifdef QCA_HT_2040_COEX
752static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
753#endif
754
755#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
756/*
757 * FUNCTION: wlan_hdd_send_avoid_freq_event
758 * This is called when wlan driver needs to send vendor specific
759 * avoid frequency range event to userspace
760 */
761int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
762 tHddAvoidFreqList *pAvoidFreqList)
763{
764 struct sk_buff *vendor_event;
765
766 ENTER();
767
768 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700769 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800770 return -EINVAL;
771 }
772
773 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700774 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 return -EINVAL;
776 }
777
778 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
779 NULL,
780 sizeof(tHddAvoidFreqList),
781 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
782 GFP_KERNEL);
783 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700784 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785 return -EINVAL;
786 }
787
788 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
789 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
790
791 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
792
793 EXIT();
794 return 0;
795}
796#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
797
798/* vendor specific events */
799static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
800#ifdef FEATURE_WLAN_CH_AVOID
801 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
802 .vendor_id =
803 QCA_NL80211_VENDOR_ID,
804 .subcmd =
805 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
806 },
807#endif /* FEATURE_WLAN_CH_AVOID */
808
809#ifdef WLAN_FEATURE_NAN
810 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
811 .vendor_id =
812 QCA_NL80211_VENDOR_ID,
813 .subcmd =
814 QCA_NL80211_VENDOR_SUBCMD_NAN
815 },
816#endif
817
818#ifdef WLAN_FEATURE_STATS_EXT
819 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
820 .vendor_id =
821 QCA_NL80211_VENDOR_ID,
822 .subcmd =
823 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
824 },
825#endif /* WLAN_FEATURE_STATS_EXT */
826#ifdef FEATURE_WLAN_EXTSCAN
827 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
828 .vendor_id =
829 QCA_NL80211_VENDOR_ID,
830 .subcmd =
831 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
832 },
833 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
834 .vendor_id =
835 QCA_NL80211_VENDOR_ID,
836 .subcmd =
837 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
838 },
839 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
840 .
841 vendor_id
842 =
843 QCA_NL80211_VENDOR_ID,
844 .subcmd =
845 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
846 },
847 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
848 .
849 vendor_id
850 =
851 QCA_NL80211_VENDOR_ID,
852 .
853 subcmd =
854 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
855 },
856 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
857 .
858 vendor_id
859 =
860 QCA_NL80211_VENDOR_ID,
861 .
862 subcmd
863 =
864 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
865 },
866 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
867 .
868 vendor_id
869 =
870 QCA_NL80211_VENDOR_ID,
871 .subcmd =
872 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
873 },
874 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
875 .vendor_id =
876 QCA_NL80211_VENDOR_ID,
877 .subcmd =
878 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
879 },
880 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
881 .
882 vendor_id
883 =
884 QCA_NL80211_VENDOR_ID,
885 .subcmd =
886 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
887 },
888 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
889 .
890 vendor_id
891 =
892 QCA_NL80211_VENDOR_ID,
893 .subcmd =
894 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
895 },
896 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
897 .
898 vendor_id
899 =
900 QCA_NL80211_VENDOR_ID,
901 .
902 subcmd
903 =
904 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
905 },
906 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
907 .
908 vendor_id
909 =
910 QCA_NL80211_VENDOR_ID,
911 .
912 subcmd =
913 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
914 },
915 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
916 .
917 vendor_id
918 =
919 QCA_NL80211_VENDOR_ID,
920 .
921 subcmd
922 =
923 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
924 },
925 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
926 .
927 vendor_id
928 =
929 QCA_NL80211_VENDOR_ID,
930 .
931 subcmd
932 =
933 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
934 },
935 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
936 .vendor_id = QCA_NL80211_VENDOR_ID,
937 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
938 },
939 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
940 .vendor_id = QCA_NL80211_VENDOR_ID,
941 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
942 },
943#endif /* FEATURE_WLAN_EXTSCAN */
944
945#ifdef WLAN_FEATURE_LINK_LAYER_STATS
946 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
947 .vendor_id =
948 QCA_NL80211_VENDOR_ID,
949 .subcmd =
950 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
951 },
952 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
953 .vendor_id =
954 QCA_NL80211_VENDOR_ID,
955 .subcmd =
956 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
957 },
958 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
959 .vendor_id =
960 QCA_NL80211_VENDOR_ID,
961 .subcmd =
962 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
963 },
964 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
965 .vendor_id =
966 QCA_NL80211_VENDOR_ID,
967 .subcmd =
968 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
969 },
970 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
971 .vendor_id =
972 QCA_NL80211_VENDOR_ID,
973 .subcmd =
974 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
975 },
976 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
981 },
982#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
983 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
984 .vendor_id =
985 QCA_NL80211_VENDOR_ID,
986 .subcmd =
987 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
988 },
989 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
990 .vendor_id = QCA_NL80211_VENDOR_ID,
991 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
992 },
993#ifdef WLAN_FEATURE_ROAM_OFFLOAD
994 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
995 .vendor_id =
996 QCA_NL80211_VENDOR_ID,
997 .subcmd =
998 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
999 },
1000#endif
1001 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1002 .vendor_id =
1003 QCA_NL80211_VENDOR_ID,
1004 .subcmd =
1005 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1006 },
1007 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1020 .vendor_id =
1021 QCA_NL80211_VENDOR_ID,
1022 .subcmd =
1023 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1024 },
1025 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1026 .vendor_id =
1027 QCA_NL80211_VENDOR_ID,
1028 .subcmd =
1029 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1030 },
1031#ifdef FEATURE_WLAN_EXTSCAN
1032 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1033 .vendor_id = QCA_NL80211_VENDOR_ID,
1034 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1035 },
1036 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1037 .vendor_id = QCA_NL80211_VENDOR_ID,
1038 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1039 },
1040 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1041 .vendor_id = QCA_NL80211_VENDOR_ID,
1042 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1043 },
1044 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1045 .vendor_id = QCA_NL80211_VENDOR_ID,
1046 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1047 },
1048 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1049 .vendor_id = QCA_NL80211_VENDOR_ID,
1050 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1051 },
1052#endif /* FEATURE_WLAN_EXTSCAN */
1053 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1054 .vendor_id = QCA_NL80211_VENDOR_ID,
1055 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1056 },
1057#ifdef WLAN_FEATURE_MEMDUMP
1058 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1059 .vendor_id = QCA_NL80211_VENDOR_ID,
1060 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1061 },
1062#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001063#ifdef WLAN_FEATURE_TSF
1064 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1067 },
1068#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001069 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1070 .vendor_id = QCA_NL80211_VENDOR_ID,
1071 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1072 },
1073 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1074 .vendor_id = QCA_NL80211_VENDOR_ID,
1075 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1076 },
1077 /* OCB events */
1078 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1079 .vendor_id = QCA_NL80211_VENDOR_ID,
1080 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1081 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001082#ifdef FEATURE_LFR_SUBNET_DETECTION
1083 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1084 .vendor_id = QCA_NL80211_VENDOR_ID,
1085 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1086 },
1087#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001088
1089#ifdef WLAN_FEATURE_NAN_DATAPATH
1090 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1091 .vendor_id = QCA_NL80211_VENDOR_ID,
1092 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1093 },
1094#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001095
1096 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1097 .vendor_id = QCA_NL80211_VENDOR_ID,
1098 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1099 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301100 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1101 .vendor_id = QCA_NL80211_VENDOR_ID,
1102 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1103 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301104 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1105 .vendor_id = QCA_NL80211_VENDOR_ID,
1106 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1107 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001108#ifdef WLAN_UMAC_CONVERGENCE
1109 COMMON_VENDOR_EVENTS
1110#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111};
1112
1113/**
1114 * __is_driver_dfs_capable() - get driver DFS capability
1115 * @wiphy: pointer to wireless wiphy structure.
1116 * @wdev: pointer to wireless_dev structure.
1117 * @data: Pointer to the data to be passed via vendor interface
1118 * @data_len:Length of the data to be passed
1119 *
1120 * This function is called by userspace to indicate whether or not
1121 * the driver supports DFS offload.
1122 *
1123 * Return: 0 on success, negative errno on failure
1124 */
1125static int __is_driver_dfs_capable(struct wiphy *wiphy,
1126 struct wireless_dev *wdev,
1127 const void *data,
1128 int data_len)
1129{
1130 u32 dfs_capability = 0;
1131 struct sk_buff *temp_skbuff;
1132 int ret_val;
1133 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1134
Jeff Johnson1f61b612016-02-12 16:28:33 -08001135 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136
1137 ret_val = wlan_hdd_validate_context(hdd_ctx);
1138 if (ret_val)
1139 return ret_val;
1140
Anurag Chouhan6d760662016-02-20 16:05:43 +05301141 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142 hdd_err("Command not allowed in FTM mode");
1143 return -EPERM;
1144 }
1145
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001147
1148 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1149 NLMSG_HDRLEN);
1150
1151 if (temp_skbuff != NULL) {
1152 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1153 dfs_capability);
1154 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001155 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001156 kfree_skb(temp_skbuff);
1157
1158 return ret_val;
1159 }
1160
1161 return cfg80211_vendor_cmd_reply(temp_skbuff);
1162 }
1163
Jeff Johnson020db452016-06-29 14:37:26 -07001164 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001165 return -ENOMEM;
1166}
1167
1168/**
1169 * is_driver_dfs_capable() - get driver DFS capability
1170 * @wiphy: pointer to wireless wiphy structure.
1171 * @wdev: pointer to wireless_dev structure.
1172 * @data: Pointer to the data to be passed via vendor interface
1173 * @data_len:Length of the data to be passed
1174 *
1175 * This function is called by userspace to indicate whether or not
1176 * the driver supports DFS offload. This is an SSR-protected
1177 * wrapper function.
1178 *
1179 * Return: 0 on success, negative errno on failure
1180 */
1181static int is_driver_dfs_capable(struct wiphy *wiphy,
1182 struct wireless_dev *wdev,
1183 const void *data,
1184 int data_len)
1185{
1186 int ret;
1187
1188 cds_ssr_protect(__func__);
1189 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1190 cds_ssr_unprotect(__func__);
1191
1192 return ret;
1193}
1194
1195/**
1196 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1197 *
1198 * @adapter: SAP adapter pointer
1199 *
1200 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1201 * radio. So in case of DFS MCC scenario override current SAP given config
1202 * to follow concurrent SAP DFS config
1203 *
1204 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1205 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1207{
1208 hdd_adapter_t *con_sap_adapter;
1209 tsap_Config_t *sap_config, *con_sap_config;
1210 int con_ch;
1211
1212 /*
1213 * Check if AP+AP case, once primary AP chooses a DFS
1214 * channel secondary AP should always follow primary APs channel
1215 */
1216 if (!cds_concurrent_beaconing_sessions_running())
1217 return 0;
1218
1219 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1220 if (!con_sap_adapter)
1221 return 0;
1222
1223 sap_config = &adapter->sessionCtx.ap.sapConfig;
1224 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1225 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1226
1227 if (!CDS_IS_DFS_CH(con_ch))
1228 return 0;
1229
Jeff Johnson020db452016-06-29 14:37:26 -07001230 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001232 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001233 sap_config->channel = con_ch;
1234
1235 if (con_sap_config->acs_cfg.acs_mode == true) {
1236 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1237 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001238 hdd_err("Primary AP channel config error");
1239 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240 con_ch, con_sap_config->acs_cfg.pri_ch,
1241 con_sap_config->acs_cfg.ht_sec_ch);
1242 return -EINVAL;
1243 }
1244 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1245 * MCC restriction. So free ch list allocated in do_acs
1246 * func for Sec AP and realloc for Pri AP ch list size
1247 */
1248 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301249 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001250
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301251 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001252 &con_sap_config->acs_cfg,
1253 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301254 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 sizeof(uint8_t) *
1256 con_sap_config->acs_cfg.ch_list_count);
1257 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001258 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001259 return -ENOMEM;
1260 }
1261
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301262 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001263 con_sap_config->acs_cfg.ch_list,
1264 con_sap_config->acs_cfg.ch_list_count);
1265
1266 } else {
1267 sap_config->acs_cfg.pri_ch = con_ch;
1268 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1269 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1270 }
1271
1272 return con_ch;
1273}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001274
1275/**
1276 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1277 * @sap_cfg: pointer to SAP config struct
1278 *
1279 * This function sets the default ACS start and end channel for the given band
1280 * and also parses the given ACS channel list.
1281 *
1282 * Return: None
1283 */
1284
1285static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1286 bool vht_enabled)
1287{
1288 int i;
1289 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1290 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001291 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1292 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001293 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1294 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001295 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1296 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001299 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1300 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1302 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001303 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1304 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305 }
1306
1307 if (ht_enabled)
1308 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1309
1310 if (vht_enabled)
1311 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1312
1313
1314 /* Parse ACS Chan list from hostapd */
1315 if (!sap_cfg->acs_cfg.ch_list)
1316 return;
1317
1318 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1319 sap_cfg->acs_cfg.end_ch =
1320 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1321 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301322 /* avoid channel as start channel */
1323 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1324 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001325 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1326 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1327 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1328 }
1329}
1330
1331
1332static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1333
1334/**
1335 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1336 * @adapter: pointer to SAP adapter struct
1337 *
1338 * This function starts the ACS procedure if there are no
1339 * constraints like MBSSID DFS restrictions.
1340 *
1341 * Return: Status of ACS Start procedure
1342 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301343int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001344{
1345
1346 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1347 tsap_Config_t *sap_config;
1348 tpWLAN_SAPEventCB acs_event_callback;
1349 int status;
1350
1351 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301352 if (hdd_ctx->acs_policy.acs_channel)
1353 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1354 else
1355 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001356
1357 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001358 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001359 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001360
1361 if (status > 0) {
1362 /*notify hostapd about channel override */
1363 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1364 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1365 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001366 }
Jeff Johnson68755312017-02-10 11:46:55 -08001367
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001368 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1369 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001370 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 return -EINVAL;
1372 }
1373
1374 acs_event_callback = hdd_hostapd_sap_event_cb;
1375
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301376 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301377 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301378 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001380 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001381 acs_event_callback, sap_config, adapter->dev);
1382
1383
1384 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001385 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386 return -EINVAL;
1387 }
bings394afdd2017-01-09 11:22:38 +08001388 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1389 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001390 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1391
1392 return 0;
1393}
1394
1395/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301396 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1397 * @ap_adapter: AP adapter
1398 * @nol: Non-occupancy list
1399 * @nol_len: Length of NOL
1400 *
1401 * Get the NOL for SAP
1402 *
1403 * Return: Zero on success, non-zero on failure
1404 */
1405static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1406 uint32_t *nol_len)
1407{
1408 QDF_STATUS ret;
1409
1410 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1411 nol, nol_len);
1412 if (QDF_IS_STATUS_ERROR(ret))
1413 return -EINVAL;
1414
1415 return 0;
1416}
1417
1418/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301419 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1420 * @hdd_ctx: hdd context
1421 * @acs_chan_params: external acs channel params
1422 * @sap_config: SAP config
1423 *
1424 * This API provides unsorted pcl list.
1425 * this list is a subset of the valid channel list given by hostapd.
1426 * if channel is not present in pcl, weightage will be given as zero
1427 *
1428 * Return: Zero on success, non-zero on failure
1429 */
1430static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1431 struct hdd_vendor_acs_chan_params *acs_chan_params,
1432 tsap_Config_t *sap_config)
1433{
1434 int i, j;
1435
1436 for (i = 0; i < acs_chan_params->channel_count; i++) {
1437 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1438 if (acs_chan_params->channel_list[i] ==
1439 sap_config->acs_cfg.pcl_channels[j]) {
1440 acs_chan_params->vendor_pcl_list[i] =
1441 sap_config->acs_cfg.pcl_channels[j];
1442 acs_chan_params->vendor_weight_list[i] =
1443 sap_config->acs_cfg.
1444 pcl_channels_weight_list[j];
1445 break;
1446 } else {
1447 acs_chan_params->vendor_pcl_list[i] =
1448 acs_chan_params->channel_list[i];
1449 acs_chan_params->vendor_weight_list[i] = 0;
1450 }
1451 }
1452 }
1453 if (hdd_ctx->unsafe_channel_count == 0)
1454 return;
1455 /* Update unsafe channel weight as zero */
1456 for (i = 0; i < acs_chan_params->channel_count; i++) {
1457 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1458 if (acs_chan_params->channel_list[i] ==
1459 hdd_ctx->unsafe_channel_list[j]) {
1460 acs_chan_params->vendor_weight_list[i] = 0;
1461 }
1462 }
1463 }
1464}
1465
1466/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301467 * hdd_update_reg_chan_info : This API contructs channel info
1468 * for all the given channel
1469 * @adapter: pointer to SAP adapter struct
1470 * @channel_count: channel count
1471 * @channel_list: channel list
1472 *
1473 * Return: Status of of channel information updation
1474 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301475static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301476 uint32_t channel_count,
1477 uint8_t *channel_list)
1478{
1479 int i;
1480 struct hdd_channel_info *icv;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301481 struct ch_params_s ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301482 uint8_t bw_offset = 0, chan = 0;
1483 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1484 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1485
1486 /* memory allocation */
1487 sap_config->channel_info = qdf_mem_malloc(
1488 sizeof(struct hdd_channel_info) *
1489 channel_count);
1490 if (!sap_config->channel_info) {
1491 hdd_err("memory allocation failed");
1492 return -ENOMEM;
1493
1494 }
1495 for (i = 0; i < channel_count; i++) {
1496 icv = &sap_config->channel_info[i];
1497 chan = channel_list[i];
1498
1499 if (chan == 0)
1500 continue;
1501
1502 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1503 bw_offset = 1 << BW_40_OFFSET_BIT;
1504 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1505 bw_offset = 1 << BW_20_OFFSET_BIT;
1506 icv->freq = cds_get_channel_freq(chan);
1507 icv->ieee_chan_number = chan;
1508 icv->max_reg_power = cds_get_channel_reg_power(chan);
1509
1510 /* filling demo values */
1511 icv->max_radio_power = HDD_MAX_TX_POWER;
1512 icv->min_radio_power = HDD_MIN_TX_POWER;
1513 /* not supported in current driver */
1514 icv->max_antenna_gain = 0;
1515
1516 icv->reg_class_id = wlan_hdd_find_opclass(
1517 WLAN_HDD_GET_HAL_CTX(adapter),
1518 chan, bw_offset);
1519
1520 if (CDS_IS_CHANNEL_5GHZ(chan)) {
1521 ch_params.ch_width = sap_config->acs_cfg.ch_width;
1522 cds_set_channel_params(chan, 0, &ch_params);
1523 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1524 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1525 }
1526 icv->flags = 0;
1527 icv->flags = cds_get_vendor_reg_flags(chan,
1528 sap_config->acs_cfg.ch_width,
1529 sap_config->acs_cfg.is_ht_enabled,
1530 sap_config->acs_cfg.is_vht_enabled,
1531 hdd_ctx->config->enable_sub_20_channel_width);
1532
1533 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1534 icv->freq, icv->flags,
1535 icv->flagext, icv->ieee_chan_number,
1536 icv->max_reg_power, icv->max_radio_power,
1537 icv->min_radio_power, icv->reg_class_id,
1538 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1539 icv->vht_center_freq_seg1);
1540 }
1541 return 0;
1542}
1543
1544/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1545#define CHAN_INFO_ATTR_FLAGS \
1546 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1547#define CHAN_INFO_ATTR_FLAG_EXT \
1548 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1549#define CHAN_INFO_ATTR_FREQ \
1550 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1551#define CHAN_INFO_ATTR_MAX_REG_POWER \
1552 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1553#define CHAN_INFO_ATTR_MAX_POWER \
1554 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1555#define CHAN_INFO_ATTR_MIN_POWER \
1556 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1557#define CHAN_INFO_ATTR_REG_CLASS_ID \
1558 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1559#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1560 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1561#define CHAN_INFO_ATTR_VHT_SEG_0 \
1562 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1563#define CHAN_INFO_ATTR_VHT_SEG_1 \
1564 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1565
1566/**
1567 * hdd_cfg80211_update_channel_info() - add channel info attributes
1568 * @skb: pointer to sk buff
1569 * @hdd_ctx: pointer to hdd station context
1570 * @idx: attribute index
1571 *
1572 * Return: Success(0) or reason code for failure
1573 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301574static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301575hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1576 tsap_Config_t *sap_config, int idx)
1577{
1578 struct nlattr *nla_attr, *channel;
1579 struct hdd_channel_info *icv;
1580 int i;
1581
1582 nla_attr = nla_nest_start(skb, idx);
1583 if (!nla_attr)
1584 goto fail;
1585
1586 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1587 channel = nla_nest_start(skb, i);
1588 if (!channel)
1589 goto fail;
1590
1591 icv = &sap_config->channel_info[i];
1592 if (!icv) {
1593 hdd_err("channel info not found");
1594 goto fail;
1595 }
1596 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1597 icv->freq) ||
1598 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1599 icv->flags) ||
1600 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1601 icv->flagext) ||
1602 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1603 icv->max_reg_power) ||
1604 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1605 icv->max_radio_power) ||
1606 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1607 icv->min_radio_power) ||
1608 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1609 icv->reg_class_id) ||
1610 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1611 icv->max_antenna_gain) ||
1612 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1613 icv->vht_center_freq_seg0) ||
1614 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1615 icv->vht_center_freq_seg1)) {
1616 hdd_err("put fail");
1617 goto fail;
1618 }
1619 nla_nest_end(skb, channel);
1620 }
1621 nla_nest_end(skb, nla_attr);
1622 return 0;
1623fail:
1624 hdd_err("nl channel update failed");
1625 return -EINVAL;
1626}
1627#undef CHAN_INFO_ATTR_FLAGS
1628#undef CHAN_INFO_ATTR_FLAG_EXT
1629#undef CHAN_INFO_ATTR_FREQ
1630#undef CHAN_INFO_ATTR_MAX_REG_POWER
1631#undef CHAN_INFO_ATTR_MAX_POWER
1632#undef CHAN_INFO_ATTR_MIN_POWER
1633#undef CHAN_INFO_ATTR_REG_CLASS_ID
1634#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1635#undef CHAN_INFO_ATTR_VHT_SEG_0
1636#undef CHAN_INFO_ATTR_VHT_SEG_1
1637
1638/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301639 * hdd_cfg80211_update_pcl() - add pcl info attributes
1640 * @skb: pointer to sk buff
1641 * @hdd_ctx: pointer to hdd station context
1642 * @idx: attribute index
1643 * @vendor_pcl_list: PCL list
1644 * @vendor_weight_list: PCL weights
1645 *
1646 * Return: Success(0) or reason code for failure
1647 */
1648static int32_t
1649hdd_cfg80211_update_pcl(struct sk_buff *skb,
1650 uint8_t ch_list_count, int idx,
1651 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1652{
1653 struct nlattr *nla_attr, *channel;
1654 int i;
1655
1656 nla_attr = nla_nest_start(skb, idx);
1657
1658 if (!nla_attr)
1659 goto fail;
1660
1661 for (i = 0; i < ch_list_count; i++) {
1662 channel = nla_nest_start(skb, i);
1663 if (!channel)
1664 goto fail;
1665 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1666 vendor_pcl_list[i]) ||
1667 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1668 vendor_weight_list[i])) {
1669 hdd_err("put fail");
1670 goto fail;
1671 }
1672 nla_nest_end(skb, channel);
1673 }
1674 nla_nest_end(skb, nla_attr);
1675
1676 return 0;
1677fail:
1678 hdd_err("updating pcl list failed");
1679 return -EINVAL;
1680}
1681
1682static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1683{
1684 /* Get scan band */
1685 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1686 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1687 *band = eCSR_BAND_24;
1688 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1689 *band = eCSR_BAND_5G;
1690 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1691 *band = eCSR_BAND_ALL;
1692 }
1693 /* Auto is not supported currently */
1694 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1695 hdd_err("invalid band");
1696 *band = eCSR_BAND_24;
1697 }
1698}
1699
1700void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1701 uint8_t reason)
1702{
1703 struct sk_buff *skb;
1704 tsap_Config_t *sap_config;
1705 uint32_t channel_count = 0, status;
1706 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1707 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1708 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1709 struct hdd_vendor_acs_chan_params acs_chan_params;
1710 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1711 eCsrBand band = eCSR_BAND_24;
1712 eCsrPhyMode phy_mode;
1713
1714 if (!hdd_ctx) {
1715 hdd_err("HDD context is NULL");
1716 return;
1717 }
1718
1719 ENTER();
1720 sap_config = &adapter->sessionCtx.ap.sapConfig;
1721
1722 /* Get valid channels for SAP */
1723 wlan_hdd_sap_get_valid_channellist(adapter,
1724 &channel_count, channel_list);
1725
1726 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1727 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1728 /* Get phymode */
1729 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1730
1731 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1732 &(adapter->wdev),
1733 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1734 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1735 GFP_KERNEL);
1736
1737 if (!skb) {
1738 hdd_err("cfg80211_vendor_event_alloc failed");
1739 return;
1740 }
1741 /*
1742 * Application expects pcl to be a subset of channel list
1743 * Remove all channels which are not in channel list from pcl
1744 * and add weight as zero
1745 */
1746 acs_chan_params.channel_count = channel_count;
1747 acs_chan_params.channel_list = channel_list;
1748 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1749 acs_chan_params.vendor_weight_list = vendor_weight_list;
1750
1751 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1752 sap_config);
1753 /* Update values in NL buffer */
1754 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1755 reason) ||
1756 nla_put_u8(skb,
1757 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1758 false) ||
1759 nla_put_u8(skb,
1760 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1761 true) ||
1762 nla_put_u8(skb,
1763 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1764 true) ||
1765 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1766 sap_config->acs_cfg.ch_width) ||
1767 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1768 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1769 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1770 band) ||
1771 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1772 phy_mode) ||
1773 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1774 channel_count, channel_list)) {
1775 hdd_err("nla put fail");
1776 goto fail;
1777 }
1778 status = hdd_cfg80211_update_pcl(skb, channel_count,
1779 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1780 vendor_pcl_list, vendor_weight_list);
1781
1782 if (status != 0)
1783 goto fail;
1784
1785 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1786 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1787
1788 if (status != 0)
1789 goto fail;
1790
1791 cfg80211_vendor_event(skb, GFP_KERNEL);
1792 return;
1793fail:
1794 if (skb)
1795 kfree_skb(skb);
1796}
1797
1798static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1799{
1800 struct hdd_external_acs_timer_context *timer_context;
1801
1802 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1803 return 0;
1804
1805 hdd_notice("Starting vendor app based ACS");
1806 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1807 timer_context->adapter = adapter;
1808
1809 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1810 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1811 QDF_TIMER_TYPE_SW,
1812 hdd_acs_response_timeout_handler, timer_context);
1813 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1814 return 0;
1815}
1816
1817/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001818 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1819 * @wiphy: Linux wiphy struct pointer
1820 * @wdev: Linux wireless device struct pointer
1821 * @data: ACS information from hostapd
1822 * @data_len: ACS information length
1823 *
1824 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1825 * and starts ACS procedure.
1826 *
1827 * Return: ACS procedure start status
1828 */
1829
1830static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1831 struct wireless_dev *wdev,
1832 const void *data, int data_len)
1833{
1834 struct net_device *ndev = wdev->netdev;
1835 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1836 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1837 tsap_Config_t *sap_config;
1838 struct sk_buff *temp_skbuff;
1839 int status = -EINVAL, i = 0;
1840 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1841 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301842 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843
1844 /* ***Note*** Donot set SME config related to ACS operation here because
1845 * ACS operation is not synchronouse and ACS for Second AP may come when
1846 * ACS operation for first AP is going on. So only do_acs is split to
1847 * seperate start_acs routine. Also SME-PMAC struct that is used to
1848 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1849 * config shall be set only from start_acs.
1850 */
1851
1852 /* nla_policy Policy template. Policy not applied as some attributes are
1853 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1854 *
1855 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1856 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1857 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1858 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1859 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1860 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1861 */
1862
Jeff Johnson1f61b612016-02-12 16:28:33 -08001863 ENTER_DEV(ndev);
1864
Anurag Chouhan6d760662016-02-20 16:05:43 +05301865 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001866 hdd_err("Command not allowed in FTM mode");
1867 return -EPERM;
1868 }
1869
Kapil Gupta8878ad92017-02-13 11:56:04 +05301870 if (hdd_ctx->config->force_sap_acs &&
1871 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001872 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001873 return -EPERM;
1874 }
1875
1876 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301877 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001878 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301879
Naveen Rawat64e477e2016-05-20 10:34:56 -07001880 if (cds_is_sub_20_mhz_enabled()) {
1881 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1882 status = -EINVAL;
1883 goto out;
1884 }
1885
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301887 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888
1889 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1890 NULL);
1891 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001892 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001893 goto out;
1894 }
1895
1896 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001897 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001898 goto out;
1899 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301900 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1901 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001902
1903 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1904 ht_enabled =
1905 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1906 else
1907 ht_enabled = 0;
1908
1909 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1910 ht40_enabled =
1911 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1912 else
1913 ht40_enabled = 0;
1914
1915 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1916 vht_enabled =
1917 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1918 else
1919 vht_enabled = 0;
1920
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301921 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1922 vht_enabled = 0;
1923 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1924 }
1925
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001926 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1927 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1928 } else {
1929 if (ht_enabled && ht40_enabled)
1930 ch_width = 40;
1931 else
1932 ch_width = 20;
1933 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301934
1935 /* this may be possible, when sap_force_11n_for_11ac is set */
1936 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1937 if (ht_enabled && ht40_enabled)
1938 ch_width = 40;
1939 else
1940 ch_width = 20;
1941 }
1942
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943 if (ch_width == 80)
1944 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1945 else if (ch_width == 40)
1946 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1947 else
1948 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1949
1950 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1951 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1952 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1953 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1954 * since it contains the frequency values of the channels in
1955 * the channel list.
1956 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1957 * is present
1958 */
1959 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1960 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1961 sap_config->acs_cfg.ch_list_count = nla_len(
1962 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1963 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301964 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 sizeof(uint8_t) *
1966 sap_config->acs_cfg.ch_list_count);
1967 if (sap_config->acs_cfg.ch_list == NULL)
1968 goto out;
1969
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301970 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971 sap_config->acs_cfg.ch_list_count);
1972 }
1973 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1974 uint32_t *freq =
1975 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1976 sap_config->acs_cfg.ch_list_count = nla_len(
1977 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1978 sizeof(uint32_t);
1979 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301980 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981 sap_config->acs_cfg.ch_list_count);
1982 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001983 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 status = -ENOMEM;
1985 goto out;
1986 }
1987
1988 /* convert frequency to channel */
1989 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1990 sap_config->acs_cfg.ch_list[i] =
1991 ieee80211_frequency_to_channel(freq[i]);
1992 }
1993 }
1994
1995 hdd_debug("get pcl for DO_ACS vendor command");
1996
1997 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001998 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301999 sap_config->acs_cfg.pcl_channels,
2000 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302001 sap_config->acs_cfg.pcl_channels_weight_list,
2002 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302003 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002004 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002006 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302007 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2008 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07002009 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010 vht_enabled = 1;
2011 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2012 sap_config->acs_cfg.ch_width =
2013 hdd_ctx->config->vhtChannelWidth;
2014 /* No VHT80 in 2.4G so perform ACS accordingly */
2015 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302016 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002017 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302018 ch_width = 40;
2019 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020 }
2021
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302022 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2023
Jeff Johnson020db452016-06-29 14:37:26 -07002024 hdd_notice("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 -08002025 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2026 ch_width, ht_enabled, vht_enabled,
2027 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2028
Kapil Gupta8878ad92017-02-13 11:56:04 +05302029 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2030 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2031
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002032 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07002033 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002034 sap_config->acs_cfg.ch_list_count);
2035 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07002036 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 }
2038 sap_config->acs_cfg.acs_mode = true;
2039 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002040 /* ***Note*** Completion variable usage is not allowed
2041 * here since ACS scan operation may take max 2.2 sec
2042 * for 5G band:
2043 * 9 Active channel X 40 ms active scan time +
2044 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2046 * for this long. So we split up the scanning part.
2047 */
2048 set_bit(ACS_PENDING, &adapter->event_flags);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302049 hdd_notice("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002050 status = 0;
2051 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302052 /* Check if vendor specific acs is enabled */
2053 if (hdd_ctx->config->vendor_acs_support) {
2054 sap_config->acs_cfg.hw_mode = hw_mode;
2055 hdd_create_acs_timer(adapter);
2056 hdd_update_acs_timer_reason(adapter,
2057 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2058 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2059 wlan_sap_set_vendor_acs(
2060 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2061 true);
2062 else
2063 wlan_sap_set_vendor_acs(
2064 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2065 false);
2066
2067 } else
2068 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002069 }
2070
2071out:
2072 if (0 == status) {
2073 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2074 NLMSG_HDRLEN);
2075 if (temp_skbuff != NULL)
2076 return cfg80211_vendor_cmd_reply(temp_skbuff);
2077 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002078 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2080
2081 return status;
2082}
2083
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002084/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002085 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2086 * @wiphy: Linux wiphy struct pointer
2087 * @wdev: Linux wireless device struct pointer
2088 * @data: ACS information from hostapd
2089 * @data_len: ACS information len
2090 *
2091 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2092 * and starts ACS procedure.
2093 *
2094 * Return: ACS procedure start status
2095 */
2096
2097static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2098 struct wireless_dev *wdev,
2099 const void *data, int data_len)
2100{
2101 int ret;
2102
2103 cds_ssr_protect(__func__);
2104 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2105 cds_ssr_unprotect(__func__);
2106
2107 return ret;
2108}
2109
2110/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002111 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2112 * @adapter: Pointer to adapter struct
2113 *
2114 * This function handle cleanup of what was done in DO_ACS, including free
2115 * memory.
2116 *
2117 * Return: void
2118 */
2119
2120void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2121{
2122 if (adapter == NULL)
2123 return;
2124 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2125 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2126 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2127 }
2128}
2129
2130/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002131 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2132 * @work: Linux workqueue struct pointer for ACS work
2133 *
2134 * This function starts the ACS procedure which was marked pending when an ACS
2135 * procedure was in progress for a concurrent SAP interface.
2136 *
2137 * Return: None
2138 */
2139
2140static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2141{
2142 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2143 acs_pending_work.work);
2144 wlan_hdd_cfg80211_start_acs(adapter);
2145}
2146
2147/**
2148 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2149 * @adapter: Pointer to SAP adapter struct
2150 * @pri_channel: SAP ACS procedure selected Primary channel
2151 * @sec_channel: SAP ACS procedure selected secondary channel
2152 *
2153 * This is a callback function from SAP module on ACS procedure is completed.
2154 * This function send the ACS selected channel information to hostapd
2155 *
2156 * Return: None
2157 */
2158
2159void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2160{
2161 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2162 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2163 struct sk_buff *vendor_event;
2164 int ret_val;
2165 hdd_adapter_t *con_sap_adapter;
2166 uint16_t ch_width;
2167
2168 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002169 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002170 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2171 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2172 GFP_KERNEL);
2173
2174 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002175 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176 return;
2177 }
2178
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002179 ret_val = nla_put_u8(vendor_event,
2180 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2181 sap_cfg->acs_cfg.pri_ch);
2182 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002183 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184 kfree_skb(vendor_event);
2185 return;
2186 }
2187
2188 ret_val = nla_put_u8(vendor_event,
2189 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2190 sap_cfg->acs_cfg.ht_sec_ch);
2191 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002192 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002193 kfree_skb(vendor_event);
2194 return;
2195 }
2196
2197 ret_val = nla_put_u8(vendor_event,
2198 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2199 sap_cfg->acs_cfg.vht_seg0_center_ch);
2200 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002201 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002202 kfree_skb(vendor_event);
2203 return;
2204 }
2205
2206 ret_val = nla_put_u8(vendor_event,
2207 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2208 sap_cfg->acs_cfg.vht_seg1_center_ch);
2209 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002210 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002211 kfree_skb(vendor_event);
2212 return;
2213 }
2214
2215 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2216 ch_width = 80;
2217 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2218 ch_width = 40;
2219 else
2220 ch_width = 20;
2221
2222 ret_val = nla_put_u16(vendor_event,
2223 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2224 ch_width);
2225 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002226 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002227 kfree_skb(vendor_event);
2228 return;
2229 }
2230 if (sap_cfg->acs_cfg.pri_ch > 14)
2231 ret_val = nla_put_u8(vendor_event,
2232 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2233 QCA_ACS_MODE_IEEE80211A);
2234 else
2235 ret_val = nla_put_u8(vendor_event,
2236 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2237 QCA_ACS_MODE_IEEE80211G);
2238
2239 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002240 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002241 kfree_skb(vendor_event);
2242 return;
2243 }
2244
Jeff Johnson46b40792016-06-29 14:03:14 -07002245 hdd_notice("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 -08002246 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2247 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2248 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2249
2250 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2251 /* ***Note*** As already mentioned Completion variable usage is not
2252 * allowed here since ACS scan operation may take max 2.2 sec.
2253 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2254 * operation.
2255 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2256 * when Primary AP ACS is complete and secondary AP ACS is started here
2257 * immediately, Primary AP start_bss may come inbetween ACS operation
2258 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2259 * delay. This path and below constraint will be removed on sessionizing
2260 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2261 * As per design constraint user space control application must take
2262 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2263 * this code path. Sec AP hostapd should be started after Primary AP
2264 * start beaconing which can be confirmed by getchannel iwpriv command
2265 */
2266
2267 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2268 if (con_sap_adapter &&
2269 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002270 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2271 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002272 /* Lets give 500ms for OBSS + START_BSS to complete */
2273 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2274 msecs_to_jiffies(500));
2275 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2276 }
2277
2278 return;
2279}
2280
2281static int
2282__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2283 struct wireless_dev *wdev,
2284 const void *data,
2285 int data_len)
2286{
2287 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2288 struct sk_buff *skb = NULL;
2289 uint32_t fset = 0;
2290 int ret;
2291
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002292 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302293
Anurag Chouhan6d760662016-02-20 16:05:43 +05302294 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002295 hdd_err("Command not allowed in FTM mode");
2296 return -EPERM;
2297 }
2298
2299 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302300 if (ret)
2301 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302
2303 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002304 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002305 fset |= WIFI_FEATURE_INFRA;
2306 }
2307 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002308 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002309 fset |= WIFI_FEATURE_INFRA_5G;
2310 }
2311#ifdef WLAN_FEATURE_P2P
2312 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2313 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002314 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002315 fset |= WIFI_FEATURE_P2P;
2316 }
2317#endif
2318 fset |= WIFI_FEATURE_SOFT_AP;
2319
2320 /* HOTSPOT is a supplicant feature, enable it by default */
2321 fset |= WIFI_FEATURE_HOTSPOT;
2322
2323#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302324 if (pHddCtx->config->extscan_enabled &&
2325 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002326 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002327 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2328 }
2329#endif
2330 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07002331 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002332 fset |= WIFI_FEATURE_NAN;
2333 }
2334 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002335 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002336 fset |= WIFI_FEATURE_D2D_RTT;
2337 fset |= WIFI_FEATURE_D2AP_RTT;
2338 }
2339#ifdef FEATURE_WLAN_SCAN_PNO
2340 if (pHddCtx->config->configPNOScanSupport &&
2341 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002342 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343 fset |= WIFI_FEATURE_PNO;
2344 }
2345#endif
2346 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2347#ifdef FEATURE_WLAN_TDLS
2348 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2349 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002350 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 fset |= WIFI_FEATURE_TDLS;
2352 }
2353 if (sme_is_feature_supported_by_fw(TDLS) &&
2354 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2355 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002356 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002357 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2358 }
2359#endif
2360#ifdef WLAN_AP_STA_CONCURRENCY
2361 fset |= WIFI_FEATURE_AP_STA;
2362#endif
2363 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002364 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002365
2366 if (hdd_link_layer_stats_supported())
2367 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2368
2369 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2370 NLMSG_HDRLEN);
2371 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002372 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002373 return -EINVAL;
2374 }
Jeff Johnson020db452016-06-29 14:37:26 -07002375 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002377 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 goto nla_put_failure;
2379 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302380 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302381 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382nla_put_failure:
2383 kfree_skb(skb);
2384 return -EINVAL;
2385}
2386
2387/**
2388 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2389 * @wiphy: pointer to wireless wiphy structure.
2390 * @wdev: pointer to wireless_dev structure.
2391 * @data: Pointer to the data to be passed via vendor interface
2392 * @data_len:Length of the data to be passed
2393 *
2394 * Return: Return the Success or Failure code.
2395 */
2396static int
2397wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2398 struct wireless_dev *wdev,
2399 const void *data, int data_len)
2400{
2401 int ret = 0;
2402
2403 cds_ssr_protect(__func__);
2404 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2405 data, data_len);
2406 cds_ssr_unprotect(__func__);
2407
2408 return ret;
2409}
2410
2411/**
2412 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2413 * @wiphy: pointer to wireless wiphy structure.
2414 * @wdev: pointer to wireless_dev structure.
2415 * @data: Pointer to the data to be passed via vendor interface
2416 * @data_len:Length of the data to be passed
2417 *
2418 * Set the MAC address that is to be used for scanning.
2419 *
2420 * Return: Return the Success or Failure code.
2421 */
2422static int
2423__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2424 struct wireless_dev *wdev,
2425 const void *data,
2426 int data_len)
2427{
2428 tpSirScanMacOui pReqMsg = NULL;
2429 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2430 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302431 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002432 int ret;
2433
Jeff Johnson1f61b612016-02-12 16:28:33 -08002434 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435
Anurag Chouhan6d760662016-02-20 16:05:43 +05302436 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 hdd_err("Command not allowed in FTM mode");
2438 return -EPERM;
2439 }
2440
2441 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302442 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002444
2445 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002446 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002447 return -ENOTSUPP;
2448 }
2449
2450 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2451 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002452 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453 return -EINVAL;
2454 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302455 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002456 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002457 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458 return -ENOMEM;
2459 }
2460 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002461 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002462 goto fail;
2463 }
2464 nla_memcpy(&pReqMsg->oui[0],
2465 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2466 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002467 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002468 pReqMsg->oui[1], pReqMsg->oui[2]);
2469 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302470 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002471 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 goto fail;
2473 }
2474 return 0;
2475fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302476 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002477 return -EINVAL;
2478}
2479
2480/**
2481 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2482 * @wiphy: pointer to wireless wiphy structure.
2483 * @wdev: pointer to wireless_dev structure.
2484 * @data: Pointer to the data to be passed via vendor interface
2485 * @data_len:Length of the data to be passed
2486 *
2487 * Set the MAC address that is to be used for scanning. This is an
2488 * SSR-protecting wrapper function.
2489 *
2490 * Return: Return the Success or Failure code.
2491 */
2492static int
2493wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2494 struct wireless_dev *wdev,
2495 const void *data,
2496 int data_len)
2497{
2498 int ret;
2499
2500 cds_ssr_protect(__func__);
2501 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2502 data, data_len);
2503 cds_ssr_unprotect(__func__);
2504
2505 return ret;
2506}
2507
2508/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302509 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2510 * @wiphy: pointer phy adapter
2511 * @wdev: pointer to wireless device structure
2512 * @data: pointer to data buffer
2513 * @data_len: length of data
2514 *
2515 * This routine will give concurrency matrix
2516 *
2517 * Return: int status code
2518 */
2519static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2520 struct wireless_dev *wdev,
2521 const void *data,
2522 int data_len)
2523{
2524 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2525 uint8_t i, feature_sets, max_feature_sets;
2526 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2527 struct sk_buff *reply_skb;
2528 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2529 int ret;
2530
2531 ENTER_DEV(wdev->netdev);
2532
2533 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2534 hdd_err("Command not allowed in FTM mode");
2535 return -EPERM;
2536 }
2537
2538 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302539 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302540 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302541
2542 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2543 data, data_len, NULL)) {
2544 hdd_err("Invalid ATTR");
2545 return -EINVAL;
2546 }
2547
2548 /* Parse and fetch max feature set */
2549 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2550 hdd_err("Attr max feature set size failed");
2551 return -EINVAL;
2552 }
2553 max_feature_sets = nla_get_u32(tb[
2554 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2555 hdd_info("Max feature set size: %d", max_feature_sets);
2556
2557 /* Fill feature combination matrix */
2558 feature_sets = 0;
2559 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002560 WIFI_FEATURE_P2P;
2561 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2562 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302563 /* Add more feature combinations here */
2564
2565 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002566 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302567 hdd_info("Feature set matrix");
2568 for (i = 0; i < feature_sets; i++)
2569 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2570
2571 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2572 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2573 if (!reply_skb) {
2574 hdd_err("Feature set matrix: buffer alloc fail");
2575 return -ENOMEM;
2576 }
2577
2578 if (nla_put_u32(reply_skb,
2579 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2580 feature_sets) ||
2581 nla_put(reply_skb,
2582 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2583 sizeof(u32) * feature_sets,
2584 feature_set_matrix)) {
2585 hdd_err("nla put fail");
2586 kfree_skb(reply_skb);
2587 return -EINVAL;
2588 }
2589 return cfg80211_vendor_cmd_reply(reply_skb);
2590}
2591
2592/**
2593 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2594 * @wiphy: pointer to wireless wiphy structure.
2595 * @wdev: pointer to wireless_dev structure.
2596 * @data: Pointer to the data to be passed via vendor interface
2597 * @data_len:Length of the data to be passed
2598 *
2599 * Retrieves the concurrency feature set matrix
2600 *
2601 * Return: 0 on success, negative errno on failure
2602 */
2603static int
2604wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2605 struct wireless_dev *wdev,
2606 const void *data,
2607 int data_len)
2608{
2609 int ret;
2610
2611 cds_ssr_protect(__func__);
2612 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2613 data, data_len);
2614 cds_ssr_unprotect(__func__);
2615
2616 return ret;
2617}
2618
2619/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2621 * @feature_flags: pointer to the byte array of features.
2622 * @feature: Feature to be turned ON in the byte array.
2623 *
2624 * Return: None
2625 *
2626 * This is called to turn ON or SET the feature flag for the requested feature.
2627 **/
2628#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002629static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2630 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002631{
2632 uint32_t index;
2633 uint8_t bit_mask;
2634
2635 index = feature / NUM_BITS_IN_BYTE;
2636 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2637 feature_flags[index] |= bit_mask;
2638}
2639
2640/**
2641 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2642 * @wiphy: pointer to wireless wiphy structure.
2643 * @wdev: pointer to wireless_dev structure.
2644 * @data: Pointer to the data to be passed via vendor interface
2645 * @data_len:Length of the data to be passed
2646 *
2647 * This is called when wlan driver needs to send supported feature set to
2648 * supplicant upon a request/query from the supplicant.
2649 *
2650 * Return: Return the Success or Failure code.
2651 **/
2652#define MAX_CONCURRENT_CHAN_ON_24G 2
2653#define MAX_CONCURRENT_CHAN_ON_5G 2
2654static int
2655__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2656 struct wireless_dev *wdev,
2657 const void *data, int data_len)
2658{
2659 struct sk_buff *skb = NULL;
2660 uint32_t dbs_capability = 0;
2661 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302662 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002663 int ret_val;
2664
2665 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2666 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2667
Jeff Johnson1f61b612016-02-12 16:28:33 -08002668 ENTER_DEV(wdev->netdev);
2669
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002670 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2671 if (ret_val)
2672 return ret_val;
2673
Anurag Chouhan6d760662016-02-20 16:05:43 +05302674 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675 hdd_err("Command not allowed in FTM mode");
2676 return -EPERM;
2677 }
2678
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002679 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002680 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681 wlan_hdd_cfg80211_set_feature(feature_flags,
2682 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2683 }
2684
2685 wlan_hdd_cfg80211_set_feature(feature_flags,
2686 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2687 if (wma_is_scan_simultaneous_capable())
2688 wlan_hdd_cfg80211_set_feature(feature_flags,
2689 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002690
2691 if (wma_is_p2p_lo_capable())
2692 wlan_hdd_cfg80211_set_feature(feature_flags,
2693 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2694
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002695 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2696 NLMSG_HDRLEN);
2697
2698 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002699 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002700 return -ENOMEM;
2701 }
2702
2703 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2704 sizeof(feature_flags), feature_flags))
2705 goto nla_put_failure;
2706
2707 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302708 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002709 if (one_by_one_dbs)
2710 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2711
2712 if (two_by_two_dbs)
2713 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2714
2715 if (!one_by_one_dbs && !two_by_two_dbs)
2716 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2717 } else {
2718 hdd_err("wma_get_dbs_hw_mode failed");
2719 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2720 }
2721
2722 hdd_info("dbs_capability is %d", dbs_capability);
2723
2724 if (nla_put_u32(skb,
2725 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2726 MAX_CONCURRENT_CHAN_ON_24G))
2727 goto nla_put_failure;
2728
2729 if (nla_put_u32(skb,
2730 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2731 MAX_CONCURRENT_CHAN_ON_5G))
2732 goto nla_put_failure;
2733
2734 return cfg80211_vendor_cmd_reply(skb);
2735
2736nla_put_failure:
2737 kfree_skb(skb);
2738 return -EINVAL;
2739}
2740
2741/**
2742 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2743 * @wiphy: pointer to wireless wiphy structure.
2744 * @wdev: pointer to wireless_dev structure.
2745 * @data: Pointer to the data to be passed via vendor interface
2746 * @data_len:Length of the data to be passed
2747 *
2748 * This is called when wlan driver needs to send supported feature set to
2749 * supplicant upon a request/query from the supplicant.
2750 *
2751 * Return: Return the Success or Failure code.
2752 */
2753static int
2754wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2755 struct wireless_dev *wdev,
2756 const void *data, int data_len)
2757{
2758 int ret;
2759
2760 cds_ssr_protect(__func__);
2761 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2762 data, data_len);
2763 cds_ssr_unprotect(__func__);
2764
2765 return ret;
2766}
2767
2768
2769/**
2770 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2771 * @wiphy: The wiphy structure
2772 * @wdev: The wireless device
2773 * @data: Data passed by framework
2774 * @data_len: Parameters to be configured passed as data
2775 *
2776 * The roaming related parameters are configured by the framework
2777 * using this interface.
2778 *
2779 * Return: Return either success or failure code.
2780 */
2781static int
2782__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2783 struct wireless_dev *wdev, const void *data, int data_len)
2784{
2785 struct net_device *dev = wdev->netdev;
2786 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2787 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2788 uint8_t session_id;
2789 struct roam_ext_params roam_params;
2790 uint32_t cmd_type, req_id;
2791 struct nlattr *curr_attr;
2792 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2793 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2794 int rem, i;
2795 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002796 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002797 int ret;
2798
Jeff Johnson1f61b612016-02-12 16:28:33 -08002799 ENTER_DEV(dev);
2800
Anurag Chouhan6d760662016-02-20 16:05:43 +05302801 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002802 hdd_err("Command not allowed in FTM mode");
2803 return -EPERM;
2804 }
2805
2806 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302807 if (ret)
2808 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002809
2810 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2811 data, data_len,
2812 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002813 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002814 return -EINVAL;
2815 }
2816 /* Parse and fetch Command Type*/
2817 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002818 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002819 goto fail;
2820 }
2821 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302822 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2824 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002825 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002826 goto fail;
2827 }
2828 req_id = nla_get_u32(
2829 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002830 hdd_debug("Req Id (%d)", req_id);
2831 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002832 switch (cmd_type) {
2833 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2834 i = 0;
2835 nla_for_each_nested(curr_attr,
2836 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2837 rem) {
2838 if (nla_parse(tb2,
2839 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2840 nla_data(curr_attr), nla_len(curr_attr),
2841 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002842 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002843 goto fail;
2844 }
2845 /* Parse and Fetch allowed SSID list*/
2846 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002847 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002848 goto fail;
2849 }
2850 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2851 /*
2852 * Upper Layers include a null termination character.
2853 * Check for the actual permissible length of SSID and
2854 * also ensure not to copy the NULL termination
2855 * character to the driver buffer.
2856 */
2857 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2858 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2859 nla_memcpy(
2860 roam_params.ssid_allowed_list[i].ssId,
2861 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2862 buf_len - 1);
2863 roam_params.ssid_allowed_list[i].length =
2864 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002865 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002866 roam_params.ssid_allowed_list[i].length,
2867 roam_params.ssid_allowed_list[i].ssId,
2868 roam_params.ssid_allowed_list[i].length);
2869 i++;
2870 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002871 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002872 }
2873 }
2874 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002875 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002876 roam_params.num_ssid_allowed_list);
2877 sme_update_roam_params(pHddCtx->hHal, session_id,
2878 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2879 break;
2880 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2881 /* Parse and fetch 5G Boost Threshold */
2882 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002883 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002884 goto fail;
2885 }
2886 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2887 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002888 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002889 roam_params.raise_rssi_thresh_5g);
2890 /* Parse and fetch 5G Penalty Threshold */
2891 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002892 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893 goto fail;
2894 }
2895 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2896 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002897 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002898 roam_params.drop_rssi_thresh_5g);
2899 /* Parse and fetch 5G Boost Factor */
2900 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002901 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002902 goto fail;
2903 }
2904 roam_params.raise_factor_5g = nla_get_u32(
2905 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002906 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 roam_params.raise_factor_5g);
2908 /* Parse and fetch 5G Penalty factor */
2909 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002910 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002911 goto fail;
2912 }
2913 roam_params.drop_factor_5g = nla_get_u32(
2914 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002915 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002916 roam_params.drop_factor_5g);
2917 /* Parse and fetch 5G Max Boost */
2918 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002919 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002920 goto fail;
2921 }
2922 roam_params.max_raise_rssi_5g = nla_get_u32(
2923 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002924 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002925 roam_params.max_raise_rssi_5g);
2926 /* Parse and fetch Rssi Diff */
2927 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002928 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002929 goto fail;
2930 }
2931 roam_params.rssi_diff = nla_get_s32(
2932 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002933 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002934 roam_params.rssi_diff);
2935 /* Parse and fetch Alert Rssi Threshold */
2936 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002937 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002938 goto fail;
2939 }
2940 roam_params.alert_rssi_threshold = nla_get_u32(
2941 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002942 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002943 roam_params.alert_rssi_threshold);
2944 sme_update_roam_params(pHddCtx->hHal, session_id,
2945 roam_params,
2946 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2947 break;
2948 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2949 /* Parse and fetch Activate Good Rssi Roam */
2950 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002951 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952 goto fail;
2953 }
2954 roam_params.good_rssi_roam = nla_get_s32(
2955 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002956 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 roam_params.good_rssi_roam);
2958 sme_update_roam_params(pHddCtx->hHal, session_id,
2959 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2960 break;
2961 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2962 /* Parse and fetch number of preferred BSSID */
2963 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002964 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002965 goto fail;
2966 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002967 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002968 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002969 if (count > MAX_BSSID_FAVORED) {
2970 hdd_err("Preferred BSSID count %u exceeds max %u",
2971 count, MAX_BSSID_FAVORED);
2972 goto fail;
2973 }
2974 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002975 i = 0;
2976 nla_for_each_nested(curr_attr,
2977 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2978 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002979
2980 if (i == count) {
2981 hdd_warn("Ignoring excess Preferred BSSID");
2982 break;
2983 }
2984
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985 if (nla_parse(tb2,
2986 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2987 nla_data(curr_attr), nla_len(curr_attr),
2988 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002989 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002990 goto fail;
2991 }
2992 /* Parse and fetch MAC address */
2993 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002994 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995 goto fail;
2996 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002997 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002998 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302999 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003000 hdd_debug(MAC_ADDRESS_STR,
3001 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 /* Parse and fetch preference factor*/
3003 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003004 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003005 goto fail;
3006 }
3007 roam_params.bssid_favored_factor[i] = nla_get_u32(
3008 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003009 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003010 roam_params.bssid_favored_factor[i]);
3011 i++;
3012 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003013 if (i < count)
3014 hdd_warn("Num Preferred BSSID %u less than expected %u",
3015 i, count);
3016 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017 sme_update_roam_params(pHddCtx->hHal, session_id,
3018 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3019 break;
3020 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3021 /* Parse and fetch number of blacklist BSSID */
3022 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003023 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003024 goto fail;
3025 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003026 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003028 if (count > MAX_BSSID_AVOID_LIST) {
3029 hdd_err("Blacklist BSSID count %u exceeds max %u",
3030 count, MAX_BSSID_AVOID_LIST);
3031 goto fail;
3032 }
3033 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 i = 0;
3035 nla_for_each_nested(curr_attr,
3036 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3037 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003038
3039 if (i == count) {
3040 hdd_warn("Ignoring excess Blacklist BSSID");
3041 break;
3042 }
3043
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003044 if (nla_parse(tb2,
3045 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3046 nla_data(curr_attr), nla_len(curr_attr),
3047 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003048 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003049 goto fail;
3050 }
3051 /* Parse and fetch MAC address */
3052 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003053 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003054 goto fail;
3055 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003056 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003057 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303058 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003059 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003060 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003061 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003062 i++;
3063 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003064 if (i < count)
3065 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3066 i, count);
3067 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003068 sme_update_roam_params(pHddCtx->hHal, session_id,
3069 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3070 break;
3071 }
3072 return 0;
3073fail:
3074 return -EINVAL;
3075}
3076
3077/**
3078 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3079 * @wiphy: pointer to wireless wiphy structure.
3080 * @wdev: pointer to wireless_dev structure.
3081 * @data: Pointer to the data to be passed via vendor interface
3082 * @data_len:Length of the data to be passed
3083 *
3084 * Return: Return the Success or Failure code.
3085 */
3086static int
3087wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3088 struct wireless_dev *wdev,
3089 const void *data,
3090 int data_len)
3091{
3092 int ret;
3093
3094 cds_ssr_protect(__func__);
3095 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3096 data, data_len);
3097 cds_ssr_unprotect(__func__);
3098
3099 return ret;
3100}
3101
3102static const struct nla_policy
3103wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3104 +1] = {
3105 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3106};
3107
3108/**
3109 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3110 * @hdd_ctx: HDD context
3111 * @device_mode: device mode
3112 * Return: bool
3113 */
3114static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003115 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003116{
3117 hdd_adapter_t *adapter;
3118 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3119 hdd_ap_ctx_t *ap_ctx;
3120 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303121 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003122
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303123 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003124 &adapter_node);
3125
3126 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303127 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003128 adapter = adapter_node->pAdapter;
3129
3130 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003131 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003132 ap_ctx =
3133 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3134
3135 /*
3136 * if there is SAP already running on DFS channel,
3137 * do not disable scan on dfs channels. Note that
3138 * with SAP on DFS, there cannot be conurrency on
3139 * single radio. But then we can have multiple
3140 * radios !!
3141 */
3142 if (CHANNEL_STATE_DFS ==
3143 cds_get_channel_state(
3144 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003145 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146 return true;
3147 }
3148 }
3149
3150 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003151 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003152 sta_ctx =
3153 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3154
3155 /*
3156 * if STA is already connected on DFS channel,
3157 * do not disable scan on dfs channels
3158 */
3159 if (hdd_conn_is_connected(sta_ctx) &&
3160 (CHANNEL_STATE_DFS ==
3161 cds_get_channel_state(
3162 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003163 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164 return true;
3165 }
3166 }
3167
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303168 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003169 adapter_node,
3170 &next);
3171 adapter_node = next;
3172 }
3173
3174 return false;
3175}
3176
3177/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003178 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3179 * @hdd_ctx: HDD context within host driver
3180 * @adapter: Adapter pointer
3181 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3182 *
3183 * Loops through devices to see who is operating on DFS channels
3184 * and then disables/enables DFS channels by calling SME API.
3185 * Fails the disable request if any device is active on a DFS channel.
3186 *
3187 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003188 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003189
3190int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3191 hdd_adapter_t *adapter,
3192 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003193{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303195 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003196 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197
3198 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3199 if (no_dfs_flag) {
3200 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003201 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202
3203 if (true == status)
3204 return -EOPNOTSUPP;
3205
3206 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003207 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003208
3209 if (true == status)
3210 return -EOPNOTSUPP;
3211 }
3212
3213 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3214
3215 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3216
3217 /*
3218 * call the SME API to tunnel down the new channel list
3219 * to the firmware
3220 */
3221 status = sme_handle_dfs_chan_scan(
3222 h_hal, hdd_ctx->config->enableDFSChnlScan);
3223
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303224 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 ret_val = 0;
3226
3227 /*
3228 * Clear the SME scan cache also. Note that the
3229 * clearing of scan results is independent of session;
3230 * so no need to iterate over
3231 * all sessions
3232 */
3233 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303234 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 ret_val = -EPERM;
3236 }
3237
3238 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003239 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003240 ret_val = 0;
3241 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003242 return ret_val;
3243}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003244
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003245/**
3246 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3247 * @wiphy: corestack handler
3248 * @wdev: wireless device
3249 * @data: data
3250 * @data_len: data length
3251 * Return: success(0) or reason code for failure
3252 */
3253static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3254 struct wireless_dev *wdev,
3255 const void *data,
3256 int data_len)
3257{
3258 struct net_device *dev = wdev->netdev;
3259 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3260 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3261 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3262 int ret_val;
3263 uint32_t no_dfs_flag = 0;
3264
Jeff Johnson1f61b612016-02-12 16:28:33 -08003265 ENTER_DEV(dev);
3266
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003267 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303268 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003269 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003270
3271 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3272 data, data_len,
3273 wlan_hdd_set_no_dfs_flag_config_policy)) {
3274 hdd_err("invalid attr");
3275 return -EINVAL;
3276 }
3277
3278 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3279 hdd_err("attr dfs flag failed");
3280 return -EINVAL;
3281 }
3282
3283 no_dfs_flag = nla_get_u32(
3284 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3285
Jeff Johnson020db452016-06-29 14:37:26 -07003286 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003287
3288 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003289 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003290 return -EINVAL;
3291 }
3292
3293 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3294 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 return ret_val;
3296}
3297
3298/**
3299 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3300 *
3301 * @wiphy: wiphy device pointer
3302 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003303 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003304 * @data_len: Buffer length
3305 *
3306 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3307 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3308 *
3309 * Return: EOK or other error codes.
3310 */
3311
3312static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3313 struct wireless_dev *wdev,
3314 const void *data,
3315 int data_len)
3316{
3317 int ret;
3318
3319 cds_ssr_protect(__func__);
3320 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3321 data, data_len);
3322 cds_ssr_unprotect(__func__);
3323
3324 return ret;
3325}
3326
Manikandan Mohan80dea792016-04-28 16:36:48 -07003327static const struct nla_policy
3328wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3329 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3330};
3331
3332/**
3333 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3334 * @wiphy: wiphy device pointer
3335 * @wdev: wireless device pointer
3336 * @data: Vendor command data buffer
3337 * @data_len: Buffer length
3338 *
3339 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3340 * setup WISA Mode features.
3341 *
3342 * Return: Success(0) or reason code for failure
3343 */
3344static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3345 struct wireless_dev *wdev, const void *data, int data_len)
3346{
3347 struct net_device *dev = wdev->netdev;
3348 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3349 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3350 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3351 struct sir_wisa_params wisa;
3352 int ret_val;
3353 QDF_STATUS status;
3354 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003355 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3356 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003357
3358 ENTER_DEV(dev);
3359 ret_val = wlan_hdd_validate_context(hdd_ctx);
3360 if (ret_val)
3361 goto err;
3362
3363 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3364 hdd_err("Command not allowed in FTM mode");
3365 return -EPERM;
3366 }
3367
3368 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3369 wlan_hdd_wisa_cmd_policy)) {
3370 hdd_err("Invalid WISA cmd attributes");
3371 ret_val = -EINVAL;
3372 goto err;
3373 }
3374 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3375 hdd_err("Invalid WISA mode");
3376 ret_val = -EINVAL;
3377 goto err;
3378 }
3379
3380 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
3381 hdd_info("WISA Mode: %d", wisa_mode);
3382 wisa.mode = wisa_mode;
3383 wisa.vdev_id = adapter->sessionId;
3384 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003385 if (!QDF_IS_STATUS_SUCCESS(status)) {
3386 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003387 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003388 }
3389 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003390 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003391 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3392 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003393 adapter->sessionId),
3394 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003395err:
3396 EXIT();
3397 return ret_val;
3398}
3399
3400/**
3401 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3402 * @wiphy: corestack handler
3403 * @wdev: wireless device
3404 * @data: data
3405 * @data_len: data length
3406 *
3407 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3408 * setup WISA mode features.
3409 *
3410 * Return: Success(0) or reason code for failure
3411 */
3412static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3413 struct wireless_dev *wdev,
3414 const void *data,
3415 int data_len)
3416{
3417 int ret;
3418
3419 cds_ssr_protect(__func__);
3420 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3421 cds_ssr_unprotect(__func__);
3422
3423 return ret;
3424}
3425
Anurag Chouhan96919482016-07-13 16:36:57 +05303426/*
3427 * define short names for the global vendor params
3428 * used by __wlan_hdd_cfg80211_get_station_cmd()
3429 */
3430#define STATION_INVALID \
3431 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3432#define STATION_INFO \
3433 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3434#define STATION_ASSOC_FAIL_REASON \
3435 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3436#define STATION_MAX \
3437 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3438
3439static const struct nla_policy
3440hdd_get_station_policy[STATION_MAX + 1] = {
3441 [STATION_INFO] = {.type = NLA_FLAG},
3442 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3443};
3444
3445/**
3446 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3447 * @hdd_ctx: HDD context within host driver
3448 * @wdev: wireless device
3449 *
3450 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3451 * Validate cmd attributes and send the station info to upper layers.
3452 *
3453 * Return: Success(0) or reason code for failure
3454 */
3455static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3456 hdd_adapter_t *adapter)
3457{
3458 struct sk_buff *skb = NULL;
3459 uint32_t nl_buf_len;
3460 hdd_station_ctx_t *hdd_sta_ctx;
3461
3462 nl_buf_len = NLMSG_HDRLEN;
3463 nl_buf_len += sizeof(uint32_t);
3464 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3465
3466 if (!skb) {
3467 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3468 return -ENOMEM;
3469 }
3470
3471 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3472
3473 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3474 hdd_sta_ctx->conn_info.assoc_status_code)) {
3475 hdd_err("put fail");
3476 goto fail;
3477 }
3478 return cfg80211_vendor_cmd_reply(skb);
3479fail:
3480 if (skb)
3481 kfree_skb(skb);
3482 return -EINVAL;
3483}
3484
3485/**
3486 * hdd_map_auth_type() - transform auth type specific to
3487 * vendor command
3488 * @auth_type: csr auth type
3489 *
3490 * Return: Success(0) or reason code for failure
3491 */
3492static int hdd_convert_auth_type(uint32_t auth_type)
3493{
3494 uint32_t ret_val;
3495
3496 switch (auth_type) {
3497 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3498 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3499 break;
3500 case eCSR_AUTH_TYPE_SHARED_KEY:
3501 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3502 break;
3503 case eCSR_AUTH_TYPE_WPA:
3504 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3505 break;
3506 case eCSR_AUTH_TYPE_WPA_PSK:
3507 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3508 break;
3509 case eCSR_AUTH_TYPE_AUTOSWITCH:
3510 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3511 break;
3512 case eCSR_AUTH_TYPE_WPA_NONE:
3513 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3514 break;
3515 case eCSR_AUTH_TYPE_RSN:
3516 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3517 break;
3518 case eCSR_AUTH_TYPE_RSN_PSK:
3519 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3520 break;
3521 case eCSR_AUTH_TYPE_FT_RSN:
3522 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3523 break;
3524 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3525 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3526 break;
3527 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3528 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3529 break;
3530 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3531 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3532 break;
3533 case eCSR_AUTH_TYPE_CCKM_WPA:
3534 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3535 break;
3536 case eCSR_AUTH_TYPE_CCKM_RSN:
3537 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3538 break;
3539 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3540 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3541 break;
3542 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3543 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3544 break;
3545 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3546 case eCSR_AUTH_TYPE_FAILED:
3547 case eCSR_AUTH_TYPE_NONE:
3548 default:
3549 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3550 break;
3551 }
3552 return ret_val;
3553}
3554
3555/**
3556 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3557 * vendor command
3558 * @dot11mode: dot11mode
3559 *
3560 * Return: Success(0) or reason code for failure
3561 */
3562static int hdd_convert_dot11mode(uint32_t dot11mode)
3563{
3564 uint32_t ret_val;
3565
3566 switch (dot11mode) {
3567 case eCSR_CFG_DOT11_MODE_11A:
3568 ret_val = QCA_WLAN_802_11_MODE_11A;
3569 break;
3570 case eCSR_CFG_DOT11_MODE_11B:
3571 ret_val = QCA_WLAN_802_11_MODE_11B;
3572 break;
3573 case eCSR_CFG_DOT11_MODE_11G:
3574 ret_val = QCA_WLAN_802_11_MODE_11G;
3575 break;
3576 case eCSR_CFG_DOT11_MODE_11N:
3577 ret_val = QCA_WLAN_802_11_MODE_11N;
3578 break;
3579 case eCSR_CFG_DOT11_MODE_11AC:
3580 ret_val = QCA_WLAN_802_11_MODE_11AC;
3581 break;
3582 case eCSR_CFG_DOT11_MODE_AUTO:
3583 case eCSR_CFG_DOT11_MODE_ABG:
3584 default:
3585 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3586 }
3587 return ret_val;
3588}
3589
3590/**
3591 * hdd_add_tx_bitrate() - add tx bitrate attribute
3592 * @skb: pointer to sk buff
3593 * @hdd_sta_ctx: pointer to hdd station context
3594 * @idx: attribute index
3595 *
3596 * Return: Success(0) or reason code for failure
3597 */
3598static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3599 hdd_station_ctx_t *hdd_sta_ctx,
3600 int idx)
3601{
3602 struct nlattr *nla_attr;
3603 uint32_t bitrate, bitrate_compat;
3604
3605 nla_attr = nla_nest_start(skb, idx);
3606 if (!nla_attr)
3607 goto fail;
3608 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3609 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3610
3611 /* report 16-bit bitrate only if we can */
3612 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3613 if (bitrate > 0 &&
3614 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3615 hdd_err("put fail");
3616 goto fail;
3617 }
3618 if (bitrate_compat > 0 &&
3619 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3620 hdd_err("put fail");
3621 goto fail;
3622 }
3623 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3624 hdd_sta_ctx->conn_info.txrate.nss)) {
3625 hdd_err("put fail");
3626 goto fail;
3627 }
3628 nla_nest_end(skb, nla_attr);
3629 return 0;
3630fail:
3631 return -EINVAL;
3632}
3633
3634/**
3635 * hdd_add_sta_info() - add station info attribute
3636 * @skb: pointer to sk buff
3637 * @hdd_sta_ctx: pointer to hdd station context
3638 * @idx: attribute index
3639 *
3640 * Return: Success(0) or reason code for failure
3641 */
3642static int32_t hdd_add_sta_info(struct sk_buff *skb,
3643 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3644{
3645 struct nlattr *nla_attr;
3646
3647 nla_attr = nla_nest_start(skb, idx);
3648 if (!nla_attr)
3649 goto fail;
3650 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3651 (hdd_sta_ctx->conn_info.signal + 100))) {
3652 hdd_err("put fail");
3653 goto fail;
3654 }
3655 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3656 goto fail;
3657 nla_nest_end(skb, nla_attr);
3658 return 0;
3659fail:
3660 return -EINVAL;
3661}
3662
3663/**
3664 * hdd_add_survey_info() - add survey info attribute
3665 * @skb: pointer to sk buff
3666 * @hdd_sta_ctx: pointer to hdd station context
3667 * @idx: attribute index
3668 *
3669 * Return: Success(0) or reason code for failure
3670 */
3671static int32_t hdd_add_survey_info(struct sk_buff *skb,
3672 hdd_station_ctx_t *hdd_sta_ctx,
3673 int idx)
3674{
3675 struct nlattr *nla_attr;
3676
3677 nla_attr = nla_nest_start(skb, idx);
3678 if (!nla_attr)
3679 goto fail;
3680 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3681 hdd_sta_ctx->conn_info.freq) ||
3682 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3683 (hdd_sta_ctx->conn_info.noise + 100))) {
3684 hdd_err("put fail");
3685 goto fail;
3686 }
3687 nla_nest_end(skb, nla_attr);
3688 return 0;
3689fail:
3690 return -EINVAL;
3691}
3692
3693/**
3694 * hdd_add_link_standard_info() - add link info attribute
3695 * @skb: pointer to sk buff
3696 * @hdd_sta_ctx: pointer to hdd station context
3697 * @idx: attribute index
3698 *
3699 * Return: Success(0) or reason code for failure
3700 */
3701static int32_t
3702hdd_add_link_standard_info(struct sk_buff *skb,
3703 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3704{
3705 struct nlattr *nla_attr;
3706
3707 nla_attr = nla_nest_start(skb, idx);
3708 if (!nla_attr)
3709 goto fail;
3710 if (nla_put(skb,
3711 NL80211_ATTR_SSID,
3712 hdd_sta_ctx->conn_info.SSID.SSID.length,
3713 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3714 hdd_err("put fail");
3715 goto fail;
3716 }
3717 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3718 goto fail;
3719 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3720 goto fail;
3721 nla_nest_end(skb, nla_attr);
3722 return 0;
3723fail:
3724 return -EINVAL;
3725}
3726
3727/**
3728 * hdd_add_ap_standard_info() - add ap info attribute
3729 * @skb: pointer to sk buff
3730 * @hdd_sta_ctx: pointer to hdd station context
3731 * @idx: attribute index
3732 *
3733 * Return: Success(0) or reason code for failure
3734 */
3735static int32_t
3736hdd_add_ap_standard_info(struct sk_buff *skb,
3737 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3738{
3739 struct nlattr *nla_attr;
3740
3741 nla_attr = nla_nest_start(skb, idx);
3742 if (!nla_attr)
3743 goto fail;
3744 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3745 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3746 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3747 &hdd_sta_ctx->conn_info.vht_caps)) {
3748 hdd_err("put fail");
3749 goto fail;
3750 }
3751 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3752 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3753 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3754 &hdd_sta_ctx->conn_info.ht_caps)) {
3755 hdd_err("put fail");
3756 goto fail;
3757 }
3758 nla_nest_end(skb, nla_attr);
3759 return 0;
3760fail:
3761 return -EINVAL;
3762}
3763
3764/**
3765 * hdd_get_station_info() - send BSS information to supplicant
3766 * @hdd_ctx: pointer to hdd context
3767 * @adapter: pointer to adapter
3768 *
3769 * Return: 0 if success else error status
3770 */
3771static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3772 hdd_adapter_t *adapter)
3773{
3774 struct sk_buff *skb = NULL;
3775 uint8_t *tmp_hs20 = NULL;
3776 uint32_t nl_buf_len;
3777 hdd_station_ctx_t *hdd_sta_ctx;
3778
3779 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3780
3781 nl_buf_len = NLMSG_HDRLEN;
3782 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3783 sizeof(hdd_sta_ctx->conn_info.freq) +
3784 sizeof(hdd_sta_ctx->conn_info.noise) +
3785 sizeof(hdd_sta_ctx->conn_info.signal) +
3786 (sizeof(uint32_t) * 2) +
3787 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3788 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3789 sizeof(hdd_sta_ctx->conn_info.authType) +
3790 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3791 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3792 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3793 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3794 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3795 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3796 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3797 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3798 1);
3799 }
3800 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3801 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3802 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3803 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3804
3805
3806 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3807 if (!skb) {
3808 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3809 return -ENOMEM;
3810 }
3811
3812 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3813 LINK_INFO_STANDARD_NL80211_ATTR)) {
3814 hdd_err("put fail");
3815 goto fail;
3816 }
3817 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3818 AP_INFO_STANDARD_NL80211_ATTR)) {
3819 hdd_err("put fail");
3820 goto fail;
3821 }
3822 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3823 hdd_sta_ctx->conn_info.roam_count) ||
3824 nla_put_u32(skb, INFO_AKM,
3825 hdd_convert_auth_type(
3826 hdd_sta_ctx->conn_info.authType)) ||
3827 nla_put_u32(skb, WLAN802_11_MODE,
3828 hdd_convert_dot11mode(
3829 hdd_sta_ctx->conn_info.dot11Mode))) {
3830 hdd_err("put fail");
3831 goto fail;
3832 }
3833 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3834 if (nla_put(skb, HT_OPERATION,
3835 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3836 &hdd_sta_ctx->conn_info.ht_operation)) {
3837 hdd_err("put fail");
3838 goto fail;
3839 }
3840 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3841 if (nla_put(skb, VHT_OPERATION,
3842 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3843 &hdd_sta_ctx->conn_info.vht_operation)) {
3844 hdd_err("put fail");
3845 goto fail;
3846 }
3847 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3848 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3849 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3850 tmp_hs20 + 1)) {
3851 hdd_err("put fail");
3852 goto fail;
3853 }
3854
3855 return cfg80211_vendor_cmd_reply(skb);
3856fail:
3857 if (skb)
3858 kfree_skb(skb);
3859 return -EINVAL;
3860}
3861
3862/**
3863 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3864 * @wiphy: corestack handler
3865 * @wdev: wireless device
3866 * @data: data
3867 * @data_len: data length
3868 *
3869 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3870 * Validate cmd attributes and send the station info to upper layers.
3871 *
3872 * Return: Success(0) or reason code for failure
3873 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303874static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303875__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3876 struct wireless_dev *wdev,
3877 const void *data,
3878 int data_len)
3879{
3880 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3881 struct net_device *dev = wdev->netdev;
3882 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3883 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3884 int32_t status;
3885
3886 ENTER_DEV(dev);
3887 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3888 hdd_err("Command not allowed in FTM mode");
3889 status = -EPERM;
3890 goto out;
3891 }
3892
3893 status = wlan_hdd_validate_context(hdd_ctx);
3894 if (0 != status)
3895 goto out;
3896
3897
3898 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3899 data, data_len, NULL);
3900 if (status) {
3901 hdd_err("Invalid ATTR");
3902 goto out;
3903 }
3904
3905 /* Parse and fetch Command Type*/
3906 if (tb[STATION_INFO]) {
3907 status = hdd_get_station_info(hdd_ctx, adapter);
3908 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3909 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3910 } else {
3911 hdd_err("get station info cmd type failed");
3912 status = -EINVAL;
3913 goto out;
3914 }
3915 EXIT();
3916out:
3917 return status;
3918}
3919
3920/**
3921 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3922 * @wiphy: corestack handler
3923 * @wdev: wireless device
3924 * @data: data
3925 * @data_len: data length
3926 *
3927 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3928 * Validate cmd attributes and send the station info to upper layers.
3929 *
3930 * Return: Success(0) or reason code for failure
3931 */
3932static int32_t
3933hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3934 struct wireless_dev *wdev,
3935 const void *data,
3936 int data_len)
3937{
3938 int ret;
3939
3940 cds_ssr_protect(__func__);
3941 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3942 cds_ssr_unprotect(__func__);
3943
3944 return ret;
3945}
3946
3947/*
3948 * undef short names defined for get station command
3949 * used by __wlan_hdd_cfg80211_get_station_cmd()
3950 */
3951#undef STATION_INVALID
3952#undef STATION_INFO
3953#undef STATION_ASSOC_FAIL_REASON
3954#undef STATION_MAX
3955
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003956#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3957/**
3958 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3959 * @wiphy: pointer to wireless wiphy structure.
3960 * @wdev: pointer to wireless_dev structure.
3961 * @data: Pointer to the Key data
3962 * @data_len:Length of the data passed
3963 *
3964 * This is called when wlan driver needs to save the keys received via
3965 * vendor specific command.
3966 *
3967 * Return: Return the Success or Failure code.
3968 */
3969static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3970 struct wireless_dev *wdev,
3971 const void *data, int data_len)
3972{
3973 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3974 struct net_device *dev = wdev->netdev;
3975 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3976 hdd_context_t *hdd_ctx_ptr;
3977 int status;
3978
Jeff Johnson1f61b612016-02-12 16:28:33 -08003979 ENTER_DEV(dev);
3980
Anurag Chouhan6d760662016-02-20 16:05:43 +05303981 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003982 hdd_err("Command not allowed in FTM mode");
3983 return -EPERM;
3984 }
3985
3986 if ((data == NULL) || (data_len == 0) ||
3987 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003988 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003989 return -EINVAL;
3990 }
3991
3992 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3993 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003994 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003995 return -EINVAL;
3996 }
3997
3998 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303999 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004000 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004001 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4002 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004003 true,
4004 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304005 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4006 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004007 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4008 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4009 return 0;
4010}
4011
4012/**
4013 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4014 * @wiphy: pointer to wireless wiphy structure.
4015 * @wdev: pointer to wireless_dev structure.
4016 * @data: Pointer to the Key data
4017 * @data_len:Length of the data passed
4018 *
4019 * This is called when wlan driver needs to save the keys received via
4020 * vendor specific command.
4021 *
4022 * Return: Return the Success or Failure code.
4023 */
4024static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4025 struct wireless_dev *wdev,
4026 const void *data, int data_len)
4027{
4028 int ret;
4029
4030 cds_ssr_protect(__func__);
4031 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4032 cds_ssr_unprotect(__func__);
4033
4034 return ret;
4035}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004036#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037
4038static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4039 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4040 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4041 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004042 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043};
4044
4045/**
4046 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4047 * @wiphy: pointer to wireless wiphy structure.
4048 * @wdev: pointer to wireless_dev structure.
4049 * @data: Pointer to the data to be passed via vendor interface
4050 * @data_len:Length of the data to be passed
4051 *
4052 * This is called when wlan driver needs to send wifi driver related info
4053 * (driver/fw version) to the user space application upon request.
4054 *
4055 * Return: Return the Success or Failure code.
4056 */
4057static int
4058__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4059 struct wireless_dev *wdev,
4060 const void *data, int data_len)
4061{
4062 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4063 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004064 tSirVersionString driver_version;
4065 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004066 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004067 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004068 struct sk_buff *reply_skb;
4069 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004070
Jeff Johnson1f61b612016-02-12 16:28:33 -08004071 ENTER_DEV(wdev->netdev);
4072
Anurag Chouhan6d760662016-02-20 16:05:43 +05304073 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004074 hdd_err("Command not allowed in FTM mode");
4075 return -EPERM;
4076 }
4077
4078 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304079 if (status)
4080 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081
4082 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4083 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004084 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004085 return -EINVAL;
4086 }
4087
4088 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004089 hdd_err("Rcvd req for Driver version");
4090 strlcpy(driver_version, QWLAN_VERSIONSTR,
4091 sizeof(driver_version));
4092 skb_len += strlen(driver_version) + 1;
4093 count++;
4094 }
4095
4096 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
4097 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004098 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4099 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004100 snprintf(firmware_version, sizeof(firmware_version),
4101 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4102 skb_len += strlen(firmware_version) + 1;
4103 count++;
4104 }
4105
4106 if (count == 0) {
4107 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004108 return -EINVAL;
4109 }
4110
Ryan Hsu7ac88852016-04-28 10:20:34 -07004111 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4112 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004114 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004115 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004116 return -ENOMEM;
4117 }
4118
Ryan Hsu7ac88852016-04-28 10:20:34 -07004119 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4120 if (nla_put_string(reply_skb,
4121 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4122 driver_version))
4123 goto error_nla_fail;
4124 }
4125
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304126 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004127 if (nla_put_string(reply_skb,
4128 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4129 firmware_version))
4130 goto error_nla_fail;
4131 }
4132
4133 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4134 if (nla_put_u32(reply_skb,
4135 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4136 hdd_ctx->radio_index))
4137 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004138 }
4139
4140 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004141
4142error_nla_fail:
4143 hdd_err("nla put fail");
4144 kfree_skb(reply_skb);
4145 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004146}
4147
4148/**
4149 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4150 * @wiphy: pointer to wireless wiphy structure.
4151 * @wdev: pointer to wireless_dev structure.
4152 * @data: Pointer to the data to be passed via vendor interface
4153 * @data_len:Length of the data to be passed
4154 *
4155 * This is called when wlan driver needs to send wifi driver related info
4156 * (driver/fw version) to the user space application upon request.
4157 *
4158 * Return: Return the Success or Failure code.
4159 */
4160static int
4161wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4162 struct wireless_dev *wdev,
4163 const void *data, int data_len)
4164{
4165 int ret;
4166
4167 cds_ssr_protect(__func__);
4168 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4169 cds_ssr_unprotect(__func__);
4170
4171 return ret;
4172}
4173
4174/**
4175 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4176 * @wiphy: pointer to wireless wiphy structure.
4177 * @wdev: pointer to wireless_dev structure.
4178 * @data: Pointer to the data to be passed via vendor interface
4179 * @data_len:Length of the data to be passed
4180 *
4181 * This is called by userspace to know the supported logger features
4182 *
4183 * Return: Return the Success or Failure code.
4184 */
4185static int
4186__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4187 struct wireless_dev *wdev,
4188 const void *data, int data_len)
4189{
4190 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4191 int status;
4192 uint32_t features;
4193 struct sk_buff *reply_skb = NULL;
4194
Jeff Johnson1f61b612016-02-12 16:28:33 -08004195 ENTER_DEV(wdev->netdev);
4196
Anurag Chouhan6d760662016-02-20 16:05:43 +05304197 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004198 hdd_err("Command not allowed in FTM mode");
4199 return -EPERM;
4200 }
4201
4202 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304203 if (status)
4204 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004205
4206 features = 0;
4207
4208 if (hdd_is_memdump_supported())
4209 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4210 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4211 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4212 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4213
4214 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4215 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4216 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004217 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004218 return -ENOMEM;
4219 }
4220
Jeff Johnson020db452016-06-29 14:37:26 -07004221 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004222 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4223 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004224 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004225 kfree_skb(reply_skb);
4226 return -EINVAL;
4227 }
4228
4229 return cfg80211_vendor_cmd_reply(reply_skb);
4230}
4231
4232/**
4233 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4234 * @wiphy: pointer to wireless wiphy structure.
4235 * @wdev: pointer to wireless_dev structure.
4236 * @data: Pointer to the data to be passed via vendor interface
4237 * @data_len:Length of the data to be passed
4238 *
4239 * This is called by userspace to know the supported logger features
4240 *
4241 * Return: Return the Success or Failure code.
4242 */
4243static int
4244wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4245 struct wireless_dev *wdev,
4246 const void *data, int data_len)
4247{
4248 int ret;
4249
4250 cds_ssr_protect(__func__);
4251 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4252 data, data_len);
4253 cds_ssr_unprotect(__func__);
4254
4255 return ret;
4256}
4257
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004258#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004259/**
4260 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304261 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004262 * @bssid: pointer to bssid of roamed AP.
4263 * @req_rsn_ie: Pointer to request RSN IE
4264 * @req_rsn_len: Length of the request RSN IE
4265 * @rsp_rsn_ie: Pointer to response RSN IE
4266 * @rsp_rsn_len: Length of the response RSN IE
4267 * @roam_info_ptr: Pointer to the roaming related information
4268 *
4269 * This is called when wlan driver needs to send the roaming and
4270 * authorization information after roaming.
4271 *
4272 * The information that would be sent is the request RSN IE, response
4273 * RSN IE and BSSID of the newly roamed AP.
4274 *
4275 * If the Authorized status is authenticated, then additional parameters
4276 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4277 * supplicant.
4278 *
4279 * The supplicant upon receiving this event would ignore the legacy
4280 * cfg80211_roamed call and use the entire information from this event.
4281 * The cfg80211_roamed should still co-exist since the kernel will
4282 * make use of the parameters even if the supplicant ignores it.
4283 *
4284 * Return: Return the Success or Failure code.
4285 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304286int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004287 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4288 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4289{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304290 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004291 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004292 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004293 ENTER();
4294
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304295 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004296 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004297
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004298 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004299 !roam_info_ptr->roamSynchInProgress)
4300 return 0;
4301
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004302 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304303 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004304 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4305 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4306 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004307 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004308 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4309 GFP_KERNEL);
4310
4311 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004312 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313 return -EINVAL;
4314 }
4315
4316 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4317 ETH_ALEN, bssid) ||
4318 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4319 req_rsn_len, req_rsn_ie) ||
4320 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4321 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004322 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004323 goto nla_put_failure;
4324 }
Jeff Johnson020db452016-06-29 14:37:26 -07004325 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004326 if (roam_info_ptr->synchAuthStatus ==
4327 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004328 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004329 if (nla_put_u8(skb,
4330 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4331 hdd_err("nla put fail");
4332 goto nla_put_failure;
4333 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004334 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4335 /* if FT or CCKM connection: dont send replay counter */
4336 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4337 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4338 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4339 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4340 nla_put(skb,
4341 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4342 SIR_REPLAY_CTR_LEN,
4343 roam_info_ptr->replay_ctr)) {
4344 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08004345 hdd_err("failed to send replay counter.");
4346 goto nla_put_failure;
4347 }
4348 if (nla_put(skb,
4349 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4350 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4351 nla_put(skb,
4352 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4353 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4354 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 goto nla_put_failure;
4356 }
4357 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004358 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004359 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4360 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004361 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 goto nla_put_failure;
4363 }
4364 }
4365
Jeff Johnson020db452016-06-29 14:37:26 -07004366 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004367 roam_info_ptr->subnet_change_status);
4368
4369 /*
4370 * Add subnet change status if subnet has changed
4371 * 0 = unchanged
4372 * 1 = changed
4373 * 2 = unknown
4374 */
4375 if (roam_info_ptr->subnet_change_status) {
4376 if (nla_put_u8(skb,
4377 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4378 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004379 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004380 goto nla_put_failure;
4381 }
4382 }
4383
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004384 cfg80211_vendor_event(skb, GFP_KERNEL);
4385 return 0;
4386
4387nla_put_failure:
4388 kfree_skb(skb);
4389 return -EINVAL;
4390}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004391#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004392
4393static const struct nla_policy
4394wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4395
4396 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4397 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4398 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304399 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304400 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4401 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004402 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4403 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4404 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4405 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4406 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304407 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004408};
4409
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004410/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304411 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4412 *
4413 * @adapter: Pointer to HDD adapter
4414 * @ie_data: Pointer to Scan IEs buffer
4415 * @ie_len: Length of Scan IEs
4416 *
4417 * Return: 0 on success; error number otherwise
4418 */
4419static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4420 uint8_t *ie_data, uint8_t ie_len)
4421{
4422 hdd_scaninfo_t *scan_info = NULL;
4423 scan_info = &adapter->scan_info;
4424
4425 if (scan_info->default_scan_ies) {
4426 qdf_mem_free(scan_info->default_scan_ies);
4427 scan_info->default_scan_ies = NULL;
4428 }
4429
4430 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4431 if (!scan_info->default_scan_ies)
4432 return -ENOMEM;
4433
4434 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4435 scan_info->default_scan_ies_len = ie_len;
4436 return 0;
4437}
4438
4439/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004440 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4441 * vendor command
4442 *
4443 * @wiphy: wiphy device pointer
4444 * @wdev: wireless device pointer
4445 * @data: Vendor command data buffer
4446 * @data_len: Buffer length
4447 *
4448 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4449 *
4450 * Return: Error code.
4451 */
4452static int
4453__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4454 struct wireless_dev *wdev,
4455 const void *data,
4456 int data_len)
4457{
4458 struct net_device *dev = wdev->netdev;
4459 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4460 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4461 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4462 int ret_val = 0;
4463 u32 modulated_dtim;
4464 u16 stats_avg_factor;
4465 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304466 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004467 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004468 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304469 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304470 int attr_len;
4471 int access_policy = 0;
4472 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4473 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304474 uint16_t scan_ie_len = 0;
4475 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304476 struct sir_set_tx_rx_aggregation_size request;
4477 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004478 uint8_t retry, delay;
4479 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304480 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304481
Jeff Johnson1f61b612016-02-12 16:28:33 -08004482 ENTER_DEV(dev);
4483
Anurag Chouhan6d760662016-02-20 16:05:43 +05304484 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004485 hdd_err("Command not allowed in FTM mode");
4486 return -EPERM;
4487 }
4488
4489 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304490 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004492
4493 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4494 data, data_len,
4495 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004496 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004497 return -EINVAL;
4498 }
4499
Krunal Sonie3531942016-04-12 17:43:53 -07004500 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4501 ftm_capab = nla_get_u32(tb[
4502 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4503 hdd_ctx->config->fine_time_meas_cap =
4504 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4505 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304506 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004507 hdd_ctx->config->fine_time_meas_cap);
4508 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4509 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4510 hdd_ctx->config->fine_time_meas_cap);
4511 }
4512
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004513 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4514 modulated_dtim = nla_get_u32(
4515 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4516
4517 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4518 adapter->sessionId,
4519 modulated_dtim);
4520
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304521 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004522 ret_val = -EPERM;
4523 }
4524
Kapil Gupta6213c012016-09-02 19:39:09 +05304525 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4526 qpower = nla_get_u8(
4527 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4528 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4529 ret_val = -EINVAL;
4530 }
4531
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004532 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4533 stats_avg_factor = nla_get_u16(
4534 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4535 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4536 adapter->sessionId,
4537 stats_avg_factor);
4538
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304539 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004540 ret_val = -EPERM;
4541 }
4542
4543
4544 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4545 guard_time = nla_get_u32(
4546 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4547 status = sme_configure_guard_time(hdd_ctx->hHal,
4548 adapter->sessionId,
4549 guard_time);
4550
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304551 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004552 ret_val = -EPERM;
4553 }
4554
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304555 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4556 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4557 attr_len = nla_len(
4558 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4559 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4560 hdd_info("Invalid value. attr_len %d",
4561 attr_len);
4562 return -EINVAL;
4563 }
4564
4565 nla_memcpy(&vendor_ie,
4566 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4567 attr_len);
4568 vendor_ie_present = true;
4569 hdd_info("Access policy vendor ie present.attr_len %d",
4570 attr_len);
4571 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4572 &vendor_ie[0], attr_len);
4573 }
4574
4575 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4576 access_policy = (int) nla_get_u32(
4577 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4578 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4579 (access_policy >
4580 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4581 hdd_info("Invalid value. access_policy %d",
4582 access_policy);
4583 return -EINVAL;
4584 }
4585 access_policy_present = true;
4586 hdd_info("Access policy present. access_policy %d",
4587 access_policy);
4588 }
4589
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004590 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4591 retry = nla_get_u8(tb[
4592 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4593 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4594 CFG_NON_AGG_RETRY_MAX : retry;
4595 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4596 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4597 retry, PDEV_CMD);
4598 }
4599
4600 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4601 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4602 retry = retry > CFG_AGG_RETRY_MAX ?
4603 CFG_AGG_RETRY_MAX : retry;
4604
4605 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4606 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4607 CFG_AGG_RETRY_MIN : retry;
4608 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4609 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4610 retry, PDEV_CMD);
4611 }
4612
4613 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4614 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4615 retry = retry > CFG_MGMT_RETRY_MAX ?
4616 CFG_MGMT_RETRY_MAX : retry;
4617 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4618 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4619 retry, PDEV_CMD);
4620 }
4621
4622 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4623 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4624 retry = retry > CFG_CTRL_RETRY_MAX ?
4625 CFG_CTRL_RETRY_MAX : retry;
4626 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4627 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4628 retry, PDEV_CMD);
4629 }
4630
4631 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4632 delay = nla_get_u8(tb[
4633 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4634 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4635 CFG_PROPAGATION_DELAY_MAX : delay;
4636 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4637 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4638 delay, PDEV_CMD);
4639 }
4640
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304641 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4642 tx_fail_count = nla_get_u32(
4643 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4644 if (tx_fail_count) {
4645 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4646 adapter->sessionId, tx_fail_count);
4647 if (QDF_STATUS_SUCCESS != status) {
4648 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4649 status);
4650 return -EINVAL;
4651 }
4652 }
4653 }
4654
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304655 if (vendor_ie_present && access_policy_present) {
4656 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4657 access_policy =
4658 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304659 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304660 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304661 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304662
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304663 hdd_info("calling sme_update_access_policy_vendor_ie");
4664 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4665 adapter->sessionId, &vendor_ie[0],
4666 access_policy);
4667 if (QDF_STATUS_SUCCESS != status) {
4668 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304669 return -EINVAL;
4670 }
4671 }
4672
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304673 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4674 set_value = nla_get_u8(
4675 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4676 hdd_info("set_value: %d", set_value);
4677 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4678 }
4679
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304680 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4681 scan_ie_len = nla_len(
4682 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4683 hdd_info("Received default scan IE of len %d session %d device mode %d",
4684 scan_ie_len, adapter->sessionId,
4685 adapter->device_mode);
4686 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4687 scan_ie = (uint8_t *) nla_data(tb
4688 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304689
4690 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4691 scan_ie_len))
4692 hdd_err("Failed to save default scan IEs");
4693
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304694 if (adapter->device_mode == QDF_STA_MODE) {
4695 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4696 adapter->sessionId, scan_ie,
4697 scan_ie_len);
4698 if (QDF_STATUS_SUCCESS != status)
4699 ret_val = -EPERM;
4700 }
4701 } else
4702 ret_val = -EPERM;
4703 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304704
4705 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4706 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4707 /* if one is specified, both must be specified */
4708 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4709 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4710 hdd_err("Both TX and RX MPDU Aggregation required");
4711 return -EINVAL;
4712 }
4713
4714 request.tx_aggregation_size = nla_get_u8(
4715 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4716 request.rx_aggregation_size = nla_get_u8(
4717 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4718 request.vdev_id = adapter->sessionId;
4719
4720 if (request.tx_aggregation_size >=
4721 CFG_TX_AGGREGATION_SIZE_MIN &&
4722 request.tx_aggregation_size <=
4723 CFG_TX_AGGREGATION_SIZE_MAX &&
4724 request.rx_aggregation_size >=
4725 CFG_RX_AGGREGATION_SIZE_MIN &&
4726 request.rx_aggregation_size <=
4727 CFG_RX_AGGREGATION_SIZE_MAX) {
4728 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4729 if (qdf_status != QDF_STATUS_SUCCESS) {
4730 hdd_err("failed to set aggr sizes err %d",
4731 qdf_status);
4732 ret_val = -EPERM;
4733 }
4734 } else {
4735 hdd_err("TX %d RX %d MPDU aggr size not in range",
4736 request.tx_aggregation_size,
4737 request.rx_aggregation_size);
4738 ret_val = -EINVAL;
4739 }
4740 }
4741
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304742 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4743 uint8_t ignore_assoc_disallowed;
4744
4745 ignore_assoc_disallowed
4746 = nla_get_u8(tb[
4747 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4748 hdd_info("Set ignore_assoc_disallowed value - %d",
4749 ignore_assoc_disallowed);
4750 if ((ignore_assoc_disallowed <
4751 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4752 (ignore_assoc_disallowed >
4753 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4754 return -EPERM;
4755
4756 sme_update_session_param(hdd_ctx->hHal,
4757 adapter->sessionId,
4758 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4759 ignore_assoc_disallowed);
4760 }
4761
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762 return ret_val;
4763}
4764
4765/**
4766 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4767 * vendor command
4768 *
4769 * @wiphy: wiphy device pointer
4770 * @wdev: wireless device pointer
4771 * @data: Vendor command data buffer
4772 * @data_len: Buffer length
4773 *
4774 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4775 *
4776 * Return: EOK or other error codes.
4777 */
4778static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4779 struct wireless_dev *wdev,
4780 const void *data,
4781 int data_len)
4782{
4783 int ret;
4784
4785 cds_ssr_protect(__func__);
4786 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4787 data, data_len);
4788 cds_ssr_unprotect(__func__);
4789
4790 return ret;
4791}
4792
4793static const struct
4794nla_policy
4795qca_wlan_vendor_wifi_logger_start_policy
4796[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4797 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4798 = {.type = NLA_U32 },
4799 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4800 = {.type = NLA_U32 },
4801 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4802 = {.type = NLA_U32 },
4803};
4804
4805/**
4806 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4807 * or disable the collection of packet statistics from the firmware
4808 * @wiphy: WIPHY structure pointer
4809 * @wdev: Wireless device structure pointer
4810 * @data: Pointer to the data received
4811 * @data_len: Length of the data received
4812 *
4813 * This function enables or disables the collection of packet statistics from
4814 * the firmware
4815 *
4816 * Return: 0 on success and errno on failure
4817 */
4818static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4819 struct wireless_dev *wdev,
4820 const void *data,
4821 int data_len)
4822{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304823 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004824 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4825 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4826 struct sir_wifi_start_log start_log;
4827
Jeff Johnson1f61b612016-02-12 16:28:33 -08004828 ENTER_DEV(wdev->netdev);
4829
Anurag Chouhan6d760662016-02-20 16:05:43 +05304830 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004831 hdd_err("Command not allowed in FTM mode");
4832 return -EPERM;
4833 }
4834
4835 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304836 if (status)
4837 return status;
4838
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004839
4840 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4841 data, data_len,
4842 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004843 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004844 return -EINVAL;
4845 }
4846
4847 /* Parse and fetch ring id */
4848 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004849 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004850 return -EINVAL;
4851 }
4852 start_log.ring_id = nla_get_u32(
4853 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004854 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004855
4856 /* Parse and fetch verbose level */
4857 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004858 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004859 return -EINVAL;
4860 }
4861 start_log.verbose_level = nla_get_u32(
4862 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004863 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004864
4865 /* Parse and fetch flag */
4866 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004867 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004868 return -EINVAL;
4869 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304870 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004871 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304872 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304874 /* size is buff size which can be set using iwpriv command*/
4875 start_log.size = 0;
4876
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004877 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4878
4879 if (start_log.ring_id == RING_ID_WAKELOCK) {
4880 /* Start/stop wakelock events */
4881 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4882 cds_set_wakelock_logging(true);
4883 else
4884 cds_set_wakelock_logging(false);
4885 return 0;
4886 }
4887
4888 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304889 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004890 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004891 status);
4892 return -EINVAL;
4893 }
4894 return 0;
4895}
4896
4897/**
4898 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4899 * or disable the collection of packet statistics from the firmware
4900 * @wiphy: WIPHY structure pointer
4901 * @wdev: Wireless device structure pointer
4902 * @data: Pointer to the data received
4903 * @data_len: Length of the data received
4904 *
4905 * This function is used to enable or disable the collection of packet
4906 * statistics from the firmware
4907 *
4908 * Return: 0 on success and errno on failure
4909 */
4910static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4911 struct wireless_dev *wdev,
4912 const void *data,
4913 int data_len)
4914{
4915 int ret = 0;
4916
4917 cds_ssr_protect(__func__);
4918 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4919 wdev, data, data_len);
4920 cds_ssr_unprotect(__func__);
4921
4922 return ret;
4923}
4924
4925static const struct
4926nla_policy
4927qca_wlan_vendor_wifi_logger_get_ring_data_policy
4928[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4929 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4930 = {.type = NLA_U32 },
4931};
4932
4933/**
4934 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4935 * @wiphy: WIPHY structure pointer
4936 * @wdev: Wireless device structure pointer
4937 * @data: Pointer to the data received
4938 * @data_len: Length of the data received
4939 *
4940 * This function is used to flush or retrieve the per packet statistics from
4941 * the driver
4942 *
4943 * Return: 0 on success and errno on failure
4944 */
4945static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4946 struct wireless_dev *wdev,
4947 const void *data,
4948 int data_len)
4949{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304950 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004951 uint32_t ring_id;
4952 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4953 struct nlattr *tb
4954 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4955
Jeff Johnson1f61b612016-02-12 16:28:33 -08004956 ENTER_DEV(wdev->netdev);
4957
Anurag Chouhan6d760662016-02-20 16:05:43 +05304958 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004959 hdd_err("Command not allowed in FTM mode");
4960 return -EPERM;
4961 }
4962
4963 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304964 if (status)
4965 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004966
4967 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4968 data, data_len,
4969 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004970 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004971 return -EINVAL;
4972 }
4973
4974 /* Parse and fetch ring id */
4975 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004976 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004977 return -EINVAL;
4978 }
4979
4980 ring_id = nla_get_u32(
4981 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4982
4983 if (ring_id == RING_ID_PER_PACKET_STATS) {
4984 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004985 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304986 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4987 /*
4988 * As part of DRIVER ring ID, flush both driver and fw logs.
4989 * For other Ring ID's driver doesn't have any rings to flush
4990 */
4991 hdd_notice("Bug report triggered by framework");
4992
4993 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4994 WLAN_LOG_INDICATOR_FRAMEWORK,
4995 WLAN_LOG_REASON_CODE_UNUSED,
4996 true, false);
4997 if (QDF_STATUS_SUCCESS != status) {
4998 hdd_err("Failed to trigger bug report");
4999 return -EINVAL;
5000 }
5001 } else {
5002 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5003 WLAN_LOG_INDICATOR_FRAMEWORK,
5004 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005006 return 0;
5007}
5008
5009/**
5010 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5011 * @wiphy: WIPHY structure pointer
5012 * @wdev: Wireless device structure pointer
5013 * @data: Pointer to the data received
5014 * @data_len: Length of the data received
5015 *
5016 * This function is used to flush or retrieve the per packet statistics from
5017 * the driver
5018 *
5019 * Return: 0 on success and errno on failure
5020 */
5021static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5022 struct wireless_dev *wdev,
5023 const void *data,
5024 int data_len)
5025{
5026 int ret = 0;
5027
5028 cds_ssr_protect(__func__);
5029 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5030 wdev, data, data_len);
5031 cds_ssr_unprotect(__func__);
5032
5033 return ret;
5034}
5035
5036#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5037/**
5038 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5039 * @hdd_ctx: HDD context
5040 * @request_id: [input] request id
5041 * @pattern_id: [output] pattern id
5042 *
5043 * This function loops through request id to pattern id array
5044 * if the slot is available, store the request id and return pattern id
5045 * if entry exists, return the pattern id
5046 *
5047 * Return: 0 on success and errno on failure
5048 */
5049static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5050 uint32_t request_id,
5051 uint8_t *pattern_id)
5052{
5053 uint32_t i;
5054
5055 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5056 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5057 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5058 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5059 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5060 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5061 return 0;
5062 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5063 request_id) {
5064 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5065 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5066 return 0;
5067 }
5068 }
5069 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5070 return -EINVAL;
5071}
5072
5073/**
5074 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5075 * @hdd_ctx: HDD context
5076 * @request_id: [input] request id
5077 * @pattern_id: [output] pattern id
5078 *
5079 * This function loops through request id to pattern id array
5080 * reset request id to 0 (slot available again) and
5081 * return pattern id
5082 *
5083 * Return: 0 on success and errno on failure
5084 */
5085static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5086 uint32_t request_id,
5087 uint8_t *pattern_id)
5088{
5089 uint32_t i;
5090
5091 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5092 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5093 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5094 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5095 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5096 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5097 return 0;
5098 }
5099 }
5100 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5101 return -EINVAL;
5102}
5103
5104
5105/*
5106 * define short names for the global vendor params
5107 * used by __wlan_hdd_cfg80211_offloaded_packets()
5108 */
5109#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5110#define PARAM_REQUEST_ID \
5111 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5112#define PARAM_CONTROL \
5113 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5114#define PARAM_IP_PACKET \
5115 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5116#define PARAM_SRC_MAC_ADDR \
5117 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5118#define PARAM_DST_MAC_ADDR \
5119 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5120#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5121
5122/**
5123 * wlan_hdd_add_tx_ptrn() - add tx pattern
5124 * @adapter: adapter pointer
5125 * @hdd_ctx: hdd context
5126 * @tb: nl attributes
5127 *
5128 * This function reads the NL attributes and forms a AddTxPtrn message
5129 * posts it to SME.
5130 *
5131 */
5132static int
5133wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5134 struct nlattr **tb)
5135{
5136 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305137 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005138 uint32_t request_id, ret, len;
5139 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305140 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005141 uint16_t eth_type = htons(ETH_P_IP);
5142
5143 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005144 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005145 return -ENOTSUPP;
5146 }
5147
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305148 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005150 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005151 return -ENOMEM;
5152 }
5153
5154 /* Parse and fetch request Id */
5155 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005156 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005157 goto fail;
5158 }
5159
5160 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5161 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005162 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005163 return -EINVAL;
5164 }
Jeff Johnson77848112016-06-29 14:52:06 -07005165 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005166
5167 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005168 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005169 goto fail;
5170 }
5171 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07005172 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005173 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005174 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005175 goto fail;
5176 }
5177
5178 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005179 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005180 goto fail;
5181 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005182 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305183 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005184 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005185 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005186
Anurag Chouhanc5548422016-02-24 18:33:27 +05305187 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005188 &adapter->macAddressCurrent)) {
5189 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005190 goto fail;
5191 }
5192
5193 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005194 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005195 goto fail;
5196 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305197 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005198 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199 MAC_ADDR_ARRAY(dst_addr.bytes));
5200
5201 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005202 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005203 goto fail;
5204 }
5205 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07005206 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005207
5208 if (add_req->ucPtrnSize < 0 ||
5209 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5210 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005211 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005212 add_req->ucPtrnSize);
5213 goto fail;
5214 }
5215
5216 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305217 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305218 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305219 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305220 QDF_MAC_ADDR_SIZE);
5221 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305222 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005223 len += 2;
5224
5225 /*
5226 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5227 * ------------------------------------------------------------
5228 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5229 * ------------------------------------------------------------
5230 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305231 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005232 nla_data(tb[PARAM_IP_PACKET]),
5233 add_req->ucPtrnSize);
5234 add_req->ucPtrnSize += len;
5235
5236 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5237 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005238 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239 goto fail;
5240 }
5241 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005242 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005243
5244 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305245 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005246 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247 goto fail;
5248 }
5249
5250 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305251 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252 return 0;
5253
5254fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305255 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005256 return -EINVAL;
5257}
5258
5259/**
5260 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5261 * @adapter: adapter pointer
5262 * @hdd_ctx: hdd context
5263 * @tb: nl attributes
5264 *
5265 * This function reads the NL attributes and forms a DelTxPtrn message
5266 * posts it to SME.
5267 *
5268 */
5269static int
5270wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5271 struct nlattr **tb)
5272{
5273 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305274 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005275 uint32_t request_id, ret;
5276 uint8_t pattern_id = 0;
5277
5278 /* Parse and fetch request Id */
5279 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005280 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005281 return -EINVAL;
5282 }
5283 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5284 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005285 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005286 return -EINVAL;
5287 }
5288
5289 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5290 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005291 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005292 return -EINVAL;
5293 }
5294
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305295 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005296 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005297 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005298 return -ENOMEM;
5299 }
5300
Anurag Chouhanc5548422016-02-24 18:33:27 +05305301 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005302 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005303 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005304 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005305 request_id, del_req->ucPtrnId);
5306
5307 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305308 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005309 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005310 goto fail;
5311 }
5312
5313 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305314 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005315 return 0;
5316
5317fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305318 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005319 return -EINVAL;
5320}
5321
5322
5323/**
5324 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5325 * @wiphy: Pointer to wireless phy
5326 * @wdev: Pointer to wireless device
5327 * @data: Pointer to data
5328 * @data_len: Data length
5329 *
5330 * Return: 0 on success, negative errno on failure
5331 */
5332static int
5333__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5334 struct wireless_dev *wdev,
5335 const void *data,
5336 int data_len)
5337{
5338 struct net_device *dev = wdev->netdev;
5339 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5340 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5341 struct nlattr *tb[PARAM_MAX + 1];
5342 uint8_t control;
5343 int ret;
5344 static const struct nla_policy policy[PARAM_MAX + 1] = {
5345 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5346 [PARAM_CONTROL] = { .type = NLA_U32 },
5347 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305348 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005349 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305350 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005351 [PARAM_PERIOD] = { .type = NLA_U32 },
5352 };
5353
Jeff Johnson1f61b612016-02-12 16:28:33 -08005354 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005355
Anurag Chouhan6d760662016-02-20 16:05:43 +05305356 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005357 hdd_err("Command not allowed in FTM mode");
5358 return -EPERM;
5359 }
5360
5361 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305362 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005363 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364
5365 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005366 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005367 return -ENOTSUPP;
5368 }
5369
5370 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005371 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372 return -EINVAL;
5373 }
5374
5375 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005376 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377 return -EINVAL;
5378 }
5379 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07005380 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005381
5382 if (control == WLAN_START_OFFLOADED_PACKETS)
5383 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005384 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005386
5387 hdd_err("Invalid control: %d", control);
5388
5389 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005390}
5391
5392/*
5393 * done with short names for the global vendor params
5394 * used by __wlan_hdd_cfg80211_offloaded_packets()
5395 */
5396#undef PARAM_MAX
5397#undef PARAM_REQUEST_ID
5398#undef PARAM_CONTROL
5399#undef PARAM_IP_PACKET
5400#undef PARAM_SRC_MAC_ADDR
5401#undef PARAM_DST_MAC_ADDR
5402#undef PARAM_PERIOD
5403
5404/**
5405 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5406 * @wiphy: wiphy structure pointer
5407 * @wdev: Wireless device structure pointer
5408 * @data: Pointer to the data received
5409 * @data_len: Length of @data
5410 *
5411 * Return: 0 on success; errno on failure
5412 */
5413static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5414 struct wireless_dev *wdev,
5415 const void *data,
5416 int data_len)
5417{
5418 int ret = 0;
5419
5420 cds_ssr_protect(__func__);
5421 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5422 wdev, data, data_len);
5423 cds_ssr_unprotect(__func__);
5424
5425 return ret;
5426}
5427#endif
5428
5429/*
5430 * define short names for the global vendor params
5431 * used by __wlan_hdd_cfg80211_monitor_rssi()
5432 */
5433#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5434#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5435#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5436#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5437#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5438
5439/**
5440 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5441 * @wiphy: Pointer to wireless phy
5442 * @wdev: Pointer to wireless device
5443 * @data: Pointer to data
5444 * @data_len: Data length
5445 *
5446 * Return: 0 on success, negative errno on failure
5447 */
5448static int
5449__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5450 struct wireless_dev *wdev,
5451 const void *data,
5452 int data_len)
5453{
5454 struct net_device *dev = wdev->netdev;
5455 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5456 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5457 struct nlattr *tb[PARAM_MAX + 1];
5458 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305459 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005460 int ret;
5461 uint32_t control;
5462 static const struct nla_policy policy[PARAM_MAX + 1] = {
5463 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5464 [PARAM_CONTROL] = { .type = NLA_U32 },
5465 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5466 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5467 };
5468
Jeff Johnson1f61b612016-02-12 16:28:33 -08005469 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005470
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305471 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5472 hdd_err("invalid session id: %d", adapter->sessionId);
5473 return -EINVAL;
5474 }
5475
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005476 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305477 if (ret)
5478 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005479
5480 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005481 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005482 return -ENOTSUPP;
5483 }
5484
5485 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005486 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005487 return -EINVAL;
5488 }
5489
5490 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005491 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005492 return -EINVAL;
5493 }
5494
5495 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005496 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005497 return -EINVAL;
5498 }
5499
5500 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5501 req.session_id = adapter->sessionId;
5502 control = nla_get_u32(tb[PARAM_CONTROL]);
5503
5504 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5505 req.control = true;
5506 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005507 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005508 return -EINVAL;
5509 }
5510
5511 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005512 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005513 return -EINVAL;
5514 }
5515
5516 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5517 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5518
5519 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005520 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005521 req.min_rssi, req.max_rssi);
5522 return -EINVAL;
5523 }
Jeff Johnson77848112016-06-29 14:52:06 -07005524 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005525 req.min_rssi, req.max_rssi);
5526
5527 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5528 req.control = false;
5529 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005530 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005531 return -EINVAL;
5532 }
Jeff Johnson77848112016-06-29 14:52:06 -07005533 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005534 req.request_id, req.session_id, req.control);
5535
5536 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305537 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005538 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005539 return -EINVAL;
5540 }
5541
5542 return 0;
5543}
5544
5545/*
5546 * done with short names for the global vendor params
5547 * used by __wlan_hdd_cfg80211_monitor_rssi()
5548 */
5549#undef PARAM_MAX
5550#undef PARAM_CONTROL
5551#undef PARAM_REQUEST_ID
5552#undef PARAM_MAX_RSSI
5553#undef PARAM_MIN_RSSI
5554
5555/**
5556 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5557 * @wiphy: wiphy structure pointer
5558 * @wdev: Wireless device structure pointer
5559 * @data: Pointer to the data received
5560 * @data_len: Length of @data
5561 *
5562 * Return: 0 on success; errno on failure
5563 */
5564static int
5565wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5566 const void *data, int data_len)
5567{
5568 int ret;
5569
5570 cds_ssr_protect(__func__);
5571 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5572 cds_ssr_unprotect(__func__);
5573
5574 return ret;
5575}
5576
5577/**
5578 * hdd_rssi_threshold_breached() - rssi breached NL event
5579 * @hddctx: HDD context
5580 * @data: rssi breached event data
5581 *
5582 * This function reads the rssi breached event %data and fill in the skb with
5583 * NL attributes and send up the NL event.
5584 *
5585 * Return: none
5586 */
5587void hdd_rssi_threshold_breached(void *hddctx,
5588 struct rssi_breach_event *data)
5589{
5590 hdd_context_t *hdd_ctx = hddctx;
5591 struct sk_buff *skb;
5592
5593 ENTER();
5594
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305595 if (wlan_hdd_validate_context(hdd_ctx))
5596 return;
5597 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005598 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005599 return;
5600 }
5601
5602 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5603 NULL,
5604 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5605 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5606 GFP_KERNEL);
5607
5608 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005609 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005610 return;
5611 }
5612
Jeff Johnson77848112016-06-29 14:52:06 -07005613 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005614 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005615 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005616 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5617
5618 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5619 data->request_id) ||
5620 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5621 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5622 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5623 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005624 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005625 goto fail;
5626 }
5627
5628 cfg80211_vendor_event(skb, GFP_KERNEL);
5629 return;
5630
5631fail:
5632 kfree_skb(skb);
5633 return;
5634}
5635
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305636static const struct nla_policy
5637ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5638 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5639};
5640
5641/**
5642 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5643 * @wiphy: Pointer to wireless phy
5644 * @wdev: Pointer to wireless device
5645 * @data: Pointer to data
5646 * @data_len: Length of @data
5647 *
5648 * Return: 0 on success, negative errno on failure
5649 */
5650static int
5651__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5652 struct wireless_dev *wdev,
5653 const void *data, int data_len)
5654{
5655 int status;
5656 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5657 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005658 struct net_device *dev = wdev->netdev;
5659 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305660
5661 ENTER_DEV(wdev->netdev);
5662
5663 status = wlan_hdd_validate_context(pHddCtx);
5664 if (0 != status)
5665 return status;
5666 if (!pHddCtx->config->fhostNSOffload) {
5667 hdd_err("ND Offload not supported");
5668 return -EINVAL;
5669 }
5670
5671 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5672 (struct nlattr *)data,
5673 data_len, ns_offload_set_policy)) {
5674 hdd_err("nla_parse failed");
5675 return -EINVAL;
5676 }
5677
5678 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5679 hdd_err("ND Offload flag attribute not present");
5680 return -EINVAL;
5681 }
5682
5683 pHddCtx->ns_offload_enable =
5684 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5685
Dustin Brownd8279d22016-09-07 14:52:57 -07005686 /* update ns offload in case it is already enabled/disabled */
5687 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5688
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305689 return 0;
5690}
5691
5692/**
5693 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5694 * @wiphy: pointer to wireless wiphy structure.
5695 * @wdev: pointer to wireless_dev structure.
5696 * @data: Pointer to the data to be passed via vendor interface
5697 * @data_len:Length of the data to be passed
5698 *
5699 * Return: Return the Success or Failure code.
5700 */
5701static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5702 struct wireless_dev *wdev,
5703 const void *data, int data_len)
5704{
5705 int ret;
5706
5707 cds_ssr_protect(__func__);
5708 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5709 cds_ssr_unprotect(__func__);
5710
5711 return ret;
5712}
5713
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005714/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5715 * @wiphy: Pointer to wireless phy
5716 * @wdev: Pointer to wireless device
5717 * @data: Pointer to data
5718 * @data_len: Data length
5719 *
5720 * This function return the preferred frequency list generated by the policy
5721 * manager.
5722 *
5723 * Return: success or failure code
5724 */
5725static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5726 struct wireless_dev
5727 *wdev, const void *data,
5728 int data_len)
5729{
5730 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5731 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305732 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305733 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005734 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305735 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005736 enum cds_con_mode intf_mode;
5737 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5738 struct sk_buff *reply_skb;
5739
Jeff Johnson1f61b612016-02-12 16:28:33 -08005740 ENTER_DEV(wdev->netdev);
5741
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005742 ret = wlan_hdd_validate_context(hdd_ctx);
5743 if (ret)
5744 return -EINVAL;
5745
5746 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5747 data, data_len, NULL)) {
5748 hdd_err("Invalid ATTR");
5749 return -EINVAL;
5750 }
5751
5752 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5753 hdd_err("attr interface type failed");
5754 return -EINVAL;
5755 }
5756
5757 intf_mode = nla_get_u32(tb
5758 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5759
5760 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5761 hdd_err("Invalid interface type");
5762 return -EINVAL;
5763 }
5764
5765 hdd_debug("Userspace requested pref freq list");
5766
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305767 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5768 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305769 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005770 hdd_err("Get pcl failed");
5771 return -EINVAL;
5772 }
5773
5774 /* convert channel number to frequency */
5775 for (i = 0; i < pcl_len; i++) {
5776 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5777 freq_list[i] =
5778 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005779 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005780 else
5781 freq_list[i] =
5782 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005783 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005784 }
5785
5786 /* send the freq_list back to supplicant */
5787 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5788 sizeof(u32) *
5789 pcl_len +
5790 NLMSG_HDRLEN);
5791
5792 if (!reply_skb) {
5793 hdd_err("Allocate reply_skb failed");
5794 return -EINVAL;
5795 }
5796
5797 if (nla_put_u32(reply_skb,
5798 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5799 intf_mode) ||
5800 nla_put(reply_skb,
5801 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5802 sizeof(uint32_t) * pcl_len,
5803 freq_list)) {
5804 hdd_err("nla put fail");
5805 kfree_skb(reply_skb);
5806 return -EINVAL;
5807 }
5808
5809 return cfg80211_vendor_cmd_reply(reply_skb);
5810}
5811
5812/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5813 * @wiphy: Pointer to wireless phy
5814 * @wdev: Pointer to wireless device
5815 * @data: Pointer to data
5816 * @data_len: Data length
5817 *
5818 * This function return the preferred frequency list generated by the policy
5819 * manager.
5820 *
5821 * Return: success or failure code
5822 */
5823static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5824 struct wireless_dev
5825 *wdev, const void *data,
5826 int data_len)
5827{
5828 int ret = 0;
5829
5830 cds_ssr_protect(__func__);
5831 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5832 data, data_len);
5833 cds_ssr_unprotect(__func__);
5834
5835 return ret;
5836}
5837
5838/**
5839 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5840 * @wiphy: Pointer to wireless phy
5841 * @wdev: Pointer to wireless device
5842 * @data: Pointer to data
5843 * @data_len: Data length
5844 *
5845 * Return: 0 on success, negative errno on failure
5846 */
5847static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5848 struct wireless_dev *wdev,
5849 const void *data,
5850 int data_len)
5851{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305852 struct net_device *ndev = wdev->netdev;
5853 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005854 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5855 int ret = 0;
5856 enum cds_con_mode intf_mode;
5857 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5858 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005859
Jeff Johnson1f61b612016-02-12 16:28:33 -08005860 ENTER_DEV(ndev);
5861
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005862 ret = wlan_hdd_validate_context(hdd_ctx);
5863 if (ret)
5864 return ret;
5865
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005866 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5867 data, data_len, NULL)) {
5868 hdd_err("Invalid ATTR");
5869 return -EINVAL;
5870 }
5871
5872 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5873 hdd_err("attr interface type failed");
5874 return -EINVAL;
5875 }
5876
5877 intf_mode = nla_get_u32(tb
5878 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5879
5880 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5881 hdd_err("Invalid interface type");
5882 return -EINVAL;
5883 }
5884
5885 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5886 hdd_err("attr probable freq failed");
5887 return -EINVAL;
5888 }
5889
5890 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5891 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5892
5893 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005894 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005895 channel_hint, HW_MODE_20_MHZ)) {
5896 hdd_err("Set channel hint failed due to concurrency check");
5897 return -EINVAL;
5898 }
5899
Krunal Soni09e55032016-06-07 10:06:55 -07005900 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5901 hdd_warn("Remain On Channel Pending");
5902
Krunal Soni3091bcc2016-06-23 12:28:21 -07005903 ret = qdf_reset_connection_update();
5904 if (!QDF_IS_STATUS_SUCCESS(ret))
5905 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005906
Krunal Soni3091bcc2016-06-23 12:28:21 -07005907 ret = cds_current_connections_update(adapter->sessionId,
5908 channel_hint,
5909 SIR_UPDATE_REASON_SET_OPER_CHAN);
5910 if (QDF_STATUS_E_FAILURE == ret) {
5911 /* return in the failure case */
5912 hdd_err("ERROR: connections update failed!!");
5913 return -EINVAL;
5914 }
5915
5916 if (QDF_STATUS_SUCCESS == ret) {
5917 /*
5918 * Success is the only case for which we expect hw mode
5919 * change to take place, hence we need to wait.
5920 * For any other return value it should be a pass
5921 * through
5922 */
5923 ret = qdf_wait_for_connection_update();
5924 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5925 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005926 return -EINVAL;
5927 }
5928
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005929 }
5930
5931 return 0;
5932}
5933
5934/**
5935 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5936 * @wiphy: Pointer to wireless phy
5937 * @wdev: Pointer to wireless device
5938 * @data: Pointer to data
5939 * @data_len: Data length
5940 *
5941 * Return: 0 on success, negative errno on failure
5942 */
5943static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5944 struct wireless_dev *wdev,
5945 const void *data,
5946 int data_len)
5947{
5948 int ret = 0;
5949
5950 cds_ssr_protect(__func__);
5951 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5952 data, data_len);
5953 cds_ssr_unprotect(__func__);
5954
5955 return ret;
5956}
5957
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305958static const struct
5959nla_policy
5960qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5961 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5962};
5963
5964/**
5965 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5966 * @wiphy: WIPHY structure pointer
5967 * @wdev: Wireless device structure pointer
5968 * @data: Pointer to the data received
5969 * @data_len: Length of the data received
5970 *
5971 * This function is used to get link properties like nss, rate flags and
5972 * operating frequency for the active connection with the given peer.
5973 *
5974 * Return: 0 on success and errno on failure
5975 */
5976static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5977 struct wireless_dev *wdev,
5978 const void *data,
5979 int data_len)
5980{
5981 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5982 struct net_device *dev = wdev->netdev;
5983 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5984 hdd_station_ctx_t *hdd_sta_ctx;
5985 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305986 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305987 uint32_t sta_id;
5988 struct sk_buff *reply_skb;
5989 uint32_t rate_flags = 0;
5990 uint8_t nss;
5991 uint8_t final_rate_flags = 0;
5992 uint32_t freq;
5993
Jeff Johnson1f61b612016-02-12 16:28:33 -08005994 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305995
Anurag Chouhan6d760662016-02-20 16:05:43 +05305996 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305997 hdd_err("Command not allowed in FTM mode");
5998 return -EPERM;
5999 }
6000
6001 if (0 != wlan_hdd_validate_context(hdd_ctx))
6002 return -EINVAL;
6003
6004 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6005 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006006 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306007 return -EINVAL;
6008 }
6009
6010 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006011 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306012 adapter->device_mode);
6013 return -EINVAL;
6014 }
6015
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306016 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306017 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07006018 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306019 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6020
Krunal Sonib4326f22016-03-10 13:05:51 -08006021 if (adapter->device_mode == QDF_STA_MODE ||
6022 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306023 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6024 if ((hdd_sta_ctx->conn_info.connState !=
6025 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306026 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306027 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006028 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306029 MAC_ADDR_ARRAY(peer_mac));
6030 return -EINVAL;
6031 }
6032
6033 nss = hdd_sta_ctx->conn_info.nss;
6034 freq = cds_chan_to_freq(
6035 hdd_sta_ctx->conn_info.operationChannel);
6036 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006037 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6038 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306039
6040 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6041 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306042 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306043 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306044 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306045 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306046 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306047 break;
6048 }
6049
6050 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006051 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306052 MAC_ADDR_ARRAY(peer_mac));
6053 return -EINVAL;
6054 }
6055
6056 nss = adapter->aStaInfo[sta_id].nss;
6057 freq = cds_chan_to_freq(
6058 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6059 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6060 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006061 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306062 MAC_ADDR_ARRAY(peer_mac));
6063 return -EINVAL;
6064 }
6065
6066 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6067 if (rate_flags & eHAL_TX_RATE_VHT80) {
6068 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006069#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306070 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006071#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306072 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6073 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006074#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306075 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006076#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306077 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6078 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6079 } else if (rate_flags &
6080 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6081 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006082#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306083 if (rate_flags & eHAL_TX_RATE_HT40)
6084 final_rate_flags |=
6085 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006086#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306087 }
6088
6089 if (rate_flags & eHAL_TX_RATE_SGI) {
6090 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6091 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6092 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6093 }
6094 }
6095
6096 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6097 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6098
6099 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006100 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306101 return -EINVAL;
6102 }
6103
6104 if (nla_put_u8(reply_skb,
6105 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6106 nss) ||
6107 nla_put_u8(reply_skb,
6108 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6109 final_rate_flags) ||
6110 nla_put_u32(reply_skb,
6111 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6112 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006113 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306114 kfree_skb(reply_skb);
6115 return -EINVAL;
6116 }
6117
6118 return cfg80211_vendor_cmd_reply(reply_skb);
6119}
6120
6121/**
6122 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6123 * properties.
6124 * @wiphy: WIPHY structure pointer
6125 * @wdev: Wireless device structure pointer
6126 * @data: Pointer to the data received
6127 * @data_len: Length of the data received
6128 *
6129 * This function is used to get link properties like nss, rate flags and
6130 * operating frequency for the active connection with the given peer.
6131 *
6132 * Return: 0 on success and errno on failure
6133 */
6134static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6135 struct wireless_dev *wdev,
6136 const void *data,
6137 int data_len)
6138{
6139 int ret = 0;
6140
6141 cds_ssr_protect(__func__);
6142 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6143 wdev, data, data_len);
6144 cds_ssr_unprotect(__func__);
6145
6146 return ret;
6147}
6148
Peng Xu278d0122015-09-24 16:34:17 -07006149static const struct
6150nla_policy
6151qca_wlan_vendor_ota_test_policy
6152[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6153 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6154};
6155
6156/**
6157 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6158 * @wiphy: Pointer to wireless phy
6159 * @wdev: Pointer to wireless device
6160 * @data: Pointer to data
6161 * @data_len: Data length
6162 *
6163 * Return: 0 on success, negative errno on failure
6164 */
6165static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6166 struct wireless_dev *wdev,
6167 const void *data,
6168 int data_len)
6169{
6170 struct net_device *dev = wdev->netdev;
6171 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6172 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6173 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6174 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6175 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306176 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006177 uint32_t current_roam_state;
6178
Jeff Johnson1f61b612016-02-12 16:28:33 -08006179 ENTER_DEV(dev);
6180
Anurag Chouhan6d760662016-02-20 16:05:43 +05306181 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006182 hdd_err("Command not allowed in FTM mode");
6183 return -EPERM;
6184 }
6185
6186 if (0 != wlan_hdd_validate_context(hdd_ctx))
6187 return -EINVAL;
6188
6189 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6190 data, data_len,
6191 qca_wlan_vendor_ota_test_policy)) {
6192 hdd_err("invalid attr");
6193 return -EINVAL;
6194 }
6195
6196 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6197 hdd_err("attr ota test failed");
6198 return -EINVAL;
6199 }
6200
6201 ota_enable = nla_get_u8(
6202 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6203
6204 hdd_info(" OTA test enable = %d", ota_enable);
6205 if (ota_enable != 1) {
6206 hdd_err("Invalid value, only enable test mode is supported!");
6207 return -EINVAL;
6208 }
6209
6210 current_roam_state =
6211 sme_get_current_roam_state(hal, adapter->sessionId);
6212 status = sme_stop_roaming(hal, adapter->sessionId,
6213 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306214 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006215 hdd_err("Enable/Disable roaming failed");
6216 return -EINVAL;
6217 }
6218
6219 status = sme_ps_enable_disable(hal, adapter->sessionId,
6220 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306221 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006222 hdd_err("Enable/Disable power save failed");
6223 /* restore previous roaming setting */
6224 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6225 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6226 status = sme_start_roaming(hal, adapter->sessionId,
6227 eCsrHddIssued);
6228 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6229 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6230 status = sme_stop_roaming(hal, adapter->sessionId,
6231 eCsrHddIssued);
6232
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306233 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006234 hdd_err("Restoring roaming state failed");
6235
6236 return -EINVAL;
6237 }
6238
6239
6240 return 0;
6241}
6242
6243/**
6244 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6245 * @wiphy: Pointer to wireless phy
6246 * @wdev: Pointer to wireless device
6247 * @data: Pointer to data
6248 * @data_len: Data length
6249 *
6250 * Return: 0 on success, negative errno on failure
6251 */
6252static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6253 struct wireless_dev *wdev,
6254 const void *data,
6255 int data_len)
6256{
6257 int ret = 0;
6258
6259 cds_ssr_protect(__func__);
6260 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6261 cds_ssr_unprotect(__func__);
6262
6263 return ret;
6264}
6265
Peng Xu4d67c8f2015-10-16 16:02:26 -07006266/**
6267 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6268 * @wiphy: Pointer to wireless phy
6269 * @wdev: Pointer to wireless device
6270 * @data: Pointer to data
6271 * @data_len: Data length
6272 *
6273 * Return: 0 on success, negative errno on failure
6274 */
6275static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6276 struct wireless_dev *wdev,
6277 const void *data,
6278 int data_len)
6279{
6280 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6281 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006282 hdd_adapter_t *adapter;
6283 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006284 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6285 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006286 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006287
Jeff Johnson1f61b612016-02-12 16:28:33 -08006288 ENTER_DEV(dev);
6289
Peng Xu4d67c8f2015-10-16 16:02:26 -07006290 ret = wlan_hdd_validate_context(hdd_ctx);
6291 if (ret)
6292 return ret;
6293
6294 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6295
6296 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6297 data, data_len, NULL)) {
6298 hdd_err("Invalid ATTR");
6299 return -EINVAL;
6300 }
6301
6302 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6303 hdd_err("attr tx power scale failed");
6304 return -EINVAL;
6305 }
6306
6307 scale_value = nla_get_u8(tb
6308 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6309
6310 if (scale_value > MAX_TXPOWER_SCALE) {
6311 hdd_err("Invalid tx power scale level");
6312 return -EINVAL;
6313 }
6314
Peng Xu62c8c432016-05-09 15:23:02 -07006315 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006316
Peng Xu62c8c432016-05-09 15:23:02 -07006317 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006318 hdd_err("Set tx power scale failed");
6319 return -EINVAL;
6320 }
6321
6322 return 0;
6323}
6324
6325/**
6326 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6327 * @wiphy: Pointer to wireless phy
6328 * @wdev: Pointer to wireless device
6329 * @data: Pointer to data
6330 * @data_len: Data length
6331 *
6332 * Return: 0 on success, negative errno on failure
6333 */
6334static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6335 struct wireless_dev *wdev,
6336 const void *data,
6337 int data_len)
6338{
Peng Xu62c8c432016-05-09 15:23:02 -07006339 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006340
6341 cds_ssr_protect(__func__);
6342 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6343 data, data_len);
6344 cds_ssr_unprotect(__func__);
6345
6346 return ret;
6347}
6348
6349/**
6350 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6351 * @wiphy: Pointer to wireless phy
6352 * @wdev: Pointer to wireless device
6353 * @data: Pointer to data
6354 * @data_len: Data length
6355 *
6356 * Return: 0 on success, negative errno on failure
6357 */
6358static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6359 struct wireless_dev *wdev,
6360 const void *data,
6361 int data_len)
6362{
6363 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6364 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006365 hdd_adapter_t *adapter;
6366 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006367 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6368 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006369 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006370
Jeff Johnson1f61b612016-02-12 16:28:33 -08006371 ENTER_DEV(dev);
6372
Peng Xu4d67c8f2015-10-16 16:02:26 -07006373 ret = wlan_hdd_validate_context(hdd_ctx);
6374 if (ret)
6375 return ret;
6376
6377 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6378
6379 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6380 data, data_len, NULL)) {
6381 hdd_err("Invalid ATTR");
6382 return -EINVAL;
6383 }
6384
6385 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6386 hdd_err("attr tx power decrease db value failed");
6387 return -EINVAL;
6388 }
6389
6390 scale_value = nla_get_u8(tb
6391 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6392
Peng Xu62c8c432016-05-09 15:23:02 -07006393 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6394 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006395
Peng Xu62c8c432016-05-09 15:23:02 -07006396 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006397 hdd_err("Set tx power decrease db failed");
6398 return -EINVAL;
6399 }
6400
6401 return 0;
6402}
6403
6404/**
6405 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6406 * @wiphy: Pointer to wireless phy
6407 * @wdev: Pointer to wireless device
6408 * @data: Pointer to data
6409 * @data_len: Data length
6410 *
6411 * Return: 0 on success, negative errno on failure
6412 */
6413static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6414 struct wireless_dev *wdev,
6415 const void *data,
6416 int data_len)
6417{
Peng Xu62c8c432016-05-09 15:23:02 -07006418 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006419
6420 cds_ssr_protect(__func__);
6421 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6422 data, data_len);
6423 cds_ssr_unprotect(__func__);
6424
6425 return ret;
6426}
Peng Xu8fdaa492016-06-22 10:20:47 -07006427
6428/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306429 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6430 * @wiphy: Pointer to wireless phy
6431 * @wdev: Pointer to wireless device
6432 * @data: Pointer to data
6433 * @data_len: Data length
6434 *
6435 * Processes the conditional channel switch request and invokes the helper
6436 * APIs to process the channel switch request.
6437 *
6438 * Return: 0 on success, negative errno on failure
6439 */
6440static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6441 struct wireless_dev *wdev,
6442 const void *data,
6443 int data_len)
6444{
6445 int ret;
6446 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6447 struct net_device *dev = wdev->netdev;
6448 hdd_adapter_t *adapter;
6449 struct nlattr
6450 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6451 uint32_t freq_len, i;
6452 uint32_t *freq;
6453 uint8_t chans[QDF_MAX_NUM_CHAN];
6454
6455 ENTER_DEV(dev);
6456
6457 ret = wlan_hdd_validate_context(hdd_ctx);
6458 if (ret)
6459 return ret;
6460
6461 if (!hdd_ctx->config->enableDFSMasterCap) {
6462 hdd_err("DFS master capability is not present in the driver");
6463 return -EINVAL;
6464 }
6465
6466 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6467 hdd_err("Command not allowed in FTM mode");
6468 return -EPERM;
6469 }
6470
6471 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6472 if (adapter->device_mode != QDF_SAP_MODE) {
6473 hdd_err("Invalid device mode %d", adapter->device_mode);
6474 return -EINVAL;
6475 }
6476
6477 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6478 data, data_len, NULL)) {
6479 hdd_err("Invalid ATTR");
6480 return -EINVAL;
6481 }
6482
6483 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6484 hdd_err("Frequency list is missing");
6485 return -EINVAL;
6486 }
6487
6488 freq_len = nla_len(
6489 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6490 sizeof(uint32_t);
6491
6492 if (freq_len > QDF_MAX_NUM_CHAN) {
6493 hdd_err("insufficient space to hold channels");
6494 return -ENOMEM;
6495 }
6496
6497 hdd_debug("freq_len=%d", freq_len);
6498
6499 freq = nla_data(
6500 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6501
6502
6503 for (i = 0; i < freq_len; i++) {
6504 if (freq[i] == 0)
6505 chans[i] = 0;
6506 else
6507 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6508
6509 hdd_debug("freq[%d]=%d", i, freq[i]);
6510 }
6511
6512 /*
6513 * The input frequency list from user space is designed to be a
6514 * priority based frequency list. This is only to accommodate any
6515 * future request. But, current requirement is only to perform CAC
6516 * on a single channel. So, the first entry from the list is picked.
6517 *
6518 * If channel is zero, any channel in the available outdoor regulatory
6519 * domain will be selected.
6520 */
6521 ret = wlan_hdd_request_pre_cac(chans[0]);
6522 if (ret) {
6523 hdd_err("pre cac request failed with reason:%d", ret);
6524 return ret;
6525 }
6526
6527 return 0;
6528}
6529
6530/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006531 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6532 * @wiphy: Pointer to wireless phy
6533 * @wdev: Pointer to wireless device
6534 * @data: Pointer to data
6535 * @data_len: Data length
6536 *
6537 * This function is to process the p2p listen offload start vendor
6538 * command. It parses the input parameters and invoke WMA API to
6539 * send the command to firmware.
6540 *
6541 * Return: 0 on success, negative errno on failure
6542 */
6543static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6544 struct wireless_dev *wdev,
6545 const void *data,
6546 int data_len)
6547{
6548 int ret;
6549 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6550 struct net_device *dev = wdev->netdev;
6551 hdd_adapter_t *adapter;
6552 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6553 struct sir_p2p_lo_start params;
6554 QDF_STATUS status;
6555
6556 ENTER_DEV(dev);
6557
6558 ret = wlan_hdd_validate_context(hdd_ctx);
6559 if (ret)
6560 return ret;
6561
6562 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6563 hdd_err("Command not allowed in FTM mode");
6564 return -EPERM;
6565 }
6566
6567 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6568 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6569 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6570 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6571 hdd_err("Invalid device mode %d", adapter->device_mode);
6572 return -EINVAL;
6573 }
6574
6575 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6576 data, data_len, NULL)) {
6577 hdd_err("Invalid ATTR");
6578 return -EINVAL;
6579 }
6580
6581 memset(&params, 0, sizeof(params));
6582
6583 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6584 params.ctl_flags = 1; /* set to default value */
6585 else
6586 params.ctl_flags = nla_get_u32(tb
6587 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6588
6589 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6590 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6591 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6592 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6593 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6594 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6595 hdd_err("Attribute parsing failed");
6596 return -EINVAL;
6597 }
6598
6599 params.vdev_id = adapter->sessionId;
6600 params.freq = nla_get_u32(tb
6601 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6602 if ((params.freq != 2412) && (params.freq != 2437) &&
6603 (params.freq != 2462)) {
6604 hdd_err("Invalid listening channel: %d", params.freq);
6605 return -EINVAL;
6606 }
6607
6608 params.period = nla_get_u32(tb
6609 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6610 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6611 hdd_err("Invalid period: %d", params.period);
6612 return -EINVAL;
6613 }
6614
6615 params.interval = nla_get_u32(tb
6616 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6617 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6618 hdd_err("Invalid interval: %d", params.interval);
6619 return -EINVAL;
6620 }
6621
6622 params.count = nla_get_u32(tb
6623 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006624 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006625 hdd_err("Invalid count: %d", params.count);
6626 return -EINVAL;
6627 }
6628
6629 params.device_types = nla_data(tb
6630 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6631 if (params.device_types == NULL) {
6632 hdd_err("Invalid device types");
6633 return -EINVAL;
6634 }
6635
6636 params.dev_types_len = nla_len(tb
6637 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6638 if (params.dev_types_len < 8) {
6639 hdd_err("Invalid device type length: %d", params.dev_types_len);
6640 return -EINVAL;
6641 }
6642
6643 params.probe_resp_tmplt = nla_data(tb
6644 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6645 if (params.probe_resp_tmplt == NULL) {
6646 hdd_err("Invalid probe response template");
6647 return -EINVAL;
6648 }
6649
6650 params.probe_resp_len = nla_len(tb
6651 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6652 if (params.probe_resp_len == 0) {
6653 hdd_err("Invalid probe resp template length: %d",
6654 params.probe_resp_len);
6655 return -EINVAL;
6656 }
6657
6658 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6659 params.freq, params.period, params.interval, params.count);
6660
6661 status = wma_p2p_lo_start(&params);
6662
6663 if (!QDF_IS_STATUS_SUCCESS(status)) {
6664 hdd_err("P2P LO start failed");
6665 return -EINVAL;
6666 }
6667
6668 return 0;
6669}
6670
6671
6672/**
6673 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6674 * @wiphy: Pointer to wireless phy
6675 * @wdev: Pointer to wireless device
6676 * @data: Pointer to data
6677 * @data_len: Data length
6678 *
6679 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6680 * to process p2p listen offload start vendor command.
6681 *
6682 * Return: 0 on success, negative errno on failure
6683 */
6684static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6685 struct wireless_dev *wdev,
6686 const void *data,
6687 int data_len)
6688{
6689 int ret = 0;
6690
6691 cds_ssr_protect(__func__);
6692 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6693 data, data_len);
6694 cds_ssr_unprotect(__func__);
6695
6696 return ret;
6697}
6698
6699/**
6700 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6701 * @wiphy: Pointer to wireless phy
6702 * @wdev: Pointer to wireless device
6703 * @data: Pointer to data
6704 * @data_len: Data length
6705 *
6706 * This function is to process the p2p listen offload stop vendor
6707 * command. It invokes WMA API to send command to firmware.
6708 *
6709 * Return: 0 on success, negative errno on failure
6710 */
6711static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6712 struct wireless_dev *wdev,
6713 const void *data,
6714 int data_len)
6715{
6716 QDF_STATUS status;
6717 hdd_adapter_t *adapter;
6718 struct net_device *dev = wdev->netdev;
6719
6720 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6721 hdd_err("Command not allowed in FTM mode");
6722 return -EPERM;
6723 }
6724
6725 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6726 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6727 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6728 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6729 hdd_err("Invalid device mode");
6730 return -EINVAL;
6731 }
6732
6733 status = wma_p2p_lo_stop(adapter->sessionId);
6734
6735 if (!QDF_IS_STATUS_SUCCESS(status)) {
6736 hdd_err("P2P LO stop failed");
6737 return -EINVAL;
6738 }
6739
6740 return 0;
6741}
6742
6743/**
6744 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6745 * @wiphy: Pointer to wireless phy
6746 * @wdev: Pointer to wireless device
6747 * @data: Pointer to data
6748 * @data_len: Data length
6749 *
6750 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6751 * to process p2p listen offload stop vendor command.
6752 *
6753 * Return: 0 on success, negative errno on failure
6754 */
6755static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6756 struct wireless_dev *wdev,
6757 const void *data,
6758 int data_len)
6759{
6760 int ret = 0;
6761
6762 cds_ssr_protect(__func__);
6763 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6764 data, data_len);
6765 cds_ssr_unprotect(__func__);
6766
6767 return ret;
6768}
6769
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306770/**
6771 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6772 * @wiphy: Pointer to wireless phy
6773 * @wdev: Pointer to wireless device
6774 * @data: Pointer to data
6775 * @data_len: Data length
6776 *
6777 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6778 * to process the conditional channel switch request.
6779 *
6780 * Return: 0 on success, negative errno on failure
6781 */
6782static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6783 struct wireless_dev *wdev,
6784 const void *data,
6785 int data_len)
6786{
6787 int ret;
6788
6789 cds_ssr_protect(__func__);
6790 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6791 data, data_len);
6792 cds_ssr_unprotect(__func__);
6793
6794 return ret;
6795}
6796
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306797/*
6798 * define short names for the global vendor params
6799 * used by __wlan_hdd_cfg80211_bpf_offload()
6800 */
6801#define BPF_INVALID \
6802 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6803#define BPF_SET_RESET \
6804 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6805#define BPF_VERSION \
6806 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6807#define BPF_FILTER_ID \
6808 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6809#define BPF_PACKET_SIZE \
6810 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6811#define BPF_CURRENT_OFFSET \
6812 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6813#define BPF_PROGRAM \
6814 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6815#define BPF_MAX \
6816 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006817
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306818static const struct nla_policy
6819wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6820 [BPF_SET_RESET] = {.type = NLA_U32},
6821 [BPF_VERSION] = {.type = NLA_U32},
6822 [BPF_FILTER_ID] = {.type = NLA_U32},
6823 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6824 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6825 [BPF_PROGRAM] = {.type = NLA_U8},
6826};
6827
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006828struct bpf_offload_priv {
6829 struct sir_bpf_get_offload bpf_get_offload;
6830};
6831
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306832/**
6833 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006834 * @context: opaque context originally passed to SME. HDD always passes
6835 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306836 * @bpf_get_offload: struct for get offload
6837 *
6838 * This function receives the response/data from the lower layer and
6839 * checks to see if the thread is still waiting then post the results to
6840 * upper layer, if the request has timed out then ignore.
6841 *
6842 * Return: None
6843 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006844static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006845 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306846{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006847 struct hdd_request *request;
6848 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306849
6850 ENTER();
6851
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006852 request = hdd_request_get(context);
6853 if (!request) {
6854 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306855 return;
6856 }
6857
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006858 priv = hdd_request_priv(request);
6859 priv->bpf_get_offload = *data;
6860 hdd_request_complete(request);
6861 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306862}
6863
6864/**
6865 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6866 * @hdd_context: hdd_context
6867 * @bpf_get_offload: struct for get offload
6868 *
6869 * Return: 0 on success, error number otherwise.
6870 */
6871static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6872 struct sir_bpf_get_offload *bpf_get_offload)
6873{
6874 struct sk_buff *skb;
6875 uint32_t nl_buf_len;
6876
6877 ENTER();
6878
6879 nl_buf_len = NLMSG_HDRLEN;
6880 nl_buf_len +=
6881 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6882 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6883
6884 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6885 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006886 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306887 return -ENOMEM;
6888 }
6889
Jeff Johnson77848112016-06-29 14:52:06 -07006890 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306891 bpf_get_offload->bpf_version,
6892 bpf_get_offload->max_bytes_for_bpf_inst);
6893
6894 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6895 bpf_get_offload->max_bytes_for_bpf_inst) ||
6896 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006897 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306898 goto nla_put_failure;
6899 }
6900
6901 cfg80211_vendor_cmd_reply(skb);
6902 EXIT();
6903 return 0;
6904
6905nla_put_failure:
6906 kfree_skb(skb);
6907 return -EINVAL;
6908}
6909
6910/**
6911 * hdd_get_bpf_offload - Get BPF offload Capabilities
6912 * @hdd_ctx: Hdd context
6913 *
6914 * Return: 0 on success, errno on failure
6915 */
6916static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6917{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306918 QDF_STATUS status;
6919 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006920 void *cookie;
6921 struct hdd_request *request;
6922 struct bpf_offload_priv *priv;
6923 static const struct hdd_request_params params = {
6924 .priv_size = sizeof(*priv),
6925 .timeout_ms = WLAN_WAIT_TIME_BPF,
6926 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306927
6928 ENTER();
6929
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006930 request = hdd_request_alloc(&params);
6931 if (!request) {
6932 hdd_err("Unable to allocate request");
6933 return -EINVAL;
6934 }
6935 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306936
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006937 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6938 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006939 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306940 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006941 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006942 ret = qdf_status_to_os_return(status);
6943 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306944 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006945 ret = hdd_request_wait_for_response(request);
6946 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07006947 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006948 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306949 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006950 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306951 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006952 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306953 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006954 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306955
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006956cleanup:
6957 /*
6958 * either we never sent a request to SME, we sent a request to
6959 * SME and timed out, or we sent a request to SME, received a
6960 * response from SME, and posted the response to userspace.
6961 * regardless we are done with the request.
6962 */
6963 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306964 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006965
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306966 return ret;
6967}
6968
6969/**
6970 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6971 * @hdd_ctx: Hdd context
6972 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306973 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306974 *
6975 * Return: 0 on success; errno on failure
6976 */
6977static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6978 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306979 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306980{
6981 struct sir_bpf_set_offload *bpf_set_offload;
6982 QDF_STATUS status;
6983 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306984 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306985
6986 ENTER();
6987
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306988 if (adapter->device_mode == QDF_STA_MODE ||
6989 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6990 if (!hdd_conn_is_connected(
6991 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6992 hdd_err("Not in Connected state!");
6993 return -ENOTSUPP;
6994 }
6995 }
6996
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306997 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6998 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006999 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307000 return -ENOMEM;
7001 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307002
7003 /* Parse and fetch bpf packet size */
7004 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007005 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307006 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307007 goto fail;
7008 }
7009 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7010
7011 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07007012 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307013 goto post_sme;
7014 }
7015
7016 /* Parse and fetch bpf program */
7017 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007018 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307019 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307020 goto fail;
7021 }
7022
7023 prog_len = nla_len(tb[BPF_PROGRAM]);
7024 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307025
7026 if (bpf_set_offload->program == NULL) {
7027 hdd_err("qdf_mem_malloc failed for bpf offload program");
7028 ret = -ENOMEM;
7029 goto fail;
7030 }
7031
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307032 bpf_set_offload->current_length = prog_len;
7033 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307034 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307035
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307036 hdd_info("BPF set instructions");
7037 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
7038 bpf_set_offload->program, prog_len);
7039
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307040 /* Parse and fetch filter Id */
7041 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007042 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307043 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307044 goto fail;
7045 }
7046 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7047
7048 /* Parse and fetch current offset */
7049 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007050 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307051 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307052 goto fail;
7053 }
7054 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7055
7056post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07007057 hdd_notice("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 +05307058 bpf_set_offload->session_id,
7059 bpf_set_offload->version,
7060 bpf_set_offload->filter_id,
7061 bpf_set_offload->total_length,
7062 bpf_set_offload->current_length,
7063 bpf_set_offload->current_offset);
7064
7065 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7066 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007067 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307068 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307069 goto fail;
7070 }
7071 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307072
7073fail:
7074 if (bpf_set_offload->current_length)
7075 qdf_mem_free(bpf_set_offload->program);
7076 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307077 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307078}
7079
7080/**
7081 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7082 * @wiphy: wiphy structure pointer
7083 * @wdev: Wireless device structure pointer
7084 * @data: Pointer to the data received
7085 * @data_len: Length of @data
7086 *
7087 * Return: 0 on success; errno on failure
7088 */
7089static int
7090__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7091 struct wireless_dev *wdev,
7092 const void *data, int data_len)
7093{
7094 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7095 struct net_device *dev = wdev->netdev;
7096 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7097 struct nlattr *tb[BPF_MAX + 1];
7098 int ret_val, packet_filter_subcmd;
7099
7100 ENTER();
7101
7102 ret_val = wlan_hdd_validate_context(hdd_ctx);
7103 if (ret_val)
7104 return ret_val;
7105
7106 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007107 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307108 return -EINVAL;
7109 }
7110
7111 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007112 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307113 return -ENOTSUPP;
7114 }
7115
7116 if (nla_parse(tb, BPF_MAX, data, data_len,
7117 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007118 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307119 return -EINVAL;
7120 }
7121
7122 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007123 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307124 return -EINVAL;
7125 }
7126
7127 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7128
7129 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7130 return hdd_get_bpf_offload(hdd_ctx);
7131 else
7132 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307133 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307134}
7135
7136/**
7137 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7138 * @wiphy: wiphy structure pointer
7139 * @wdev: Wireless device structure pointer
7140 * @data: Pointer to the data received
7141 * @data_len: Length of @data
7142 *
7143 * Return: 0 on success; errno on failure
7144 */
7145
7146static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7147 struct wireless_dev *wdev,
7148 const void *data, int data_len)
7149{
7150 int ret;
7151
7152 cds_ssr_protect(__func__);
7153 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7154 cds_ssr_unprotect(__func__);
7155
7156 return ret;
7157}
7158
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307159/**
7160 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7161 * @pre_cac_adapter: AP adapter used for pre cac
7162 * @status: Status (true or false)
7163 * @handle: Global handle
7164 *
7165 * Sets the status of pre cac i.e., whether the pre cac is active or not
7166 *
7167 * Return: Zero on success, non-zero on failure
7168 */
7169static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7170 bool status, tHalHandle handle)
7171{
7172 QDF_STATUS ret;
7173
7174 ret = wlan_sap_set_pre_cac_status(
7175 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7176 if (QDF_IS_STATUS_ERROR(ret))
7177 return -EINVAL;
7178
7179 return 0;
7180}
7181
7182/**
7183 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7184 * @ap_adapter: AP adapter
7185 * @chan_before_pre_cac: Channel
7186 *
7187 * Saves the channel which the AP was beaconing on before moving to the pre
7188 * cac channel. If radar is detected on the pre cac channel, this saved
7189 * channel will be used for AP operations.
7190 *
7191 * Return: Zero on success, non-zero on failure
7192 */
7193static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7194 uint8_t chan_before_pre_cac)
7195{
7196 QDF_STATUS ret;
7197
7198 ret = wlan_sap_set_chan_before_pre_cac(
7199 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7200 if (QDF_IS_STATUS_ERROR(ret))
7201 return -EINVAL;
7202
7203 return 0;
7204}
7205
7206/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307207 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7208 * are in nol list from provided channel list
7209 * @adapter: AP adapter
7210 * @channel_count: channel count
7211 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307212 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307213 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307214 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307215static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7216 uint32_t *channel_count,
7217 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307218{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307219 uint8_t i, j;
7220 uint32_t nol_len = 0;
7221 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7222 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7223 uint32_t chan_count;
7224 bool found;
7225 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307226
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307227 if (!hdd_ctx) {
7228 hdd_err("hdd ctx not found");
7229 *channel_count = 0;
7230 return;
7231 }
7232
7233 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7234 hdd_err("invalid channel count %d", *channel_count);
7235 return;
7236 }
7237
7238 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7239 if (nol_len == 0)
7240 return;
7241
7242 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7243 chan_count = *channel_count;
7244 qdf_mem_zero(channel_list, chan_count);
7245 *channel_count = 0;
7246
7247 for (i = 0 ; i < chan_count; i++) {
7248 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7249 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7250 continue;
7251 found = false;
7252 for (j = 0; j < nol_len; j++) {
7253 if (tmp_chan_list[i] == nol[j]) {
7254 found = true;
7255 hdd_notice("skipped channel %d due to nol",
7256 nol[j]);
7257 break;
7258 }
7259 }
7260 if (!found) {
7261 channel_list[*channel_count] = tmp_chan_list[i];
7262 *channel_count = *channel_count + 1;
7263 }
7264 }
7265}
7266
7267int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7268 uint32_t *channel_count,
7269 uint8_t *channel_list)
7270{
7271 tsap_Config_t *sap_config;
7272
7273 sap_config = &adapter->sessionCtx.ap.sapConfig;
7274
7275 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7276 sap_config->acs_cfg.ch_list_count);
7277 *channel_count = sap_config->acs_cfg.ch_list_count;
7278 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7279
7280 if (*channel_count == 0) {
7281 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307282 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307283 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307284
7285 return 0;
7286}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307287
7288/**
7289 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7290 * @hdd_ctx: HDD context
7291 * @ap_adapter: AP adapter
7292 * @channel: Channel requested by userspace
7293 * @pre_cac_chan: Pointer to the pre CAC channel
7294 *
7295 * Validates the channel provided by userspace. If user provided channel 0,
7296 * a valid outdoor channel must be selected from the regulatory channel.
7297 *
7298 * Return: Zero on success and non zero value on error
7299 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007300static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7301 hdd_adapter_t *ap_adapter,
7302 uint8_t channel,
7303 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307304{
7305 uint32_t i, j;
7306 QDF_STATUS status;
7307 int ret;
7308 uint8_t nol[QDF_MAX_NUM_CHAN];
7309 uint32_t nol_len = 0, weight_len = 0;
7310 bool found;
7311 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7312 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7313 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7314
7315 if (0 == channel) {
7316 /* Channel is not obtained from PCL because PCL may not have
7317 * the entire channel list. For example: if SAP is up on
7318 * channel 6 and PCL is queried for the next SAP interface,
7319 * if SCC is preferred, the PCL will contain only the channel
7320 * 6. But, we are in need of a DFS channel. So, going with the
7321 * first channel from the valid channel list.
7322 */
7323 status = cds_get_valid_chans(channel_list, &len);
7324 if (QDF_IS_STATUS_ERROR(status)) {
7325 hdd_err("Failed to get channel list");
7326 return -EINVAL;
7327 }
7328 cds_update_with_safe_channel_list(channel_list, &len,
7329 pcl_weights, weight_len);
7330 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7331 for (i = 0; i < len; i++) {
7332 found = false;
7333 for (j = 0; j < nol_len; j++) {
7334 if (channel_list[i] == nol[j]) {
7335 found = true;
7336 break;
7337 }
7338 }
7339 if (found)
7340 continue;
7341 if (CDS_IS_DFS_CH(channel_list[i])) {
7342 *pre_cac_chan = channel_list[i];
7343 break;
7344 }
7345 }
7346 if (*pre_cac_chan == 0) {
7347 hdd_err("unable to find outdoor channel");
7348 return -EINVAL;
7349 }
7350 } else {
7351 /* Only when driver selects a channel, check is done for
7352 * unnsafe and NOL channels. When user provides a fixed channel
7353 * the user is expected to take care of this.
7354 */
7355 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7356 !CDS_IS_DFS_CH(channel)) {
7357 hdd_err("Invalid channel for pre cac:%d", channel);
7358 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307359 }
Jeff Johnson68755312017-02-10 11:46:55 -08007360
7361 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307362 }
7363 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
7364 return 0;
7365}
7366
7367/**
7368 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7369 * @channel: Channel option provided by userspace
7370 *
7371 * Sets the driver to the required hardware mode and start an adapater for
7372 * pre CAC which will mimic an AP.
7373 *
7374 * Return: Zero on success, non-zero value on error
7375 */
7376int wlan_hdd_request_pre_cac(uint8_t channel)
7377{
Krunal Sonib37bb352016-12-20 14:12:21 -08007378 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307379 hdd_context_t *hdd_ctx;
7380 int ret;
7381 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7382 hdd_ap_ctx_t *hdd_ap_ctx;
7383 QDF_STATUS status;
7384 struct wiphy *wiphy;
7385 struct net_device *dev;
7386 struct cfg80211_chan_def chandef;
7387 enum nl80211_channel_type channel_type;
7388 uint32_t freq;
7389 struct ieee80211_channel *chan;
7390 tHalHandle handle;
7391 bool val;
7392
7393 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7394 if (0 != wlan_hdd_validate_context(hdd_ctx))
7395 return -EINVAL;
7396
7397 if (cds_get_connection_count() > 1) {
7398 hdd_err("pre cac not allowed in concurrency");
7399 return -EINVAL;
7400 }
7401
7402 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7403 if (!ap_adapter) {
7404 hdd_err("unable to get SAP adapter");
7405 return -EINVAL;
7406 }
7407
7408 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7409 if (!handle) {
7410 hdd_err("Invalid handle");
7411 return -EINVAL;
7412 }
7413
7414 val = wlan_sap_is_pre_cac_active(handle);
7415 if (val) {
7416 hdd_err("pre cac is already in progress");
7417 return -EINVAL;
7418 }
7419
7420 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7421 if (!hdd_ap_ctx) {
7422 hdd_err("SAP context is NULL");
7423 return -EINVAL;
7424 }
7425
7426 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7427 hdd_err("SAP is already on DFS channel:%d",
7428 hdd_ap_ctx->operatingChannel);
7429 return -EINVAL;
7430 }
7431
7432 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7433 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7434 hdd_ap_ctx->operatingChannel);
7435 return -EINVAL;
7436 }
7437
Krunal Sonib37bb352016-12-20 14:12:21 -08007438 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7439 if (!mac_addr) {
7440 hdd_err("can't add virtual intf: Not getting valid mac addr");
7441 return -EINVAL;
7442 }
7443
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307444 hdd_info("channel:%d", channel);
7445
7446 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7447 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007448 if (ret != 0) {
7449 hdd_err("can't validate pre-cac channel");
7450 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307451 }
7452
7453 hdd_debug("starting pre cac SAP adapter");
7454
7455 /* Starting a SAP adapter:
7456 * Instead of opening an adapter, we could just do a SME open session
7457 * for AP type. But, start BSS would still need an adapter.
7458 * So, this option is not taken.
7459 *
7460 * hdd open adapter is going to register this precac interface with
7461 * user space. This interface though exposed to user space will be in
7462 * DOWN state. Consideration was done to avoid this registration to the
7463 * user space. But, as part of SAP operations multiple events are sent
7464 * to user space. Some of these events received from unregistered
7465 * interface was causing crashes. So, retaining the registration.
7466 *
7467 * So, this interface would remain registered and will remain in DOWN
7468 * state for the CAC duration. We will add notes in the feature
7469 * announcement to not use this temporary interface for any activity
7470 * from user space.
7471 */
7472 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007473 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307474 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307475 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007476 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307477 }
7478
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307479 /*
7480 * This interface is internally created by the driver. So, no interface
7481 * up comes for this interface from user space and hence starting
7482 * the adapter internally.
7483 */
7484 if (hdd_start_adapter(pre_cac_adapter)) {
7485 hdd_err("error starting the pre cac adapter");
7486 goto close_pre_cac_adapter;
7487 }
7488
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307489 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7490
7491 wiphy = hdd_ctx->wiphy;
7492 dev = pre_cac_adapter->dev;
7493
7494 /* Since this is only a dummy interface lets us use the IEs from the
7495 * other active SAP interface. In regular scenarios, these IEs would
7496 * come from the user space entity
7497 */
7498 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7499 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7500 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7501 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307502 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307503 }
7504 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7505 ap_adapter->sessionCtx.ap.beacon,
7506 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7507 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7508 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7509 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7510 ap_adapter->sessionCtx.ap.sapConfig.authType;
7511
7512 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7513 * to operate on the same bandwidth as that of the 2.4GHz operations.
7514 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7515 */
7516 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7517 case CH_WIDTH_20MHZ:
7518 channel_type = NL80211_CHAN_HT20;
7519 break;
7520 case CH_WIDTH_40MHZ:
7521 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7522 ap_adapter->sessionCtx.ap.sapConfig.channel)
7523 channel_type = NL80211_CHAN_HT40PLUS;
7524 else
7525 channel_type = NL80211_CHAN_HT40MINUS;
7526 break;
7527 default:
7528 channel_type = NL80211_CHAN_NO_HT;
7529 break;
7530 }
7531
7532 freq = cds_chan_to_freq(pre_cac_chan);
7533 chan = __ieee80211_get_channel(wiphy, freq);
7534 if (!chan) {
7535 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307536 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307537 }
7538
7539 cfg80211_chandef_create(&chandef, chan, channel_type);
7540
7541 hdd_debug("orig width:%d channel_type:%d freq:%d",
7542 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7543 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007544 /*
7545 * Doing update after opening and starting pre-cac adapter will make
7546 * sure that driver won't do hardware mode change if there are any
7547 * initial hick-ups or issues in pre-cac adapter's configuration.
7548 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7549 * connection update should result in DBS mode
7550 */
7551 status = cds_update_and_wait_for_connection_update(
7552 ap_adapter->sessionId,
7553 pre_cac_chan,
7554 SIR_UPDATE_REASON_PRE_CAC);
7555 if (QDF_IS_STATUS_ERROR(status)) {
7556 hdd_err("error in moving to DBS mode");
7557 goto stop_close_pre_cac_adapter;
7558 }
7559
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307560
7561 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7562 if (0 != ret) {
7563 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307564 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307565 }
7566
7567 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7568 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007569 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307570 if (QDF_IS_STATUS_ERROR(status)) {
7571 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307572 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307573 }
7574
7575 /*
7576 * The pre cac status is set here. But, it would not be reset explicitly
7577 * anywhere, since after the pre cac success/failure, the pre cac
7578 * adapter itself would be removed.
7579 */
7580 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7581 if (0 != ret) {
7582 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307583 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307584 }
7585
7586 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7587 hdd_ap_ctx->operatingChannel);
7588 if (0 != ret) {
7589 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307590 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307591 }
7592
7593 ap_adapter->pre_cac_chan = pre_cac_chan;
7594
7595 return 0;
7596
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307597stop_close_pre_cac_adapter:
7598 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307599 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7600 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307601close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307602 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007603release_intf_addr_and_return_failure:
7604 /*
7605 * Release the interface address as the adapter
7606 * failed to start, if you don't release then next
7607 * adapter which is trying to come wouldn't get valid
7608 * mac address. Remember we have limited pool of mac addresses
7609 */
7610 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307611 return -EINVAL;
7612}
7613
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307614static const struct nla_policy
7615wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7616 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7617};
7618
Agrawal Ashish65634612016-08-18 13:24:32 +05307619static const struct nla_policy
7620wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7621 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7622 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7623};
7624
7625/**
7626 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7627 * @wiphy: Pointer to wireless phy
7628 * @wdev: Pointer to wireless device
7629 * @data: Pointer to data
7630 * @data_len: Length of @data
7631 *
7632 * This function parses the incoming NL vendor command data attributes and
7633 * updates the SAP context about channel_hint and DFS mode.
7634 * If channel_hint is set, SAP will choose that channel
7635 * as operating channel.
7636 *
7637 * If DFS mode is enabled, driver will include DFS channels
7638 * in ACS else driver will skip DFS channels.
7639 *
7640 * Return: 0 on success, negative errno on failure
7641 */
7642static int
7643__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7644 struct wireless_dev *wdev,
7645 const void *data, int data_len)
7646{
7647 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7648 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7649 int ret;
7650 struct acs_dfs_policy *acs_policy;
7651 int mode = DFS_MODE_NONE;
7652 int channel_hint = 0;
7653
7654 ENTER_DEV(wdev->netdev);
7655
7656 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7657 hdd_err("Command not allowed in FTM mode");
7658 return -EINVAL;
7659 }
7660
7661 ret = wlan_hdd_validate_context(hdd_ctx);
7662 if (0 != ret)
7663 return ret;
7664
7665 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7666 data, data_len,
7667 wlan_hdd_set_acs_dfs_config_policy)) {
7668 hdd_err("invalid attr");
7669 return -EINVAL;
7670 }
7671
7672 acs_policy = &hdd_ctx->acs_policy;
7673 /*
7674 * SCM sends this attribute to restrict SAP from choosing
7675 * DFS channels from ACS.
7676 */
7677 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7678 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7679
7680 if (!IS_DFS_MODE_VALID(mode)) {
7681 hdd_err("attr acs dfs mode is not valid");
7682 return -EINVAL;
7683 }
7684 acs_policy->acs_dfs_mode = mode;
7685
7686 /*
7687 * SCM sends this attribute to provide an active channel,
7688 * to skip redundant ACS between drivers, and save driver start up time
7689 */
7690 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7691 channel_hint = nla_get_u8(
7692 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7693
7694 if (!IS_CHANNEL_VALID(channel_hint)) {
7695 hdd_err("acs channel is not valid");
7696 return -EINVAL;
7697 }
7698 acs_policy->acs_channel = channel_hint;
7699
7700 return 0;
7701}
7702
7703/**
7704 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7705 * @wiphy: wiphy structure pointer
7706 * @wdev: Wireless device structure pointer
7707 * @data: Pointer to the data received
7708 * @data_len: Length of @data
7709 *
7710 * This function parses the incoming NL vendor command data attributes and
7711 * updates the SAP context about channel_hint and DFS mode.
7712 *
7713 * Return: 0 on success; errno on failure
7714 */
7715static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7716 struct wireless_dev *wdev,
7717 const void *data, int data_len)
7718{
7719 int ret;
7720
7721 cds_ssr_protect(__func__);
7722 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7723 cds_ssr_unprotect(__func__);
7724
7725 return ret;
7726}
7727
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307728/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307729 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7730 * @mode : cfg80211 dfs mode
7731 *
7732 * Return: return csr sta roam dfs mode else return NONE
7733 */
7734static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7735 enum dfs_mode mode)
7736{
7737 switch (mode) {
7738 case DFS_MODE_ENABLE:
7739 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7740 break;
7741 case DFS_MODE_DISABLE:
7742 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7743 break;
7744 case DFS_MODE_DEPRIORITIZE:
7745 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7746 break;
7747 default:
7748 hdd_err("STA Roam policy dfs mode is NONE");
7749 return CSR_STA_ROAM_POLICY_NONE;
7750 }
7751}
7752
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307753/*
7754 * hdd_get_sap_operating_band: Get current operating channel
7755 * for sap.
7756 * @hdd_ctx: hdd context
7757 *
7758 * Return : Corresponding band for SAP operating channel
7759 */
7760uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7761{
7762 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7763 QDF_STATUS status;
7764 hdd_adapter_t *adapter;
7765 uint8_t operating_channel = 0;
7766 uint8_t sap_operating_band = 0;
7767 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7768 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7769 adapter = adapter_node->pAdapter;
7770
7771 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7772 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7773 &next);
7774 adapter_node = next;
7775 continue;
7776 }
7777 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7778 if (IS_24G_CH(operating_channel))
7779 sap_operating_band = eCSR_BAND_24;
7780 else if (IS_5G_CH(operating_channel))
7781 sap_operating_band = eCSR_BAND_5G;
7782 else
7783 sap_operating_band = eCSR_BAND_ALL;
7784 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7785 &next);
bings373b99b2017-01-23 10:35:08 +08007786 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307787 }
7788 return sap_operating_band;
7789}
7790
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307791static const struct nla_policy
7792wlan_hdd_set_sta_roam_config_policy[
7793QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7794 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7795 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7796};
7797
7798/**
7799 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7800 * for station connection or roaming.
7801 * @wiphy: Pointer to wireless phy
7802 * @wdev: Pointer to wireless device
7803 * @data: Pointer to data
7804 * @data_len: Length of @data
7805 *
7806 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7807 * channels needs to be skipped in scanning or not.
7808 * If dfs_mode is disabled, driver will not scan DFS channels.
7809 * If skip_unsafe_channels is set, driver will skip unsafe channels
7810 * in Scanning.
7811 *
7812 * Return: 0 on success, negative errno on failure
7813 */
7814static int
7815__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7816 struct wireless_dev *wdev,
7817 const void *data, int data_len)
7818{
7819 struct net_device *dev = wdev->netdev;
7820 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7821 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7822 struct nlattr *tb[
7823 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7824 int ret;
7825 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7826 enum dfs_mode mode = DFS_MODE_NONE;
7827 bool skip_unsafe_channels = false;
7828 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307829 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307830
7831 ENTER_DEV(dev);
7832
7833 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7834 hdd_err("Command not allowed in FTM mode");
7835 return -EINVAL;
7836 }
7837
7838 ret = wlan_hdd_validate_context(hdd_ctx);
7839 if (0 != ret)
7840 return ret;
7841 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7842 data, data_len,
7843 wlan_hdd_set_sta_roam_config_policy)) {
7844 hdd_err("invalid attr");
7845 return -EINVAL;
7846 }
7847 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7848 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7849 if (!IS_DFS_MODE_VALID(mode)) {
7850 hdd_err("attr sta roam dfs mode policy is not valid");
7851 return -EINVAL;
7852 }
7853
7854 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7855
7856 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7857 skip_unsafe_channels = nla_get_u8(
7858 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307859 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307860 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307861 skip_unsafe_channels, adapter->sessionId,
7862 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307863
7864 if (!QDF_IS_STATUS_SUCCESS(status)) {
7865 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7866 return -EINVAL;
7867 }
7868 return 0;
7869}
7870
7871/**
7872 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7873 * connection and roaming for station.
7874 * @wiphy: wiphy structure pointer
7875 * @wdev: Wireless device structure pointer
7876 * @data: Pointer to the data received
7877 * @data_len: Length of @data
7878 *
7879 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7880 * channels needs to be skipped in scanning or not.
7881 * If dfs_mode is disabled, driver will not scan DFS channels.
7882 * If skip_unsafe_channels is set, driver will skip unsafe channels
7883 * in Scanning.
7884 * Return: 0 on success; errno on failure
7885 */
7886static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7887 struct wireless_dev *wdev,
7888 const void *data, int data_len)
7889{
7890 int ret;
7891
7892 cds_ssr_protect(__func__);
7893 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7894 cds_ssr_unprotect(__func__);
7895
7896 return ret;
7897}
7898
Agrawal Ashish467dde42016-09-08 18:44:22 +05307899#ifdef FEATURE_WLAN_CH_AVOID
7900/**
7901 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7902 * is on unsafe channel.
7903 * @wiphy: wiphy structure pointer
7904 * @wdev: Wireless device structure pointer
7905 * @data: Pointer to the data received
7906 * @data_len: Length of @data
7907 *
7908 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7909 * on any of unsafe channels.
7910 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7911 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7912 *
7913 * Return: 0 on success; errno on failure
7914 */
7915static int
7916__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7917 struct wireless_dev *wdev,
7918 const void *data, int data_len)
7919{
7920 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7921 int ret;
7922 uint16_t unsafe_channel_count;
7923 int unsafe_channel_index;
7924 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7925
7926 ENTER_DEV(wdev->netdev);
7927
7928 if (!qdf_ctx) {
7929 cds_err("qdf_ctx is NULL");
7930 return -EINVAL;
7931 }
7932
7933 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7934 hdd_err("Command not allowed in FTM mode");
7935 return -EINVAL;
7936 }
7937
7938 ret = wlan_hdd_validate_context(hdd_ctx);
7939 if (0 != ret)
7940 return ret;
7941 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7942 &(hdd_ctx->unsafe_channel_count),
7943 sizeof(hdd_ctx->unsafe_channel_list));
7944
7945 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7946 (uint16_t)NUM_CHANNELS);
7947 for (unsafe_channel_index = 0;
7948 unsafe_channel_index < unsafe_channel_count;
7949 unsafe_channel_index++) {
7950 hdd_info("Channel %d is not safe",
7951 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7952 }
7953 hdd_unsafe_channel_restart_sap(hdd_ctx);
7954 return 0;
7955}
7956
7957/**
7958 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7959 * is on unsafe channel.
7960 * @wiphy: wiphy structure pointer
7961 * @wdev: Wireless device structure pointer
7962 * @data: Pointer to the data received
7963 * @data_len: Length of @data
7964 *
7965 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7966 * on any of unsafe channels.
7967 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7968 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7969 *
7970 * Return: 0 on success; errno on failure
7971 */
7972static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7973 struct wireless_dev *wdev,
7974 const void *data, int data_len)
7975{
7976 int ret;
7977
7978 cds_ssr_protect(__func__);
7979 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7980 cds_ssr_unprotect(__func__);
7981
7982 return ret;
7983}
7984
7985#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307986/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307987 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7988 * SAP is on unsafe channel.
7989 * @wiphy: wiphy structure pointer
7990 * @wdev: Wireless device structure pointer
7991 * @data: Pointer to the data received
7992 * @data_len: Length of @data
7993 *
7994 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7995 * driver.
7996 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7997 * will initiate restart of sap.
7998 *
7999 * Return: 0 on success; errno on failure
8000 */
8001static int
8002__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8003 struct wireless_dev *wdev,
8004 const void *data, int data_len)
8005{
8006 struct net_device *ndev = wdev->netdev;
8007 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8008 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8009 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8010 uint8_t config_channel = 0;
8011 hdd_ap_ctx_t *ap_ctx;
8012 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308013 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308014
8015 ENTER();
8016
8017 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008018 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308019 return -EINVAL;
8020 }
8021
8022 ret = wlan_hdd_validate_context(hdd_ctx);
8023 if (0 != ret)
8024 return -EINVAL;
8025
8026 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8027 data, data_len,
8028 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008029 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308030 return -EINVAL;
8031 }
8032
8033 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8034 if (!test_bit(SOFTAP_BSS_STARTED,
8035 &hostapd_adapter->event_flags)) {
8036 hdd_err("SAP is not started yet. Restart sap will be invalid");
8037 return -EINVAL;
8038 }
8039
8040 config_channel =
8041 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8042
8043 if (!((IS_24G_CH(config_channel)) ||
8044 (IS_5G_CH(config_channel)))) {
8045 hdd_err("Channel %d is not valid to restart SAP",
8046 config_channel);
8047 return -ENOTSUPP;
8048 }
8049
8050 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8051 ap_ctx->sapConfig.channel = config_channel;
8052 ap_ctx->sapConfig.ch_params.ch_width =
8053 ap_ctx->sapConfig.ch_width_orig;
8054
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008055 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308056 ap_ctx->sapConfig.sec_ch,
8057 &ap_ctx->sapConfig.ch_params);
8058
8059 cds_restart_sap(hostapd_adapter);
8060 }
8061
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308062 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8063 uint32_t freq_len, i;
8064 uint32_t *freq;
8065 uint8_t chans[QDF_MAX_NUM_CHAN];
8066
8067 hdd_debug("setting mandatory freq/chan list");
8068
8069 freq_len = nla_len(
8070 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8071 sizeof(uint32_t);
8072
8073 if (freq_len > QDF_MAX_NUM_CHAN) {
8074 hdd_err("insufficient space to hold channels");
8075 return -ENOMEM;
8076 }
8077
8078 freq = nla_data(
8079 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8080
8081 hdd_debug("freq_len=%d", freq_len);
8082
8083 for (i = 0; i < freq_len; i++) {
8084 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8085 hdd_debug("freq[%d]=%d", i, freq[i]);
8086 }
8087
8088 status = cds_set_sap_mandatory_channels(chans, freq_len);
8089 if (QDF_IS_STATUS_ERROR(status))
8090 return -EINVAL;
8091 }
8092
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308093 return 0;
8094}
8095
8096/**
8097 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8098 * @wiphy: wiphy structure pointer
8099 * @wdev: Wireless device structure pointer
8100 * @data: Pointer to the data received
8101 * @data_len: Length of @data
8102 *
8103 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8104 * driver.
8105 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8106 * will initiate restart of sap.
8107 *
8108 * Return: 0 on success; errno on failure
8109 */
8110static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8111 struct wireless_dev *wdev,
8112 const void *data, int data_len)
8113{
8114 int ret;
8115
8116 cds_ssr_protect(__func__);
8117 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8118 wdev, data, data_len);
8119 cds_ssr_unprotect(__func__);
8120
8121 return ret;
8122}
8123
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308124#undef BPF_INVALID
8125#undef BPF_SET_RESET
8126#undef BPF_VERSION
8127#undef BPF_ID
8128#undef BPF_PACKET_SIZE
8129#undef BPF_CURRENT_OFFSET
8130#undef BPF_PROGRAM
8131#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308132
8133/**
8134 * define short names for the global vendor params
8135 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8136 */
8137#define PARAM_TOTAL_CMD_EVENT_WAKE \
8138 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8139#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8140 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8141#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8142 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8143#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8144 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8145#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8146 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8147#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8148 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8149#define PARAM_TOTAL_RX_DATA_WAKE \
8150 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8151#define PARAM_RX_UNICAST_CNT \
8152 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8153#define PARAM_RX_MULTICAST_CNT \
8154 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8155#define PARAM_RX_BROADCAST_CNT \
8156 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8157#define PARAM_ICMP_PKT \
8158 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8159#define PARAM_ICMP6_PKT \
8160 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8161#define PARAM_ICMP6_RA \
8162 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8163#define PARAM_ICMP6_NA \
8164 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8165#define PARAM_ICMP6_NS \
8166 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8167#define PARAM_ICMP4_RX_MULTICAST_CNT \
8168 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8169#define PARAM_ICMP6_RX_MULTICAST_CNT \
8170 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8171#define PARAM_OTHER_RX_MULTICAST_CNT \
8172 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308173#define PARAM_RSSI_BREACH_CNT \
8174 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8175#define PARAM_LOW_RSSI_CNT \
8176 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8177#define PARAM_GSCAN_CNT \
8178 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8179#define PARAM_PNO_COMPLETE_CNT \
8180 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8181#define PARAM_PNO_MATCH_CNT \
8182 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8183
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308184
8185
8186/**
8187 * hdd_send_wakelock_stats() - API to send wakelock stats
8188 * @ctx: context to be passed to callback
8189 * @data: data passed to callback
8190 *
8191 * This function is used to send wake lock stats to HAL layer
8192 *
8193 * Return: 0 on success, error number otherwise.
8194 */
8195static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8196 const struct sir_wake_lock_stats *data)
8197{
8198 struct sk_buff *skb;
8199 uint32_t nl_buf_len;
8200 uint32_t total_rx_data_wake, rx_multicast_cnt;
8201 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308202 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308203
8204 ENTER();
8205
8206 nl_buf_len = NLMSG_HDRLEN;
8207 nl_buf_len +=
8208 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8209 (NLMSG_HDRLEN + sizeof(uint32_t));
8210
8211 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8212
8213 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008214 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308215 return -ENOMEM;
8216 }
8217
Jeff Johnson64943bd2016-08-23 13:14:06 -07008218 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308219 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008220 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308221 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008222 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308223 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008224 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308225 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008226 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308227 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008228 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308229 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008230 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308231 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008232 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
8233 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308234 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308235 hdd_info("wow_rssi_breach_wake_up_count %d",
8236 data->wow_rssi_breach_wake_up_count);
8237 hdd_info("wow_low_rssi_wake_up_count %d",
8238 data->wow_low_rssi_wake_up_count);
8239 hdd_info("wow_gscan_wake_up_count %d",
8240 data->wow_gscan_wake_up_count);
8241 hdd_info("wow_pno_complete_wake_up_count %d",
8242 data->wow_pno_complete_wake_up_count);
8243 hdd_info("wow_pno_match_wake_up_count %d",
8244 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308245
8246 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308247 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308248
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308249 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308250 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308251
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308252 rx_multicast_cnt =
8253 data->wow_ipv4_mcast_wake_up_count +
8254 ipv6_rx_multicast_addr_cnt;
8255
8256 total_rx_data_wake =
8257 data->wow_ucast_wake_up_count +
8258 data->wow_bcast_wake_up_count +
8259 rx_multicast_cnt;
8260
8261 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8262 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8263 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8264 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8265 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8266 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8267 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8268 total_rx_data_wake) ||
8269 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8270 data->wow_ucast_wake_up_count) ||
8271 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8272 rx_multicast_cnt) ||
8273 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8274 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308275 nla_put_u32(skb, PARAM_ICMP_PKT,
8276 data->wow_icmpv4_count) ||
8277 nla_put_u32(skb, PARAM_ICMP6_PKT,
8278 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308279 nla_put_u32(skb, PARAM_ICMP6_RA,
8280 data->wow_ipv6_mcast_ra_stats) ||
8281 nla_put_u32(skb, PARAM_ICMP6_NA,
8282 data->wow_ipv6_mcast_na_stats) ||
8283 nla_put_u32(skb, PARAM_ICMP6_NS,
8284 data->wow_ipv6_mcast_ns_stats) ||
8285 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8286 data->wow_ipv4_mcast_wake_up_count) ||
8287 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8288 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308289 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8290 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8291 data->wow_rssi_breach_wake_up_count) ||
8292 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8293 data->wow_low_rssi_wake_up_count) ||
8294 nla_put_u32(skb, PARAM_GSCAN_CNT,
8295 data->wow_gscan_wake_up_count) ||
8296 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8297 data->wow_pno_complete_wake_up_count) ||
8298 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8299 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008300 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308301 goto nla_put_failure;
8302 }
8303
8304 cfg80211_vendor_cmd_reply(skb);
8305
8306 EXIT();
8307 return 0;
8308
8309nla_put_failure:
8310 kfree_skb(skb);
8311 return -EINVAL;
8312}
8313
8314/**
8315 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8316 * @wiphy: wiphy pointer
8317 * @wdev: pointer to struct wireless_dev
8318 * @data: pointer to incoming NL vendor data
8319 * @data_len: length of @data
8320 *
8321 * This function parses the incoming NL vendor command data attributes and
8322 * invokes the SME Api and blocks on a completion variable.
8323 * WMA copies required data and invokes callback
8324 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8325 *
8326 * Return: 0 on success; error number otherwise.
8327 */
8328static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8329 struct wireless_dev *wdev,
8330 const void *data,
8331 int data_len)
8332{
8333 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8334 int status, ret;
8335 struct sir_wake_lock_stats wake_lock_stats;
8336 QDF_STATUS qdf_status;
8337
8338 ENTER();
8339
8340 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008341 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308342 return -EINVAL;
8343 }
8344
8345 status = wlan_hdd_validate_context(hdd_ctx);
8346 if (0 != status)
8347 return -EINVAL;
8348
8349 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8350 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008351 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308352 return -EINVAL;
8353 }
8354
8355 ret = hdd_send_wakelock_stats(hdd_ctx,
8356 &wake_lock_stats);
8357 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008358 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308359
8360 EXIT();
8361 return ret;
8362}
8363
8364/**
8365 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8366 * @wiphy: wiphy pointer
8367 * @wdev: pointer to struct wireless_dev
8368 * @data: pointer to incoming NL vendor data
8369 * @data_len: length of @data
8370 *
8371 * This function parses the incoming NL vendor command data attributes and
8372 * invokes the SME Api and blocks on a completion variable.
8373 * WMA copies required data and invokes callback
8374 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8375 *
8376 * Return: 0 on success; error number otherwise.
8377 */
8378static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8379 struct wireless_dev *wdev,
8380 const void *data, int data_len)
8381{
8382 int ret;
8383
8384 cds_ssr_protect(__func__);
8385 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8386 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008387 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308388
8389 return ret;
8390}
8391
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308392/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308393 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8394 * @wiphy: wiphy structure pointer
8395 * @wdev: Wireless device structure pointer
8396 * @data: Pointer to the data received
8397 * @data_len: Length of @data
8398 *
8399 * This function reads wmi max bus size and fill in the skb with
8400 * NL attributes and send up the NL event.
8401 * Return: 0 on success; errno on failure
8402 */
8403static int
8404__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8405 struct wireless_dev *wdev,
8406 const void *data, int data_len)
8407{
8408 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8409 int ret_val;
8410 struct sk_buff *skb;
8411 uint32_t nl_buf_len;
8412
8413 ENTER();
8414
8415 ret_val = wlan_hdd_validate_context(hdd_ctx);
8416 if (ret_val)
8417 return ret_val;
8418
8419 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8420 hdd_err("Command not allowed in FTM mode");
8421 return -EINVAL;
8422 }
8423
8424 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
8425
8426 nl_buf_len = NLMSG_HDRLEN;
8427 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8428
8429 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8430 if (!skb) {
8431 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8432 return -ENOMEM;
8433 }
8434
8435 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8436 hdd_ctx->wmi_max_len)) {
8437 hdd_err("nla put failure");
8438 goto nla_put_failure;
8439 }
8440
8441 cfg80211_vendor_cmd_reply(skb);
8442
8443 EXIT();
8444
8445 return 0;
8446
8447nla_put_failure:
8448 kfree_skb(skb);
8449 return -EINVAL;
8450}
8451
8452/**
8453 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8454 * @wiphy: wiphy structure pointer
8455 * @wdev: Wireless device structure pointer
8456 * @data: Pointer to the data received
8457 * @data_len: Length of @data
8458 *
8459 * Return: 0 on success; errno on failure
8460 */
8461static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8462 struct wireless_dev *wdev,
8463 const void *data, int data_len)
8464{
8465 int ret;
8466
8467 cds_ssr_protect(__func__);
8468 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8469 cds_ssr_unprotect(__func__);
8470
8471 return ret;
8472}
8473
8474/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308475 *__wlan_hdd_cfg80211_setband() - set band
8476 * @wiphy: Pointer to wireless phy
8477 * @wdev: Pointer to wireless device
8478 * @data: Pointer to data
8479 * @data_len: Length of @data
8480 *
8481 * Return: 0 on success, negative errno on failure
8482 */
8483static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8484 struct wireless_dev *wdev,
8485 const void *data, int data_len)
8486{
8487 struct net_device *dev = wdev->netdev;
8488 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8489 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8490 int ret;
8491 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8492 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8493
8494 ENTER();
8495
8496 ret = wlan_hdd_validate_context(hdd_ctx);
8497 if (ret)
8498 return ret;
8499
8500 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8501 hdd_err(FL("Invalid ATTR"));
8502 return -EINVAL;
8503 }
8504
8505 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8506 hdd_err(FL("attr SETBAND_VALUE failed"));
8507 return -EINVAL;
8508 }
8509
8510 ret = hdd_set_band(dev,
8511 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8512
8513 EXIT();
8514 return ret;
8515}
8516
8517/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308518 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8519 * @adapter: hdd adapter
8520 * @channel: channel number
8521 *
8522 * return: QDF status based on success or failure
8523 */
8524static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8525 int channel, int chan_bw)
8526{
8527 if (QDF_STATUS_SUCCESS !=
8528 wlan_hdd_validate_operation_channel(adapter, channel))
8529 return QDF_STATUS_E_FAILURE;
8530 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8531 channel,
8532 PHY_SINGLE_CHANNEL_CENTERED))) {
8533 hdd_notice("channel %d is in nol", channel);
8534 return -EINVAL;
8535 }
8536
8537 if ((wlansap_is_channel_leaking_in_nol(
8538 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8539 channel, chan_bw))) {
8540 hdd_notice("channel %d is leaking in nol", channel);
8541 return -EINVAL;
8542 }
8543
8544 return 0;
8545
8546}
8547
Kapil Gupta8878ad92017-02-13 11:56:04 +05308548static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8549 tsap_Config_t *sap_config,
8550 struct hdd_vendor_chan_info *channel_list)
8551{
8552 sap_config->channel = channel_list->pri_ch;
8553
8554 sap_config->ch_params.center_freq_seg0 =
8555 channel_list->vht_seg0_center_ch;
8556 sap_config->ch_params.center_freq_seg1 =
8557 channel_list->vht_seg1_center_ch;
8558
8559 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8560 sap_config->ch_params.ch_width = channel_list->chan_width;
8561 if (sap_config->channel >= 36)
8562 sap_config->ch_width_orig =
8563 hdd_ctx->config->vhtChannelWidth;
8564 else
8565 sap_config->ch_width_orig =
8566 hdd_ctx->config->nChannelBondingMode24GHz ?
8567 eHT_CHANNEL_WIDTH_40MHZ :
8568 eHT_CHANNEL_WIDTH_20MHZ;
8569
8570 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8571 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8572 sap_config->acs_cfg.vht_seg0_center_ch =
8573 channel_list->vht_seg0_center_ch;
8574 sap_config->acs_cfg.vht_seg1_center_ch =
8575 channel_list->vht_seg1_center_ch;
8576 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8577}
8578
8579static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8580 uint8_t channel_cnt,
8581 struct hdd_vendor_chan_info *channel_list)
8582{
8583 tsap_Config_t *sap_config;
8584 hdd_ap_ctx_t *hdd_ap_ctx;
8585 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8586 QDF_STATUS status = QDF_STATUS_SUCCESS;
8587
8588 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8589 sap_config = &adapter->sessionCtx.ap.sapConfig;
8590
8591 if (QDF_TIMER_STATE_RUNNING ==
8592 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8593 ap.vendor_acs_timer)) {
8594 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8595 }
8596
8597 if (channel_list && channel_list->pri_ch == 0) {
8598 /* Check mode, set default channel */
8599 channel_list->pri_ch = 6;
8600 /*
8601 * sap_select_default_oper_chan(hdd_ctx->hHal,
8602 * sap_config->acs_cfg.hw_mode);
8603 */
8604 }
8605
8606 switch (reason) {
8607 /* SAP init case */
8608 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8609 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8610 /* Update Hostapd */
8611 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8612 break;
8613
8614 /* DFS detected on current channel */
8615 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8616 wlan_sap_update_next_channel(
8617 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8618 channel_list->pri_ch,
8619 channel_list->chan_width);
8620 status = sme_update_new_channel_event(
8621 WLAN_HDD_GET_HAL_CTX(adapter),
8622 adapter->sessionId);
8623 break;
8624
8625 /* LTE coex event on current channel */
8626 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8627 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8628 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8629 hdd_ap_ctx->sapConfig.ch_width_orig =
8630 channel_list->chan_width;
8631 hdd_restart_sap(adapter, sap_config->acs_cfg.pri_ch);
8632 break;
8633
8634 default:
8635 hdd_info("invalid reason for timer invoke");
8636 }
8637 qdf_mem_free(channel_list);
8638 EXIT();
8639 return status;
8640}
8641
8642/**
8643 * Define short name for vendor channel set config
8644 */
8645#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8646#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8647#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8648#define SET_CHAN_PRIMARY_CHANNEL \
8649 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8650#define SET_CHAN_SECONDARY_CHANNEL \
8651 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8652#define SET_CHAN_SEG0_CENTER_CHANNEL \
8653 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8654#define SET_CHAN_SEG1_CENTER_CHANNEL \
8655 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8656#define SET_CHAN_CHANNEL_WIDTH \
8657 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8658#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8659
8660/**
8661 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8662 * @channel_list: pointer to hdd_vendor_chan_info
8663 * @reason: channel change reason
8664 * @channel_cnt: channel count
8665 * @data: data
8666 * @data_len: data len
8667 *
8668 * Return: 0 on success, negative errno on failure
8669 */
8670static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8671 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8672 const void *data, int data_len)
8673{
8674 int rem, i = 0;
8675 struct nlattr *tb[SET_CHAN_MAX + 1];
8676 struct nlattr *tb2[SET_CHAN_MAX + 1];
8677 struct nlattr *curr_attr;
8678 struct hdd_vendor_chan_info *channel_list;
8679
8680 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8681 hdd_err("Invalid ATTR");
8682 return -EINVAL;
8683 }
8684
8685 if (tb[SET_CHAN_REASON])
8686 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8687
8688 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8689 *channel_cnt = nla_get_u8(tb[
8690 SET_CHAN_CHANNEL_COUNT]);
8691 hdd_info("channel count %d", *channel_cnt);
8692 }
8693
8694 if (!(*channel_cnt)) {
8695 hdd_err("channel count is %d", *channel_cnt);
8696 return -EINVAL;
8697 }
8698
8699 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8700 (*channel_cnt));
8701
8702 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8703 if (nla_parse(tb2,
8704 SET_CHAN_MAX,
8705 nla_data(curr_attr), nla_len(curr_attr),
8706 NULL)) {
8707 hdd_err("nla_parse failed");
8708 return -EINVAL;
8709 }
8710 /* Parse and Fetch allowed SSID list*/
8711 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8712 channel_list[i].pri_ch =
8713 nla_get_u8(
8714 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8715 }
8716 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8717 channel_list[i].ht_sec_ch =
8718 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8719 }
8720 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8721 channel_list[i].vht_seg0_center_ch =
8722 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8723 }
8724 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8725 channel_list[i].vht_seg1_center_ch =
8726 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8727 }
8728 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8729 channel_list[i].chan_width =
8730 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8731 }
8732 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8733 i, channel_list[i].pri_ch,
8734 channel_list[i].ht_sec_ch,
8735 channel_list[i].vht_seg0_center_ch,
8736 channel_list[i].vht_seg1_center_ch,
8737 channel_list[i].chan_width);
8738 i++;
8739 if (i > *channel_cnt)
8740 break;
8741 }
8742 *chan_list_ptr = channel_list;
8743
8744 return 0;
8745}
8746
8747/**
8748 * Undef short names for vendor set channel configuration
8749 */
8750#undef SET_CHAN_REASON
8751#undef SET_CHAN_CHANNEL_COUNT
8752#undef SET_CHAN_CHAN_LIST
8753#undef SET_CHAN_PRIMARY_CHANNEL
8754#undef SET_CHAN_SECONDARY_CHANNEL
8755#undef SET_CHAN_SEG0_CENTER_CHANNEL
8756#undef SET_CHAN_SEG1_CENTER_CHANNEL
8757#undef SET_CHAN_CHANNEL_WIDTH
8758#undef SET_CHAN_MAX
8759
8760/**
8761 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8762 * @wiphy: Pointer to wireless phy
8763 * @wdev: Pointer to wireless device
8764 * @data: Pointer to data
8765 * @data_len: Length of @data
8766 *
8767 * Return: 0 on success, negative errno on failure
8768 */
8769static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8770 struct wireless_dev *wdev,
8771 const void *data, int data_len)
8772{
8773 int ret_val;
8774 QDF_STATUS qdf_status;
8775 uint8_t channel_cnt = 0, reason = -1;
8776 struct hdd_vendor_chan_info *channel_list = NULL;
8777 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8778 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8779
8780 ENTER();
8781
8782 ret_val = wlan_hdd_validate_context(hdd_ctx);
8783 if (ret_val)
8784 return ret_val;
8785
8786 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8787 hdd_err("Command not allowed in FTM mode");
8788 return -EINVAL;
8789 }
8790
8791 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8792 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8793 else {
8794 hdd_err("already timeout happened for acs");
8795 return -EINVAL;
8796 }
8797
8798 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8799 &channel_cnt, data, data_len);
8800 if (ret_val)
8801 return ret_val;
8802
8803 /* Validate channel to be set */
8804 while (channel_cnt && channel_list) {
8805 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8806 channel_list->pri_ch,
8807 channel_list->chan_width);
8808 if (qdf_status == QDF_STATUS_SUCCESS)
8809 break;
8810 channel_cnt--;
8811 channel_list++;
8812 }
8813 if ((channel_cnt <= 0) || !channel_list) {
8814 hdd_err("no available channel/chanlist %p", channel_list);
8815 return -EINVAL;
8816 }
8817
8818 qdf_status = hdd_update_acs_channel(adapter, reason,
8819 channel_cnt, channel_list);
8820 return qdf_status_to_os_return(qdf_status);
8821}
8822
8823/**
8824 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8825 * @wiphy: Pointer to wireless phy
8826 * @wdev: Pointer to wireless device
8827 * @data: Pointer to data
8828 * @data_len: Length of @data
8829 *
8830 * Return: 0 on success, negative errno on failure
8831 */
8832static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8833 struct wireless_dev *wdev,
8834 const void *data, int data_len)
8835{
8836 int ret;
8837
8838 cds_ssr_protect(__func__);
8839 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8840 data_len);
8841 cds_ssr_protect(__func__);
8842
8843 return ret;
8844}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308845
8846/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308847 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8848 * @wiphy: wiphy structure pointer
8849 * @wdev: Wireless device structure pointer
8850 * @data: Pointer to the data received
8851 * @data_len: Length of @data
8852 *
8853 * Return: 0 on success; errno on failure
8854 */
8855static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8856 struct wireless_dev *wdev,
8857 const void *data, int data_len)
8858{
8859 int ret;
8860
8861 cds_ssr_protect(__func__);
8862 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8863 cds_ssr_unprotect(__func__);
8864
8865 return ret;
8866}
8867
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008868/**
8869 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8870 * @nl80211_value: Vendor command attribute value
8871 * @wmi_value: Pointer to return converted WMI return value
8872 *
8873 * Convert NL80211 vendor command value for SAR limit set to WMI value
8874 * Return: 0 on success, -1 on invalid value
8875 */
8876static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8877 u32 *wmi_value)
8878{
8879 int ret = 0;
8880
8881 switch (nl80211_value) {
8882 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8883 *wmi_value = WMI_SAR_FEATURE_OFF;
8884 break;
8885 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8886 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8887 break;
8888 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8889 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8890 break;
8891 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8892 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8893 break;
8894 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8895 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8896 break;
8897 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8898 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8899 break;
8900 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8901 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8902 break;
8903 default:
8904 ret = -1;
8905 }
8906 return ret;
8907}
8908
8909/**
8910 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8911 * @nl80211_value: Vendor command attribute value
8912 * @wmi_value: Pointer to return converted WMI return value
8913 *
8914 * Convert NL80211 vendor command value for SAR BAND to WMI value
8915 * Return: 0 on success, -1 on invalid value
8916 */
8917static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8918{
8919 int ret = 0;
8920
8921 switch (nl80211_value) {
8922 case NL80211_BAND_2GHZ:
8923 *wmi_value = WMI_SAR_2G_ID;
8924 break;
8925 case NL80211_BAND_5GHZ:
8926 *wmi_value = WMI_SAR_5G_ID;
8927 break;
8928 default:
8929 ret = -1;
8930 }
8931 return ret;
8932}
8933
8934/**
8935 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8936 * @nl80211_value: Vendor command attribute value
8937 * @wmi_value: Pointer to return converted WMI return value
8938 *
8939 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8940 * Return: 0 on success, -1 on invalid value
8941 */
8942static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8943 u32 *wmi_value)
8944{
8945 int ret = 0;
8946
8947 switch (nl80211_value) {
8948 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8949 *wmi_value = WMI_SAR_MOD_CCK;
8950 break;
8951 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8952 *wmi_value = WMI_SAR_MOD_OFDM;
8953 break;
8954 default:
8955 ret = -1;
8956 }
8957 return ret;
8958}
8959
8960
8961/**
8962 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
8963 * @wiphy: Pointer to wireless phy
8964 * @wdev: Pointer to wireless device
8965 * @data: Pointer to data
8966 * @data_len: Length of @data
8967 *
8968 * This function is used to setup Specific Absorption Rate limit specs.
8969 *
8970 * Return: 0 on success, negative errno on failure
8971 */
8972static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
8973 struct wireless_dev *wdev,
8974 const void *data, int data_len)
8975{
8976 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8977 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8978 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8979 *sar_spec_list;
8980 struct sar_limit_cmd_params sar_limit_cmd = {0};
8981 int ret = -EINVAL, i = 0, rem = 0;
8982
8983 ENTER();
8984
8985 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8986 hdd_err("Command not allowed in FTM mode");
8987 return -EPERM;
8988 }
8989
8990 if (wlan_hdd_validate_context(hdd_ctx))
8991 return -EINVAL;
8992
8993 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
8994 data, data_len, NULL)) {
8995 hdd_err("Invalid SAR attributes");
8996 return -EINVAL;
8997 }
8998
8999 /* Vendor command manadates all SAR Specs in single call */
9000 sar_limit_cmd.commit_limits = 1;
9001 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9002 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9003 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9004 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9005 &sar_limit_cmd.sar_enable) < 0) {
9006 hdd_err("Invalid SAR Enable attr");
9007 goto fail;
9008 }
9009 }
9010 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
9011
9012 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9013 sar_limit_cmd.num_limit_rows = nla_get_u32(
9014 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
9015 hdd_info("attr sar num_limit_rows %d",
9016 sar_limit_cmd.num_limit_rows);
9017 }
9018 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9019 hdd_err("SAR Spec list exceed supported size");
9020 goto fail;
9021 }
9022 if (sar_limit_cmd.num_limit_rows == 0)
9023 goto send_sar_limits;
9024 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9025 struct sar_limit_cmd_row) *
9026 sar_limit_cmd.num_limit_rows);
9027 if (!sar_limit_cmd.sar_limit_row_list) {
9028 ret = -ENOMEM;
9029 goto fail;
9030 }
9031 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9032 hdd_err("Invalid SAR SPECs list");
9033 goto fail;
9034 }
9035
9036 nla_for_each_nested(sar_spec_list,
9037 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9038 if (i == sar_limit_cmd.num_limit_rows) {
9039 hdd_warn("SAR Cmd has excess SPECs in list");
9040 break;
9041 }
9042
9043 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9044 nla_data(sar_spec_list), nla_len(sar_spec_list),
9045 NULL)) {
9046 hdd_err("nla_parse failed for SAR Spec list");
9047 goto fail;
9048 }
9049 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9050 if (sar_spec[
9051 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9052 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9053 nla_get_u32(sar_spec[
9054 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9055 } else {
9056 hdd_err("SAR Spec does not have power limit value");
9057 goto fail;
9058 }
9059
9060 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9061 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9062 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9063 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9064 < 0) {
9065 hdd_err("Invalid SAR Band attr");
9066 goto fail;
9067 }
9068 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9069 WMI_SAR_BAND_ID_VALID_MASK;
9070 }
9071 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9072 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9073 nla_get_u32(sar_spec[
9074 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9075 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9076 WMI_SAR_CHAIN_ID_VALID_MASK;
9077 }
9078 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9079 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9080 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9081 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9082 < 0) {
9083 hdd_err("Invalid SAR Modulation attr");
9084 goto fail;
9085 }
9086 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9087 WMI_SAR_MOD_ID_VALID_MASK;
9088 }
9089 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
9090 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9091 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9092 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9093 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9094 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9095 i++;
9096 }
9097
9098 if (i < sar_limit_cmd.num_limit_rows) {
9099 hdd_warn("SAR Cmd has less SPECs in list");
9100 sar_limit_cmd.num_limit_rows = i;
9101 }
9102
9103send_sar_limits:
9104 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9105 QDF_STATUS_SUCCESS)
9106 ret = 0;
9107fail:
9108 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9109 return ret;
9110}
9111
9112/**
9113 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9114 * @wiphy: Pointer to wireless phy
9115 * @wdev: Pointer to wireless device
9116 * @data: Pointer to data
9117 * @data_len: Length of @data
9118 *
9119 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9120 *
9121 * Return: 0 on success, negative errno on failure
9122 */
9123static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9124 struct wireless_dev *wdev,
9125 const void *data,
9126 int data_len)
9127{
9128 int ret;
9129
9130 cds_ssr_protect(__func__);
9131 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9132 data_len);
9133 cds_ssr_unprotect(__func__);
9134
9135 return ret;
9136}
9137
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309138static const struct
9139nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9140 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9141 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9142 .len = QDF_MAC_ADDR_SIZE},
9143};
9144
9145/**
9146 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9147 * @wiphy: Pointer to wireless phy
9148 * @wdev: Pointer to wireless device
9149 * @data: Pointer to data
9150 * @data_len: Length of @data
9151 *
9152 * This function is used to enable/disable roaming using vendor commands
9153 *
9154 * Return: 0 on success, negative errno on failure
9155 */
9156static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9157 struct wireless_dev *wdev,
9158 const void *data, int data_len)
9159{
9160 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9161 struct net_device *dev = wdev->netdev;
9162 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9163 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9164 uint32_t is_fast_roam_enabled;
9165 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309166 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309167
9168 ENTER_DEV(dev);
9169
9170 ret = wlan_hdd_validate_context(hdd_ctx);
9171 if (0 != ret)
9172 return ret;
9173
9174 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9175 hdd_err("Command not allowed in FTM mode");
9176 return -EINVAL;
9177 }
9178
9179 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9180 qca_wlan_vendor_attr);
9181 if (ret) {
9182 hdd_err("Invalid ATTR");
9183 return -EINVAL;
9184 }
9185
9186 /* Parse and fetch Enable flag */
9187 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9188 hdd_err("attr enable failed");
9189 return -EINVAL;
9190 }
9191
9192 is_fast_roam_enabled = nla_get_u32(
9193 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009194 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
9195 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309196
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009197 if (!adapter->fast_roaming_allowed) {
9198 hdd_err("fast roaming not allowed on %s interface",
9199 adapter->dev->name);
9200 return -EINVAL;
9201 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309202 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309203 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009204 (is_fast_roam_enabled &&
9205 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309206 if (qdf_status != QDF_STATUS_SUCCESS)
9207 hdd_err("sme_config_fast_roaming failed with status=%d",
9208 qdf_status);
9209 ret = qdf_status_to_os_return(qdf_status);
9210
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309211 EXIT();
9212 return ret;
9213}
9214
9215/**
9216 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9217 * @wiphy: Pointer to wireless phy
9218 * @wdev: Pointer to wireless device
9219 * @data: Pointer to data
9220 * @data_len: Length of @data
9221 *
9222 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9223 *
9224 * Return: 0 on success, negative errno on failure
9225 */
9226static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9227 struct wireless_dev *wdev,
9228 const void *data, int data_len)
9229{
9230 int ret;
9231
9232 cds_ssr_protect(__func__);
9233 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9234 cds_ssr_unprotect(__func__);
9235
9236 return ret;
9237}
9238
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309239static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9240 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9241 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9242 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9243 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9244};
9245
9246/**
9247 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9248 * @wiphy: Pointer to wireless phy
9249 * @wdev: Pointer to wireless device
9250 * @data: Pointer to data
9251 * @data_len: Length of @data
9252 *
9253 * Return: 0 on success, negative errno on failure
9254 */
9255static int
9256__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9257 struct wireless_dev *wdev,
9258 const void *data,
9259 int data_len)
9260{
9261 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9262 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9263 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9264 struct nlattr *apth;
9265 int rem;
9266 int ret = 1;
9267 int print_idx = -1;
9268 int module_id = -1;
9269 int bit_mask = -1;
9270 int status;
9271
9272 ENTER();
9273
9274 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9275 hdd_err("Command not allowed in FTM mode");
9276 return -EINVAL;
9277 }
9278
9279 ret = wlan_hdd_validate_context(hdd_ctx);
9280 if (ret != 0)
9281 return -EINVAL;
9282
9283 print_idx = qdf_get_pidx();
9284 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9285 hdd_err("Invalid print controle object index");
9286 return -EINVAL;
9287 }
9288
9289 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9290 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9291 hdd_err("Invalid attr");
9292 return -EINVAL;
9293 }
9294
9295 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9296 hdd_err("attr trace level param failed");
9297 return -EINVAL;
9298 }
9299
9300 nla_for_each_nested(apth,
9301 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9302 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9303 nla_data(apth), nla_len(apth), NULL)) {
9304 hdd_err("Invalid attr");
9305 return -EINVAL;
9306 }
9307
9308 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9309 hdd_err("attr Module ID failed");
9310 return -EINVAL;
9311 }
9312 module_id = nla_get_u32
9313 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9314
9315 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9316 hdd_err("attr Verbose mask failed");
9317 return -EINVAL;
9318 }
9319 bit_mask = nla_get_u32
9320 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9321
9322 status = hdd_qdf_trace_enable(module_id, bit_mask);
9323
9324 if (status != 0)
9325 hdd_err("can not set verbose mask %d for the category %d",
9326 bit_mask, module_id);
9327 }
9328
9329 EXIT();
9330 return ret;
9331}
9332
9333/**
9334 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9335 * @wiphy: Pointer to wireless phy
9336 * @wdev: Pointer to wireless device
9337 * @data: Pointer to data
9338 * @data_len: Length of @data
9339 *
9340 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9341 *
9342 * Return: 0 on success, negative errno on failure
9343 */
9344
9345static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9346 struct wireless_dev *wdev,
9347 const void *data,
9348 int data_len)
9349{
9350 int ret;
9351
9352 cds_ssr_protect(__func__);
9353 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9354 cds_ssr_unprotect(__func__);
9355
9356 return ret;
9357}
9358
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009359const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9360 {
9361 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9362 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9363 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309364 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009365 .doit = is_driver_dfs_capable
9366 },
9367
9368#ifdef WLAN_FEATURE_NAN
9369 {
9370 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9371 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9372 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9373 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9374 .doit = wlan_hdd_cfg80211_nan_request
9375 },
9376#endif
9377
9378#ifdef WLAN_FEATURE_STATS_EXT
9379 {
9380 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9381 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9382 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9383 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9384 .doit = wlan_hdd_cfg80211_stats_ext_request
9385 },
9386#endif
9387#ifdef FEATURE_WLAN_EXTSCAN
9388 {
9389 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9390 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9391 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9392 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9393 .doit = wlan_hdd_cfg80211_extscan_start
9394 },
9395 {
9396 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9397 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9398 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9399 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9400 .doit = wlan_hdd_cfg80211_extscan_stop
9401 },
9402 {
9403 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9404 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9405 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9406 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9407 },
9408 {
9409 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9410 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9411 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9412 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9413 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9414 },
9415 {
9416 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9417 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9418 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9419 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9420 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9421 },
9422 {
9423 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9424 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9425 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9426 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9427 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9428 },
9429 {
9430 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9431 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9432 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9433 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9434 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9435 },
9436 {
9437 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9438 .info.subcmd =
9439 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9440 .flags =
9441 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9442 WIPHY_VENDOR_CMD_NEED_RUNNING,
9443 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9444 },
9445 {
9446 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9447 .info.subcmd =
9448 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9449 .flags =
9450 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9451 WIPHY_VENDOR_CMD_NEED_RUNNING,
9452 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9453 },
9454 {
9455 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9456 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9457 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9458 WIPHY_VENDOR_CMD_NEED_NETDEV |
9459 WIPHY_VENDOR_CMD_NEED_RUNNING,
9460 .doit = wlan_hdd_cfg80211_set_epno_list
9461 },
9462#endif /* FEATURE_WLAN_EXTSCAN */
9463
9464#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9465 {
9466 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9467 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9468 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9469 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9470 .doit = wlan_hdd_cfg80211_ll_stats_clear
9471 },
9472
9473 {
9474 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9475 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9476 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9477 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9478 .doit = wlan_hdd_cfg80211_ll_stats_set
9479 },
9480
9481 {
9482 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9483 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9484 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9485 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9486 .doit = wlan_hdd_cfg80211_ll_stats_get
9487 },
9488#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9489#ifdef FEATURE_WLAN_TDLS
9490 {
9491 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9492 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9493 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9494 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9495 .doit = wlan_hdd_cfg80211_exttdls_enable
9496 },
9497 {
9498 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9499 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9500 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9501 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9502 .doit = wlan_hdd_cfg80211_exttdls_disable
9503 },
9504 {
9505 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9506 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9507 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9508 .doit = wlan_hdd_cfg80211_exttdls_get_status
9509 },
9510#endif
9511 {
9512 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9513 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9514 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9515 .doit = wlan_hdd_cfg80211_get_supported_features
9516 },
9517 {
9518 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9519 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9520 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9521 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9522 },
9523 {
9524 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9525 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9526 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309527 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009528 },
9529 {
9530 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9531 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9532 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9533 WIPHY_VENDOR_CMD_NEED_NETDEV,
9534 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9535 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009536 {
9537 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9538 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9539 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9540 WIPHY_VENDOR_CMD_NEED_NETDEV,
9541 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9542 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009543 {
9544 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309545 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9546 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9547 WIPHY_VENDOR_CMD_NEED_NETDEV |
9548 WIPHY_VENDOR_CMD_NEED_RUNNING,
9549 .doit = hdd_cfg80211_get_station_cmd
9550 },
9551 {
9552 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009553 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9554 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9555 WIPHY_VENDOR_CMD_NEED_NETDEV |
9556 WIPHY_VENDOR_CMD_NEED_RUNNING,
9557 .doit = wlan_hdd_cfg80211_do_acs
9558 },
9559
9560 {
9561 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9562 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9563 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9564 WIPHY_VENDOR_CMD_NEED_NETDEV,
9565 .doit = wlan_hdd_cfg80211_get_features
9566 },
9567#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9568 {
9569 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9570 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9571 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9572 WIPHY_VENDOR_CMD_NEED_NETDEV |
9573 WIPHY_VENDOR_CMD_NEED_RUNNING,
9574 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9575 },
9576#endif
9577#ifdef FEATURE_WLAN_EXTSCAN
9578 {
9579 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9580 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9581 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9582 WIPHY_VENDOR_CMD_NEED_NETDEV |
9583 WIPHY_VENDOR_CMD_NEED_RUNNING,
9584 .doit = wlan_hdd_cfg80211_set_passpoint_list
9585 },
9586 {
9587 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9588 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9589 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9590 WIPHY_VENDOR_CMD_NEED_NETDEV |
9591 WIPHY_VENDOR_CMD_NEED_RUNNING,
9592 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9593 },
9594 {
9595 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9596 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
9597 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9598 WIPHY_VENDOR_CMD_NEED_NETDEV |
9599 WIPHY_VENDOR_CMD_NEED_RUNNING,
9600 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
9601 },
9602 {
9603 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9604 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
9605 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9606 WIPHY_VENDOR_CMD_NEED_NETDEV |
9607 WIPHY_VENDOR_CMD_NEED_RUNNING,
9608 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
9609 },
9610#endif /* FEATURE_WLAN_EXTSCAN */
9611 {
9612 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9613 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9614 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9615 WIPHY_VENDOR_CMD_NEED_NETDEV,
9616 .doit = wlan_hdd_cfg80211_get_wifi_info
9617 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009618#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009619 {
9620 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9621 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9622 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9623 WIPHY_VENDOR_CMD_NEED_NETDEV |
9624 WIPHY_VENDOR_CMD_NEED_RUNNING,
9625 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9626 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009627#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009628 {
9629 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9630 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9631 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9632 WIPHY_VENDOR_CMD_NEED_NETDEV,
9633 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9634 },
9635 {
9636 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9637 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9638 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9639 WIPHY_VENDOR_CMD_NEED_NETDEV,
9640 .doit = wlan_hdd_cfg80211_wifi_logger_start
9641 },
9642 {
9643 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9644 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9645 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9646 WIPHY_VENDOR_CMD_NEED_NETDEV,
9647 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9648 },
9649 {
9650 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9651 .info.subcmd =
9652 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9653 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9654 WIPHY_VENDOR_CMD_NEED_NETDEV |
9655 WIPHY_VENDOR_CMD_NEED_RUNNING,
9656 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9657 },
9658 {
9659 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9660 .info.subcmd =
9661 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9662 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9663 WIPHY_VENDOR_CMD_NEED_NETDEV |
9664 WIPHY_VENDOR_CMD_NEED_RUNNING,
9665 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9666 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009667#ifdef WLAN_FEATURE_TSF
9668 {
9669 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9670 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9671 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9672 WIPHY_VENDOR_CMD_NEED_NETDEV |
9673 WIPHY_VENDOR_CMD_NEED_RUNNING,
9674 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9675 },
9676#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009677#ifdef FEATURE_WLAN_TDLS
9678 {
9679 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9680 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9681 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9682 WIPHY_VENDOR_CMD_NEED_NETDEV |
9683 WIPHY_VENDOR_CMD_NEED_RUNNING,
9684 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9685 },
9686#endif
9687#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9688 {
9689 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9690 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9691 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9692 WIPHY_VENDOR_CMD_NEED_NETDEV |
9693 WIPHY_VENDOR_CMD_NEED_RUNNING,
9694 .doit = wlan_hdd_cfg80211_offloaded_packets
9695 },
9696#endif
9697 {
9698 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9699 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9700 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9701 WIPHY_VENDOR_CMD_NEED_NETDEV |
9702 WIPHY_VENDOR_CMD_NEED_RUNNING,
9703 .doit = wlan_hdd_cfg80211_monitor_rssi
9704 },
9705 {
9706 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309707 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9708 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9709 WIPHY_VENDOR_CMD_NEED_NETDEV |
9710 WIPHY_VENDOR_CMD_NEED_RUNNING,
9711 .doit = wlan_hdd_cfg80211_set_ns_offload
9712 },
9713 {
9714 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009715 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9716 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9717 WIPHY_VENDOR_CMD_NEED_NETDEV |
9718 WIPHY_VENDOR_CMD_NEED_RUNNING,
9719 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9720 },
9721#ifdef WLAN_FEATURE_MEMDUMP
9722 {
9723 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9724 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9725 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9726 WIPHY_VENDOR_CMD_NEED_NETDEV |
9727 WIPHY_VENDOR_CMD_NEED_RUNNING,
9728 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9729 },
9730#endif /* WLAN_FEATURE_MEMDUMP */
9731 {
9732 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9733 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9734 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9735 WIPHY_VENDOR_CMD_NEED_NETDEV |
9736 WIPHY_VENDOR_CMD_NEED_RUNNING,
9737 .doit = wlan_hdd_cfg80211_vendor_scan
9738 },
9739
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309740 /* Vendor abort scan */
9741 {
9742 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9743 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9744 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9745 WIPHY_VENDOR_CMD_NEED_NETDEV |
9746 WIPHY_VENDOR_CMD_NEED_RUNNING,
9747 .doit = wlan_hdd_vendor_abort_scan
9748 },
9749
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009750 /* OCB commands */
9751 {
9752 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9753 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9754 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9755 WIPHY_VENDOR_CMD_NEED_NETDEV |
9756 WIPHY_VENDOR_CMD_NEED_RUNNING,
9757 .doit = wlan_hdd_cfg80211_ocb_set_config
9758 },
9759 {
9760 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9761 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9762 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9763 WIPHY_VENDOR_CMD_NEED_NETDEV |
9764 WIPHY_VENDOR_CMD_NEED_RUNNING,
9765 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9766 },
9767 {
9768 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9769 .info.subcmd =
9770 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9771 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9772 WIPHY_VENDOR_CMD_NEED_NETDEV |
9773 WIPHY_VENDOR_CMD_NEED_RUNNING,
9774 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9775 },
9776 {
9777 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9778 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9779 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9780 WIPHY_VENDOR_CMD_NEED_NETDEV |
9781 WIPHY_VENDOR_CMD_NEED_RUNNING,
9782 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9783 },
9784 {
9785 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9786 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9787 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9788 WIPHY_VENDOR_CMD_NEED_NETDEV |
9789 WIPHY_VENDOR_CMD_NEED_RUNNING,
9790 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9791 },
9792 {
9793 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9794 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9795 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9796 WIPHY_VENDOR_CMD_NEED_NETDEV |
9797 WIPHY_VENDOR_CMD_NEED_RUNNING,
9798 .doit = wlan_hdd_cfg80211_dcc_get_stats
9799 },
9800 {
9801 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9802 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9803 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9804 WIPHY_VENDOR_CMD_NEED_NETDEV |
9805 WIPHY_VENDOR_CMD_NEED_RUNNING,
9806 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9807 },
9808 {
9809 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9810 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9811 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9812 WIPHY_VENDOR_CMD_NEED_NETDEV |
9813 WIPHY_VENDOR_CMD_NEED_RUNNING,
9814 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9815 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309816 {
9817 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9818 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9819 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9820 WIPHY_VENDOR_CMD_NEED_NETDEV |
9821 WIPHY_VENDOR_CMD_NEED_RUNNING,
9822 .doit = wlan_hdd_cfg80211_get_link_properties
9823 },
Peng Xu278d0122015-09-24 16:34:17 -07009824 {
Peng Xud2220962016-07-11 17:59:17 -07009825 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009826 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9827 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9828 WIPHY_VENDOR_CMD_NEED_NETDEV |
9829 WIPHY_VENDOR_CMD_NEED_RUNNING,
9830 .doit = wlan_hdd_cfg80211_set_ota_test
9831 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009832#ifdef FEATURE_LFR_SUBNET_DETECTION
9833 {
9834 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9835 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9836 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9837 WIPHY_VENDOR_CMD_NEED_NETDEV |
9838 WIPHY_VENDOR_CMD_NEED_RUNNING,
9839 .doit = wlan_hdd_cfg80211_set_gateway_params
9840 },
9841#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009842 {
Peng Xud2220962016-07-11 17:59:17 -07009843 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009844 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9845 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9846 WIPHY_VENDOR_CMD_NEED_NETDEV |
9847 WIPHY_VENDOR_CMD_NEED_RUNNING,
9848 .doit = wlan_hdd_cfg80211_txpower_scale
9849 },
9850 {
9851 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9852 .info.subcmd =
9853 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9854 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9855 WIPHY_VENDOR_CMD_NEED_NETDEV |
9856 WIPHY_VENDOR_CMD_NEED_RUNNING,
9857 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9858 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309859 {
9860 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9861 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9862 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9863 WIPHY_VENDOR_CMD_NEED_NETDEV |
9864 WIPHY_VENDOR_CMD_NEED_RUNNING,
9865 .doit = wlan_hdd_cfg80211_bpf_offload
9866 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309867 {
9868 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309869 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9870 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9871 WIPHY_VENDOR_CMD_NEED_NETDEV |
9872 WIPHY_VENDOR_CMD_NEED_RUNNING,
9873 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9874 },
9875 {
9876 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309877 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9878 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9879 WIPHY_VENDOR_CMD_NEED_NETDEV |
9880 WIPHY_VENDOR_CMD_NEED_RUNNING,
9881 .doit = wlan_hdd_cfg80211_sta_roam_policy
9882 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309883#ifdef FEATURE_WLAN_CH_AVOID
9884 {
9885 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9886 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9887 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9888 WIPHY_VENDOR_CMD_NEED_NETDEV |
9889 WIPHY_VENDOR_CMD_NEED_RUNNING,
9890 .doit = wlan_hdd_cfg80211_avoid_freq
9891 },
9892#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309893 {
9894 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309895 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9896 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9897 WIPHY_VENDOR_CMD_NEED_NETDEV |
9898 WIPHY_VENDOR_CMD_NEED_RUNNING,
9899 .doit = wlan_hdd_cfg80211_sap_configuration_set
9900 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009901 {
Peng Xu4225c152016-07-14 21:18:14 -07009902 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009903 .info.subcmd =
9904 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9905 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9906 WIPHY_VENDOR_CMD_NEED_NETDEV |
9907 WIPHY_VENDOR_CMD_NEED_RUNNING,
9908 .doit = wlan_hdd_cfg80211_p2p_lo_start
9909 },
9910 {
9911 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9912 .info.subcmd =
9913 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9914 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9915 WIPHY_VENDOR_CMD_NEED_NETDEV |
9916 WIPHY_VENDOR_CMD_NEED_RUNNING,
9917 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9918 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309919 {
9920 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9921 .info.subcmd =
9922 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9923 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9924 WIPHY_VENDOR_CMD_NEED_NETDEV |
9925 WIPHY_VENDOR_CMD_NEED_RUNNING,
9926 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9927 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009928#ifdef WLAN_FEATURE_NAN_DATAPATH
9929 {
9930 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9931 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9932 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9933 WIPHY_VENDOR_CMD_NEED_NETDEV |
9934 WIPHY_VENDOR_CMD_NEED_RUNNING,
9935 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9936 },
9937#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309938 {
9939 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9940 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9941 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9942 WIPHY_VENDOR_CMD_NEED_NETDEV |
9943 WIPHY_VENDOR_CMD_NEED_RUNNING,
9944 .doit = wlan_hdd_cfg80211_get_wakelock_stats
9945 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309946 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309947 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9948 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
9949 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9950 WIPHY_VENDOR_CMD_NEED_NETDEV |
9951 WIPHY_VENDOR_CMD_NEED_RUNNING,
9952 .doit = wlan_hdd_cfg80211_get_bus_size
9953 },
9954 {
Kapil Gupta8878ad92017-02-13 11:56:04 +05309955 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9956 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
9957 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9958 WIPHY_VENDOR_CMD_NEED_NETDEV |
9959 WIPHY_VENDOR_CMD_NEED_RUNNING,
9960 .doit = wlan_hdd_cfg80211_update_vendor_channel
9961 },
9962 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309963 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
9964 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9965 WIPHY_VENDOR_CMD_NEED_NETDEV |
9966 WIPHY_VENDOR_CMD_NEED_RUNNING,
9967 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309968 },
9969 {
9970 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9971 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
9972 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9973 WIPHY_VENDOR_CMD_NEED_NETDEV |
9974 WIPHY_VENDOR_CMD_NEED_RUNNING,
9975 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05309976 },
9977#ifdef WLAN_FEATURE_DISA
9978 {
9979 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9980 .info.subcmd =
9981 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
9982 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9983 WIPHY_VENDOR_CMD_NEED_NETDEV |
9984 WIPHY_VENDOR_CMD_NEED_RUNNING,
9985 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
9986 },
9987#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07009988#ifdef FEATURE_WLAN_TDLS
9989 {
9990 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9991 .info.subcmd =
9992 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
9993 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9994 WIPHY_VENDOR_CMD_NEED_NETDEV |
9995 WIPHY_VENDOR_CMD_NEED_RUNNING,
9996 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009997 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -07009998#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009999 {
10000 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10001 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10002 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10003 WIPHY_VENDOR_CMD_NEED_RUNNING,
10004 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10005 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010006 {
10007 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10008 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10009 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10010 WIPHY_VENDOR_CMD_NEED_NETDEV |
10011 WIPHY_VENDOR_CMD_NEED_RUNNING,
10012 .doit = wlan_hdd_cfg80211_set_trace_level
10013 },
10014
Paul Zhang3a210c52016-12-08 10:18:12 +080010015#ifdef WLAN_UMAC_CONVERGENCE
10016 COMMON_VENDOR_COMMANDS
10017#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010018};
10019
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010020#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10021 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10022 defined(FEATURE_WLAN_SCAN_PNO)
10023/**
10024 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10025 * @wiphy: pointer to wiphy
10026 * @config: pointer to config
10027 *
10028 * Return: None
10029 */
10030static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10031 struct hdd_config *config)
10032{
10033 if (config->configPNOScanSupport) {
10034 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10035 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
10036 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
10037 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
10038 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
10039 if (config->max_sched_scan_plan_interval)
10040 wiphy->max_sched_scan_plan_interval =
10041 config->max_sched_scan_plan_interval;
10042 if (config->max_sched_scan_plan_iterations)
10043 wiphy->max_sched_scan_plan_iterations =
10044 config->max_sched_scan_plan_iterations;
10045 }
10046}
10047#else
10048static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10049 struct hdd_config *config)
10050{
10051}
10052#endif
10053
10054
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010055/**
10056 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10057 * @priv_size: Size of the hdd context.
10058 *
10059 * Allocate wiphy context and hdd context.
10060 *
10061 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010062 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010063hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010064{
10065 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010066 hdd_context_t *hdd_ctx;
10067
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010068 ENTER();
10069
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010070 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10071
10072 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010073 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010074 return NULL;
10075 }
10076
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010077 hdd_ctx = wiphy_priv(wiphy);
10078
10079 hdd_ctx->wiphy = wiphy;
10080
10081 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010082}
10083
10084/*
10085 * FUNCTION: wlan_hdd_cfg80211_update_band
10086 * This function is called from the supplicant through a
10087 * private ioctl to change the band value
10088 */
10089int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10090{
10091 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010092 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010093
10094 ENTER();
10095
Dustin Browna30892e2016-10-12 17:28:36 -070010096 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010097
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010098 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010099 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010100
10101 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10102 struct ieee80211_supported_band *band = wiphy->bands[i];
10103
10104 channelEnabledState =
10105 cds_get_channel_state(band->channels[j].
10106 hw_value);
10107
Dustin Browna30892e2016-10-12 17:28:36 -070010108 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010109 /* 5G only */
10110#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10111 /* Enable Social channels for P2P */
10112 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10113 (band->channels[j].center_freq)
10114 && CHANNEL_STATE_ENABLE ==
10115 channelEnabledState)
10116 band->channels[j].flags &=
10117 ~IEEE80211_CHAN_DISABLED;
10118 else
10119#endif
10120 band->channels[j].flags |=
10121 IEEE80211_CHAN_DISABLED;
10122 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010123 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010124 eCSR_BAND_24 == eBand) {
10125 /* 2G only */
10126 band->channels[j].flags |=
10127 IEEE80211_CHAN_DISABLED;
10128 continue;
10129 }
10130
Amar Singhal6842e8f2016-02-23 16:30:32 -080010131 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010132 band->channels[j].flags &=
10133 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010134 }
10135 }
10136 return 0;
10137}
10138
Peng Xuacfdda12017-02-06 16:15:38 -080010139#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010140/*
10141 * FUNCTION: wlan_hdd_cfg80211_init
10142 * This function is called by hdd_wlan_startup()
10143 * during initialization.
10144 * This function is used to initialize and register wiphy structure.
10145 */
10146int wlan_hdd_cfg80211_init(struct device *dev,
10147 struct wiphy *wiphy, struct hdd_config *pCfg)
10148{
10149 int i, j;
10150 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10151
10152 ENTER();
10153
10154 /* Now bind the underlying wlan device with wiphy */
10155 set_wiphy_dev(wiphy, dev);
10156
10157 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10158
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010159#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10160 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010161 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010162#else
10163 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010164 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010165#endif
10166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010167 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10168 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10169 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10170#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10171 | WIPHY_FLAG_4ADDR_STATION
10172#endif
10173 | WIPHY_FLAG_OFFCHAN_TX;
10174
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010175#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10176 wiphy->wowlan = &wowlan_support_cfg80211_init;
10177#else
10178 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10179 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10180 wiphy->wowlan.pattern_min_len = 1;
10181 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10182#endif
10183
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010184 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010185#ifdef FEATURE_WLAN_ESE
10186 || pCfg->isEseIniFeatureEnabled
10187#endif
10188 ) {
10189 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10190 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010191#ifdef FEATURE_WLAN_TDLS
10192 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10193 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10194#endif
10195
10196 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10197
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010198#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10199 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10200#endif
10201
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010202 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010203
10204#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010205 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010206#endif
10207
10208 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010209 * driver can still register regulatory callback and
10210 * it will get regulatory settings in wiphy->band[], but
10211 * driver need to determine what to do with both
10212 * regulatory settings
10213 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010214
10215 wiphy->reg_notifier = hdd_reg_notifier;
10216
10217#if defined QCA_WIFI_FTM
10218}
10219#endif
10220
10221 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10222
10223 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10224
10225 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10226
Arun Khandavallifae92942016-08-01 13:31:08 +053010227 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10228 | BIT(NL80211_IFTYPE_ADHOC)
10229 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10230 | BIT(NL80211_IFTYPE_P2P_GO)
10231 | BIT(NL80211_IFTYPE_AP)
10232 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010233
Arun Khandavallifae92942016-08-01 13:31:08 +053010234 if (pCfg->advertiseConcurrentOperation) {
10235 if (pCfg->enableMCC) {
10236 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010237
Arun Khandavallifae92942016-08-01 13:31:08 +053010238 for (i = 0;
10239 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10240 i++) {
10241 if (!pCfg->allowMCCGODiffBI)
10242 wlan_hdd_iface_combination[i].
10243 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010244 }
10245 }
10246 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010247 ARRAY_SIZE(wlan_hdd_iface_combination);
10248 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010249 }
10250
10251 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010252 * on ini values
10253 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010254 if (!pCfg->ShortGI20MhzEnable) {
10255 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10256 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010257 }
10258
10259 if (!pCfg->ShortGI40MhzEnable) {
10260 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10261 }
10262
10263 if (!pCfg->nChannelBondingMode5GHz) {
10264 wlan_hdd_band_5_ghz.ht_cap.cap &=
10265 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10266 }
10267
Abhishek Singhf512bf32016-05-04 16:47:46 +053010268 /*
10269 * In case of static linked driver at the time of driver unload,
10270 * module exit doesn't happens. Module cleanup helps in cleaning
10271 * of static memory.
10272 * If driver load happens statically, at the time of driver unload,
10273 * wiphy flags don't get reset because of static memory.
10274 * It's better not to store channel in static memory.
10275 */
Dustin Browna30892e2016-10-12 17:28:36 -070010276 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10277 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010278 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010279 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010280 hdd_err("Not enough memory to allocate channels");
10281 return -ENOMEM;
10282 }
Dustin Browna30892e2016-10-12 17:28:36 -070010283 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010284 &hdd_channels_2_4_ghz[0],
10285 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010286 if ((hdd_is_5g_supported(pHddCtx)) &&
10287 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10288 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10289 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10290 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010291 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10292 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010293 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010294 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010295 hdd_err("Not enough memory to allocate channels");
10296 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010297 bands[NL80211_BAND_2GHZ]->channels);
10298 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010299 return -ENOMEM;
10300 }
Dustin Browna30892e2016-10-12 17:28:36 -070010301 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010302 &hdd_channels_5_ghz[0],
10303 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010304 }
10305
Dustin Browna30892e2016-10-12 17:28:36 -070010306 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010307
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010308 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010309 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010310
10311 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10312 struct ieee80211_supported_band *band = wiphy->bands[i];
10313
Dustin Browna30892e2016-10-12 17:28:36 -070010314 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010315 eCSR_BAND_5G == pCfg->nBandCapability) {
10316 /* 5G only */
10317#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10318 /* Enable social channels for P2P */
10319 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10320 (band->channels[j].center_freq))
10321 band->channels[j].flags &=
10322 ~IEEE80211_CHAN_DISABLED;
10323 else
10324#endif
10325 band->channels[j].flags |=
10326 IEEE80211_CHAN_DISABLED;
10327 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010328 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010329 eCSR_BAND_24 == pCfg->nBandCapability) {
10330 /* 2G only */
10331 band->channels[j].flags |=
10332 IEEE80211_CHAN_DISABLED;
10333 continue;
10334 }
10335 }
10336 }
10337 /*Initialise the supported cipher suite details */
10338 wiphy->cipher_suites = hdd_cipher_suites;
10339 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10340
10341 /*signal strength in mBm (100*dBm) */
10342 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10343 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10344
Anurag Chouhan6d760662016-02-20 16:05:43 +053010345 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010346 wiphy->n_vendor_commands =
10347 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10348 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10349
10350 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10351 wiphy->n_vendor_events =
10352 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10353 }
10354
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010355 if (pCfg->enableDFSMasterCap) {
10356 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10357 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010358
10359 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10360
10361#ifdef QCA_HT_2040_COEX
10362 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10363#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010364 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010365
10366#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10367 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10368 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10369 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10370 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10371#endif
10372
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010373 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010374 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010376 EXIT();
10377 return 0;
10378}
10379
Abhishek Singhf512bf32016-05-04 16:47:46 +053010380/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010381 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10382 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010383 *
10384 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010385 * memory allocated in wlan_hdd_cfg80211_init also
10386 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010387 *
10388 * Return: void
10389 */
10390void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10391{
10392 int i;
10393
Dustin Browna30892e2016-10-12 17:28:36 -070010394 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010395 if (NULL != wiphy->bands[i] &&
10396 (NULL != wiphy->bands[i]->channels)) {
10397 qdf_mem_free(wiphy->bands[i]->channels);
10398 wiphy->bands[i]->channels = NULL;
10399 }
10400 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010401 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010402}
10403
Yingying Tang80e15f32016-09-27 18:23:01 +080010404/**
10405 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10406 * @hdd_ctx: HDD context
10407 *
10408 * this function will update capabilities for supported bands
10409 *
10410 * Return: void
10411 */
10412static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10413{
10414 uint32_t val32;
10415 uint16_t val16;
10416 tSirMacHTCapabilityInfo *ht_cap_info;
10417 QDF_STATUS status;
10418
10419 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10420 if (QDF_STATUS_SUCCESS != status) {
10421 hdd_err("could not get HT capability info");
10422 val32 = 0;
10423 }
10424 val16 = (uint16_t)val32;
10425 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10426
10427 if (ht_cap_info->txSTBC == true) {
10428 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10429 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10430 IEEE80211_HT_CAP_TX_STBC;
10431 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10432 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10433 IEEE80211_HT_CAP_TX_STBC;
10434 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010435
10436 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10437 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10438 vht_cap.vht_supported = 0;
10439 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10440 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10441 vht_cap.vht_supported = 0;
10442 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10443 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010444}
10445
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010446/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010447 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010448 * initialization. In wlan_hdd_cfg80211_init, only the
10449 * default values will be initialized. The final initialization
10450 * of all required members can be done here.
10451 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010452void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010453{
Yingying Tang80e15f32016-09-27 18:23:01 +080010454 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10455
10456 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010457}
10458
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010459/**
10460 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10461 * @cfg: hdd cfg
10462 *
10463 * this function update 11n mode in hdd cfg
10464 *
10465 * Return: void
10466 */
10467void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10468{
10469 if (sme_is_feature_supported_by_fw(DOT11AC)) {
10470 hdd_notice("support 11ac");
10471 } else {
10472 hdd_notice("not support 11ac");
10473 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10474 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10475 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10476 cfg->sap_p2p_11ac_override = 0;
10477 }
10478 }
10479}
10480
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010481/* In this function we are registering wiphy. */
10482int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10483{
10484 ENTER();
10485 /* Register our wiphy dev with cfg80211 */
10486 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010487 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010488 return -EIO;
10489 }
10490
10491 EXIT();
10492 return 0;
10493}
10494
10495/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010496 * HDD function to update wiphy capability based on target offload status.
10497 *
10498 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10499 * capability even before downloading firmware to the target. In discrete
10500 * case, host will get know certain offload capability (say sched_scan
10501 * caps) only after downloading firmware to the target and target boots up.
10502 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10503 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010504 */
10505void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10506{
10507#ifdef FEATURE_WLAN_SCAN_PNO
10508 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10509 struct hdd_config *pCfg = pHddCtx->config;
10510
10511 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10512 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010513 * have PNO support.
10514 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010515 if (!pCfg->PnoOffload) {
10516 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10517 wiphy->max_sched_scan_ssids = 0;
10518 wiphy->max_match_sets = 0;
10519 wiphy->max_sched_scan_ie_len = 0;
10520 }
10521#endif
10522}
10523
10524/* This function registers for all frame which supplicant is interested in */
10525void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10526{
10527 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10528 /* Register for all P2P action, public action etc frames */
10529 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10530
10531 ENTER();
10532
Abhishek Singh7996eb72015-12-30 17:24:02 +053010533 /* Register frame indication call back */
10534 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10535
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010536 /* Register for p2p ack indication */
10537 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10538
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010539 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010540 * initialized. Once we will move to 2.6.37 kernel, in which we have
10541 * frame register ops, we will move this code as a part of that
10542 */
10543
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010544 /* GAS Initial Request */
10545 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10546 (uint8_t *) GAS_INITIAL_REQ,
10547 GAS_INITIAL_REQ_SIZE);
10548
10549 /* GAS Initial Response */
10550 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10551 (uint8_t *) GAS_INITIAL_RSP,
10552 GAS_INITIAL_RSP_SIZE);
10553
10554 /* GAS Comeback Request */
10555 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10556 (uint8_t *) GAS_COMEBACK_REQ,
10557 GAS_COMEBACK_REQ_SIZE);
10558
10559 /* GAS Comeback Response */
10560 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10561 (uint8_t *) GAS_COMEBACK_RSP,
10562 GAS_COMEBACK_RSP_SIZE);
10563
10564 /* P2P Public Action */
10565 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10566 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10567 P2P_PUBLIC_ACTION_FRAME_SIZE);
10568
10569 /* P2P Action */
10570 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10571 (uint8_t *) P2P_ACTION_FRAME,
10572 P2P_ACTION_FRAME_SIZE);
10573
10574 /* WNM BSS Transition Request frame */
10575 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10576 (uint8_t *) WNM_BSS_ACTION_FRAME,
10577 WNM_BSS_ACTION_FRAME_SIZE);
10578
10579 /* WNM-Notification */
10580 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10581 (uint8_t *) WNM_NOTIFICATION_FRAME,
10582 WNM_NOTIFICATION_FRAME_SIZE);
10583}
10584
10585void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10586{
10587 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10588 /* Register for all P2P action, public action etc frames */
10589 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10590
10591 ENTER();
10592
10593 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010594 * initialized. Once we will move to 2.6.37 kernel, in which we have
10595 * frame register ops, we will move this code as a part of that
10596 */
10597
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010598 /* GAS Initial Request */
10599
10600 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10601 (uint8_t *) GAS_INITIAL_REQ,
10602 GAS_INITIAL_REQ_SIZE);
10603
10604 /* GAS Initial Response */
10605 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10606 (uint8_t *) GAS_INITIAL_RSP,
10607 GAS_INITIAL_RSP_SIZE);
10608
10609 /* GAS Comeback Request */
10610 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10611 (uint8_t *) GAS_COMEBACK_REQ,
10612 GAS_COMEBACK_REQ_SIZE);
10613
10614 /* GAS Comeback Response */
10615 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10616 (uint8_t *) GAS_COMEBACK_RSP,
10617 GAS_COMEBACK_RSP_SIZE);
10618
10619 /* P2P Public Action */
10620 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10621 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10622 P2P_PUBLIC_ACTION_FRAME_SIZE);
10623
10624 /* P2P Action */
10625 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10626 (uint8_t *) P2P_ACTION_FRAME,
10627 P2P_ACTION_FRAME_SIZE);
10628
10629 /* WNM-Notification */
10630 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10631 (uint8_t *) WNM_NOTIFICATION_FRAME,
10632 WNM_NOTIFICATION_FRAME_SIZE);
10633}
10634
10635#ifdef FEATURE_WLAN_WAPI
10636void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10637 const uint8_t *mac_addr, const uint8_t *key,
10638 int key_Len)
10639{
10640 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10641 tCsrRoamSetKey setKey;
10642 bool isConnected = true;
10643 int status = 0;
10644 uint32_t roamId = 0xFF;
10645 uint8_t *pKeyPtr = NULL;
10646 int n = 0;
10647
Jeff Johnson46b40792016-06-29 14:03:14 -070010648 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010649 hdd_device_mode_to_string(pAdapter->device_mode),
10650 pAdapter->device_mode);
10651
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010652 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010653 setKey.keyId = key_index; /* Store Key ID */
10654 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10655 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10656 setKey.paeRole = 0; /* the PAE role */
10657 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010658 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010659 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010660 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010661 }
10662 setKey.keyLength = key_Len;
10663 pKeyPtr = setKey.Key;
10664 memcpy(pKeyPtr, key, key_Len);
10665
Jeff Johnson46b40792016-06-29 14:03:14 -070010666 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010667 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -070010668 hdd_notice("WAPI KEY Data[%d]:%02x ",
10669 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010670
10671 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10672 if (isConnected) {
10673 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10674 pAdapter->sessionId, &setKey, &roamId);
10675 }
10676 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -070010677 hdd_err("sme_roam_set_key returned ERROR status= %d",
10678 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010679 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10680 }
10681}
10682#endif /* FEATURE_WLAN_WAPI */
10683
10684uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10685 uint8_t eid)
10686{
10687 int left = length;
10688 uint8_t *ptr = (uint8_t *)ies_ptr;
10689 uint8_t elem_id, elem_len;
10690
10691 while (left >= 2) {
10692 elem_id = ptr[0];
10693 elem_len = ptr[1];
10694 left -= 2;
10695 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -070010696 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010697 eid, elem_len, left);
10698 return NULL;
10699 }
10700 if (elem_id == eid) {
10701 return ptr;
10702 }
10703
10704 left -= elem_len;
10705 ptr += (elem_len + 2);
10706 }
10707 return NULL;
10708}
10709
10710/*
10711 * FUNCTION: wlan_hdd_validate_operation_channel
10712 * called by wlan_hdd_cfg80211_start_bss() and
10713 * wlan_hdd_set_channel()
10714 * This function validates whether given channel is part of valid
10715 * channel list.
10716 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010717QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010718 int channel)
10719{
10720
10721 uint32_t num_ch = 0;
10722 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10723 u32 indx = 0;
10724 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10725 uint8_t fValidChannel = false, count = 0;
10726 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10727
10728 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10729
10730 if (hdd_pConfig_ini->sapAllowAllChannel) {
10731 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010732 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010733 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010734 fValidChannel = true;
10735 break;
10736 }
10737 }
10738 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -070010739 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010740 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010741 }
10742 } else {
10743 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10744 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010745 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010746 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010747 }
10748 for (indx = 0; indx < num_ch; indx++) {
10749 if (channel == valid_ch[indx]) {
10750 break;
10751 }
10752 }
10753
10754 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -070010755 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010756 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010757 }
10758 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010759 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010760
10761}
10762
10763#ifdef DHCP_SERVER_OFFLOAD
10764static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10765{
10766 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10767 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10768 uint8_t numEntries = 0;
10769 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10770 uint8_t num;
10771 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010772 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010773 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010774 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010775 return;
10776 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010777 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10778 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10779 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10780 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10781 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10782 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -070010783 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010784 goto end;
10785 }
10786 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010787 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010788 goto end;
10789 }
10790 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -070010791 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010792 goto end;
10793 }
10794 for (num = 0; num < numEntries; num++) {
10795 temp = srv_ip[num];
10796 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10797 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010798 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010799 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010800 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010801 goto end;
10802 }
Jeff Johnson77848112016-06-29 14:52:06 -070010803 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010804end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010805 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010806 return;
10807}
10808#endif /* DHCP_SERVER_OFFLOAD */
10809
10810static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10811 struct net_device *dev,
10812 struct bss_parameters *params)
10813{
10814 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10815 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10816 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010817 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010818
10819 ENTER();
10820
Anurag Chouhan6d760662016-02-20 16:05:43 +053010821 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010822 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010823 return -EINVAL;
10824 }
10825
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010826 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10827 hdd_err("invalid session id: %d", pAdapter->sessionId);
10828 return -EINVAL;
10829 }
10830
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010831 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010832 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10833 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -070010834 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010835 hdd_device_mode_to_string(pAdapter->device_mode),
10836 pAdapter->device_mode, params->ap_isolate);
10837
10838 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10839 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010840 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010841 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010842
Krunal Sonib4326f22016-03-10 13:05:51 -080010843 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10844 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010845 return -EOPNOTSUPP;
10846 }
10847
10848 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010849 * want to update this parameter
10850 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010851 if (-1 != params->ap_isolate) {
10852 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10853 !!params->ap_isolate;
10854
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010855 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856 pAdapter->sessionId,
10857 pAdapter->sessionCtx.
10858 ap.
10859 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010860 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010861 ret = -EINVAL;
10862 }
10863 }
10864
10865 EXIT();
10866 return ret;
10867}
10868
Krunal Soni8c37e322016-02-03 16:08:37 -080010869/**
10870 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10871 * @ndev: pointer to net device provided by supplicant
10872 * @type: type of the interface, upper layer wanted to change
10873 *
10874 * Upper layer provides the new interface mode that needs to be changed
10875 * for given net device
10876 *
10877 * Return: success or failure in terms of integer value
10878 */
10879static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010880 enum nl80211_iftype type)
10881{
Krunal Soni8c37e322016-02-03 16:08:37 -080010882 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10883 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10884 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010885 hdd_wext_state_t *wext;
10886 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010887 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010888
10889 ENTER();
10890
Krunal Soni8c37e322016-02-03 16:08:37 -080010891 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010892 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010893 return 0;
10894 }
10895
10896 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080010897 hdd_stop_adapter(hdd_ctx, adapter, true);
10898 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010899 wdev->iftype = type;
10900 /*Check for sub-string p2p to confirm its a p2p interface */
10901 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080010902 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010903 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010904 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080010905 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080010906 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010907 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080010908 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010909 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010910 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010911 }
Krunal Soni8c37e322016-02-03 16:08:37 -080010912 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
10913 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080010914 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
10915 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010916 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080010917 adapter->scan_info.scanAddIE.length;
10918 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010919 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080010920 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
10921 wext->roamProfile.phyMode =
10922 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
10923 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010924 EXIT();
10925 return status;
10926}
10927
10928static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10929 struct net_device *dev,
10930 struct bss_parameters *params)
10931{
10932 int ret;
10933
10934 cds_ssr_protect(__func__);
10935 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
10936 cds_ssr_unprotect(__func__);
10937
10938 return ret;
10939}
10940
10941/* FUNCTION: wlan_hdd_change_country_code_cd
10942 * to wait for contry code completion
10943 */
10944void *wlan_hdd_change_country_code_cb(void *pAdapter)
10945{
10946 hdd_adapter_t *call_back_pAdapter = pAdapter;
10947 complete(&call_back_pAdapter->change_country_code);
10948 return NULL;
10949}
10950
Rajeev Kumar98edb772016-01-19 12:42:19 -080010951/**
10952 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10953 * @wiphy: Pointer to the wiphy structure
10954 * @ndev: Pointer to the net device
10955 * @type: Interface type
10956 * @flags: Flags for change interface
10957 * @params: Pointer to change interface parameters
10958 *
10959 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960 */
10961static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
10962 struct net_device *ndev,
10963 enum nl80211_iftype type,
10964 u32 *flags,
10965 struct vif_params *params)
10966{
10967 struct wireless_dev *wdev;
10968 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10969 hdd_context_t *pHddCtx;
10970 tCsrRoamProfile *pRoamProfile = NULL;
10971 eCsrRoamBssType LastBSSType;
10972 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010973 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010974 int status;
10975
10976 ENTER();
10977
Anurag Chouhan6d760662016-02-20 16:05:43 +053010978 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010979 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010980 return -EINVAL;
10981 }
10982
10983 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10984 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010985 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010986 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010987
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010988 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010989 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
10990 pAdapter->sessionId, type));
10991
Jeff Johnson77848112016-06-29 14:52:06 -070010992 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010993 pAdapter->device_mode, type);
10994
Arun Khandavallifae92942016-08-01 13:31:08 +053010995 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
10996 if (status) {
10997 hdd_err("Failed to start modules");
10998 return -EINVAL;
10999 }
11000
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011001 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11003 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011004 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011005 return -EINVAL;
11006 }
11007
11008 pConfig = pHddCtx->config;
11009 wdev = ndev->ieee80211_ptr;
11010
11011 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011012 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011013
11014 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
11015
Krunal Sonib4326f22016-03-10 13:05:51 -080011016 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11017 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11018 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11019 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011020 hdd_wext_state_t *pWextState =
11021 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11022
11023 pRoamProfile = &pWextState->roamProfile;
11024 LastBSSType = pRoamProfile->BSSType;
11025
11026 switch (type) {
11027 case NL80211_IFTYPE_STATION:
11028 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011029 case NL80211_IFTYPE_ADHOC:
11030 if (type == NL80211_IFTYPE_ADHOC) {
11031 wlan_hdd_tdls_exit(pAdapter);
11032 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070011033 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011034 }
11035 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11036 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011037 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011038 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011039 if (hdd_start_adapter(pAdapter)) {
11040 hdd_err("Failed to start adapter :%d",
11041 pAdapter->device_mode);
11042 return -EINVAL;
11043 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011044 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011045 case NL80211_IFTYPE_AP:
11046 case NL80211_IFTYPE_P2P_GO:
11047 {
Jeff Johnson77848112016-06-29 14:52:06 -070011048 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011049 (type ==
11050 NL80211_IFTYPE_AP) ? "SoftAP" :
11051 "P2pGo");
11052
11053 /* Cancel any remain on channel for GO mode */
11054 if (NL80211_IFTYPE_P2P_GO == type) {
11055 wlan_hdd_cancel_existing_remain_on_channel
11056 (pAdapter);
11057 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011058
Arun Khandavallifae92942016-08-01 13:31:08 +053011059 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011060 /* De-init the adapter */
11061 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11062 memset(&pAdapter->sessionCtx, 0,
11063 sizeof(pAdapter->sessionCtx));
11064 pAdapter->device_mode =
11065 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011066 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11067 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011068
11069 /*
11070 * Fw will take care incase of concurrency
11071 */
11072
Krunal Sonib4326f22016-03-10 13:05:51 -080011073 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011074 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011075 /* To meet Android requirements create
11076 * a randomized MAC address of the
11077 * form 02:1A:11:Fx:xx:xx
11078 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011079 get_random_bytes(&ndev->dev_addr[3], 3);
11080 ndev->dev_addr[0] = 0x02;
11081 ndev->dev_addr[1] = 0x1A;
11082 ndev->dev_addr[2] = 0x11;
11083 ndev->dev_addr[3] |= 0xF0;
11084 memcpy(pAdapter->macAddressCurrent.
11085 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011086 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011087 pr_info("wlan: Generated HotSpot BSSID "
11088 MAC_ADDRESS_STR "\n",
11089 MAC_ADDR_ARRAY(ndev->dev_addr));
11090 }
11091
11092 hdd_set_ap_ops(pAdapter->dev);
11093
Arun Khandavallifae92942016-08-01 13:31:08 +053011094 if (hdd_start_adapter(pAdapter)) {
11095 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011096 return -EINVAL;
11097 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011098 /* Interface type changed update in wiphy structure */
11099 if (wdev) {
11100 wdev->iftype = type;
11101 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011102 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011103 return -EINVAL;
11104 }
11105 goto done;
11106 }
11107
11108 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011109 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011110 type);
11111 return -EOPNOTSUPP;
11112 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011113 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11114 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011115 switch (type) {
11116 case NL80211_IFTYPE_STATION:
11117 case NL80211_IFTYPE_P2P_CLIENT:
11118 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011119 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11120 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011121 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011122 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011123 if (hdd_start_adapter(pAdapter)) {
11124 hdd_err("Failed to start adapter :%d",
11125 pAdapter->device_mode);
11126 return -EINVAL;
11127 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011128 goto done;
11129
11130 case NL80211_IFTYPE_AP:
11131 case NL80211_IFTYPE_P2P_GO:
11132 wdev->iftype = type;
11133 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011134 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011135 goto done;
11136
11137 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011138 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011139 type);
11140 return -EOPNOTSUPP;
11141 }
11142 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011143 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011144 pAdapter->device_mode);
11145 return -EOPNOTSUPP;
11146 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011147done:
11148 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011149 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011150
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011151 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011152
11153 EXIT();
11154 return 0;
11155}
11156
Rajeev Kumar98edb772016-01-19 12:42:19 -080011157/**
11158 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11159 * @wiphy: Pointer to the wiphy structure
11160 * @ndev: Pointer to the net device
11161 * @type: Interface type
11162 * @flags: Flags for change interface
11163 * @params: Pointer to change interface parameters
11164 *
11165 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011166 */
11167static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11168 struct net_device *ndev,
11169 enum nl80211_iftype type,
11170 u32 *flags,
11171 struct vif_params *params)
11172{
11173 int ret;
11174
11175 cds_ssr_protect(__func__);
11176 ret =
11177 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11178 cds_ssr_unprotect(__func__);
11179
11180 return ret;
11181}
11182
11183#ifdef FEATURE_WLAN_TDLS
11184static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11185 int index, uint8_t match)
11186{
11187 int i;
11188 for (i = 0; i < index; i++) {
11189 if (arr[i] == match)
11190 return true;
11191 }
11192 return false;
11193}
11194#endif
11195
11196/**
11197 * __wlan_hdd_change_station() - change station
11198 * @wiphy: Pointer to the wiphy structure
11199 * @dev: Pointer to the net device.
11200 * @mac: bssid
11201 * @params: Pointer to station parameters
11202 *
11203 * Return: 0 for success, error number on failure.
11204 */
11205#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11206static int __wlan_hdd_change_station(struct wiphy *wiphy,
11207 struct net_device *dev,
11208 const uint8_t *mac,
11209 struct station_parameters *params)
11210#else
11211static int __wlan_hdd_change_station(struct wiphy *wiphy,
11212 struct net_device *dev,
11213 uint8_t *mac,
11214 struct station_parameters *params)
11215#endif
11216{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011217 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011218 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11219 hdd_context_t *pHddCtx;
11220 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011221 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011222#ifdef FEATURE_WLAN_TDLS
11223 tCsrStaParams StaParams = { 0 };
11224 uint8_t isBufSta = 0;
11225 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011226 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011227#endif
11228 int ret;
11229
11230 ENTER();
11231
Anurag Chouhan6d760662016-02-20 16:05:43 +053011232 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011233 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011234 return -EINVAL;
11235 }
11236
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011237 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238 TRACE_CODE_HDD_CHANGE_STATION,
11239 pAdapter->sessionId, params->listen_interval));
11240
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011241 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11242 hdd_err("invalid session id: %d", pAdapter->sessionId);
11243 return -EINVAL;
11244 }
11245
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011246 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11247 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011248 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011249 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250
11251 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11252
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011253 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011254
Krunal Sonib4326f22016-03-10 13:05:51 -080011255 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11256 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011257 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11258 status =
11259 hdd_softap_change_sta_state(pAdapter,
11260 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011261 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011262
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011263 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011264 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011265 return -EINVAL;
11266 }
11267 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011268 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11269 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270#ifdef FEATURE_WLAN_TDLS
11271 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011272
11273 if (cds_is_sub_20_mhz_enabled()) {
11274 hdd_err("TDLS not allowed with sub 20 MHz");
11275 return -EINVAL;
11276 }
11277
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011278 StaParams.capability = params->capability;
11279 StaParams.uapsd_queues = params->uapsd_queues;
11280 StaParams.max_sp = params->max_sp;
11281
11282 /* Convert (first channel , number of channels) tuple to
11283 * the total list of channels. This goes with the assumption
11284 * that if the first channel is < 14, then the next channels
11285 * are an incremental of 1 else an incremental of 4 till the number
11286 * of channels.
11287 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011288 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011289 if (0 != params->supported_channels_len) {
11290 int i = 0, j = 0, k = 0, no_of_channels = 0;
11291 int num_unique_channels;
11292 int next;
11293 for (i = 0;
11294 i < params->supported_channels_len
11295 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11296 int wifi_chan_index;
11297 if (!wlan_hdd_is_duplicate_channel
11298 (StaParams.supported_channels, j,
11299 params->supported_channels[i])) {
11300 StaParams.
11301 supported_channels[j] =
11302 params->
11303 supported_channels[i];
11304 } else {
11305 continue;
11306 }
11307 wifi_chan_index =
11308 ((StaParams.supported_channels[j] <=
11309 HDD_CHANNEL_14) ? 1 : 4);
11310 no_of_channels =
11311 params->supported_channels[i + 1];
11312
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011313 hdd_notice("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 -080011314 StaParams.
11315 supported_channels[j],
11316 wifi_chan_index,
11317 no_of_channels);
11318 for (k = 1; k <= no_of_channels &&
11319 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11320 k++) {
11321 next =
11322 StaParams.
11323 supported_channels[j] +
11324 wifi_chan_index;
11325 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11326 StaParams.
11327 supported_channels[j
11328 +
11329 1]
11330 = next;
11331 } else {
11332 continue;
11333 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011334 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011335 j + 1,
11336 StaParams.
11337 supported_channels[j +
11338 1]);
11339 j += 1;
11340 }
11341 }
11342 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011343 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011344 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011345 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011346 StaParams.
11347 supported_channels[i]);
11348 }
11349 if (MAX_CHANNEL < num_unique_channels)
11350 num_unique_channels = MAX_CHANNEL;
11351 StaParams.supported_channels_len =
11352 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011353 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011354 StaParams.supported_channels_len);
11355 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011356 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011357 params->supported_oper_classes,
11358 params->supported_oper_classes_len);
11359 StaParams.supported_oper_classes_len =
11360 params->supported_oper_classes_len;
11361
11362 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011363 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011364 params->ext_capab,
11365 sizeof(StaParams.extn_capability));
11366
11367 if (NULL != params->ht_capa) {
11368 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011369 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011370 sizeof(tSirHTCap));
11371 }
11372
11373 StaParams.supported_rates_len =
11374 params->supported_rates_len;
11375
11376 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11377 * The supported_rates array , for all the structures propogating till Add Sta
11378 * to the firmware has to be modified , if the supplicant (ieee80211) is
11379 * modified to send more rates.
11380 */
11381
11382 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11383 */
11384 if (StaParams.supported_rates_len >
11385 SIR_MAC_MAX_SUPP_RATES)
11386 StaParams.supported_rates_len =
11387 SIR_MAC_MAX_SUPP_RATES;
11388
11389 if (0 != StaParams.supported_rates_len) {
11390 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011391 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011392 params->supported_rates,
11393 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011394 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011395 StaParams.supported_rates_len);
11396 for (i = 0; i < StaParams.supported_rates_len;
11397 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011398 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011399 StaParams.supported_rates[i]);
11400 }
11401
11402 if (NULL != params->vht_capa) {
11403 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011404 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011405 params->vht_capa,
11406 sizeof(tSirVHTCap));
11407 }
11408
11409 if (0 != params->ext_capab_len) {
11410 /*Define A Macro : TODO Sunil */
11411 if ((1 << 4) & StaParams.extn_capability[3]) {
11412 isBufSta = 1;
11413 }
11414 /* TDLS Channel Switching Support */
11415 if ((1 << 6) & StaParams.extn_capability[3]) {
11416 isOffChannelSupported = 1;
11417 }
11418 }
11419
Nitesh Shah99934ac2016-09-05 15:54:08 +053011420 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011421 (params->ht_capa || params->vht_capa ||
11422 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011423 is_qos_wmm_sta = true;
11424
11425 hdd_notice("%s: TDLS Peer is QOS capable"
11426 " is_qos_wmm_sta= %d HTcapPresent = %d",
11427 __func__, is_qos_wmm_sta,
11428 StaParams.htcap_present);
11429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011430 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011431 &StaParams,
11432 isBufSta,
11433 isOffChannelSupported,
11434 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011435 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011436 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011437 return -EINVAL;
11438 }
11439
11440 status =
11441 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11442 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011443 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011444 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011445 return -EINVAL;
11446 }
11447 }
11448#endif
11449 }
11450 EXIT();
11451 return ret;
11452}
11453
11454/**
11455 * wlan_hdd_change_station() - cfg80211 change station handler function
11456 * @wiphy: Pointer to the wiphy structure
11457 * @dev: Pointer to the net device.
11458 * @mac: bssid
11459 * @params: Pointer to station parameters
11460 *
11461 * This is the cfg80211 change station handler function which invokes
11462 * the internal function @__wlan_hdd_change_station with
11463 * SSR protection.
11464 *
11465 * Return: 0 for success, error number on failure.
11466 */
11467#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11468static int wlan_hdd_change_station(struct wiphy *wiphy,
11469 struct net_device *dev,
11470 const u8 *mac,
11471 struct station_parameters *params)
11472#else
11473static int wlan_hdd_change_station(struct wiphy *wiphy,
11474 struct net_device *dev,
11475 u8 *mac,
11476 struct station_parameters *params)
11477#endif
11478{
11479 int ret;
11480
11481 cds_ssr_protect(__func__);
11482 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11483 cds_ssr_unprotect(__func__);
11484
11485 return ret;
11486}
11487
11488/*
11489 * FUNCTION: __wlan_hdd_cfg80211_add_key
11490 * This function is used to initialize the key information
11491 */
11492static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11493 struct net_device *ndev,
11494 u8 key_index, bool pairwise,
11495 const u8 *mac_addr,
11496 struct key_params *params)
11497{
11498 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11499 tCsrRoamSetKey setKey;
11500 int status;
11501 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011502 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011503 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011504 hdd_context_t *pHddCtx;
11505 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11506
11507 ENTER();
11508
Anurag Chouhan6d760662016-02-20 16:05:43 +053011509 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011510 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011511 return -EINVAL;
11512 }
11513
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011514 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11515 hdd_err("invalid session id: %d", pAdapter->sessionId);
11516 return -EINVAL;
11517 }
11518
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011519 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011520 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11521 pAdapter->sessionId, params->key_len));
11522 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11523 status = wlan_hdd_validate_context(pHddCtx);
11524
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011525 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011526 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011527
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011528 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011529 hdd_device_mode_to_string(pAdapter->device_mode),
11530 pAdapter->device_mode);
11531
11532 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011533 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011534
11535 return -EINVAL;
11536 }
11537
11538 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011539 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011540
11541 return -EINVAL;
11542 }
11543
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011544 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011545
11546 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011547 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011548 setKey.keyId = key_index;
11549 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011550 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011551
11552 switch (params->cipher) {
11553 case WLAN_CIPHER_SUITE_WEP40:
11554 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11555 break;
11556
11557 case WLAN_CIPHER_SUITE_WEP104:
11558 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11559 break;
11560
11561 case WLAN_CIPHER_SUITE_TKIP:
11562 {
11563 u8 *pKey = &setKey.Key[0];
11564 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11565
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011566 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011567
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011568 /* Supplicant sends the 32bytes key in this order
11569 *
11570 * |--------------|----------|----------|
11571 * | Tk1 |TX-MIC | RX Mic |
11572 * |--------------|----------|----------|
11573 * <---16bytes---><--8bytes--><--8bytes-->
11574 *
11575 * Sme expects the 32 bytes key to be in the below order
11576 *
11577 * |--------------|----------|----------|
11578 * | Tk1 |RX-MIC | TX Mic |
11579 * |--------------|----------|----------|
11580 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011581 */
11582 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011583 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011584
11585 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011586 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587
11588 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011589 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011590
11591 break;
11592 }
11593
11594 case WLAN_CIPHER_SUITE_CCMP:
11595 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11596 break;
11597
11598#ifdef FEATURE_WLAN_WAPI
11599 case WLAN_CIPHER_SUITE_SMS4:
11600 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011601 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011602 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11603 mac_addr, params->key,
11604 params->key_len);
11605 return 0;
11606 }
11607#endif
11608
11609#ifdef FEATURE_WLAN_ESE
11610 case WLAN_CIPHER_SUITE_KRK:
11611 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11612 break;
11613#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11614 case WLAN_CIPHER_SUITE_BTK:
11615 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11616 break;
11617#endif
11618#endif
11619
11620#ifdef WLAN_FEATURE_11W
11621 case WLAN_CIPHER_SUITE_AES_CMAC:
11622 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11623 break;
11624#endif
11625
11626 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011627 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011628 return -EOPNOTSUPP;
11629 }
11630
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011631 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011632
11633 if (!pairwise) {
11634 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011635 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011636 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011637 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011638 } else {
11639 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011640 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011642 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011643 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011644 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011645 /* if a key is already installed, block all subsequent ones */
11646 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011647 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011648 return 0;
11649 }
11650
11651 setKey.keyDirection = eSIR_TX_RX;
11652 /*Set the group key */
11653 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11654 pAdapter->sessionId, &setKey, &roamId);
11655
11656 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011657 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658 return -EINVAL;
11659 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011660 /* Save the keys here and call sme_roam_set_key for setting
11661 * the PTK after peer joins the IBSS network
11662 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011663 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011664 &setKey, sizeof(tCsrRoamSetKey));
11665
11666 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11667 return status;
11668 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011669 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11670 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011671 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11672 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011673 status = wlansap_set_key_sta(
11674 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011675 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011676 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011677 __LINE__, status);
11678 }
11679 }
11680
11681 /* Save the key in ap ctx for use on START_BASS and restart */
11682 if (pairwise ||
11683 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11684 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011685 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011686 sizeof(tCsrRoamSetKey));
11687 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011688 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011689 sizeof(tCsrRoamSetKey));
11690
Krunal Sonib4326f22016-03-10 13:05:51 -080011691 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11692 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011693 hdd_wext_state_t *pWextState =
11694 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11695 hdd_station_ctx_t *pHddStaCtx =
11696 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11697
11698 if (!pairwise) {
11699 /* set group key */
11700 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011701 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011702 __func__, __LINE__);
11703 hdd_perform_roam_set_key_complete(pAdapter);
11704 }
11705 }
11706
11707 pWextState->roamProfile.Keys.KeyLength[key_index] =
11708 (u8) params->key_len;
11709
11710 pWextState->roamProfile.Keys.defaultIndex = key_index;
11711
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011712 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011713 KeyMaterial[key_index][0], params->key,
11714 params->key_len);
11715
11716 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11717
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011718 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011719 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11720 setKey.keyDirection);
11721
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011722 /* The supplicant may attempt to set the PTK once
11723 * pre-authentication is done. Save the key in the
11724 * UMAC and include it in the ADD BSS request
11725 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011726 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011727 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011728 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011729 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011730 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011731 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011732 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011733 return -EINVAL;
11734 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011735
11736 /* issue set key request to SME */
11737 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11738 pAdapter->sessionId, &setKey, &roamId);
11739
11740 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011741 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011742 pHddStaCtx->roam_info.roamingState =
11743 HDD_ROAM_STATE_NONE;
11744 return -EINVAL;
11745 }
11746
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011747 /* in case of IBSS as there was no information
11748 * available about WEP keys during IBSS join, group
11749 * key intialized with NULL key, so re-initialize
11750 * group key with correct value
11751 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011752 if ((eCSR_BSS_TYPE_START_IBSS ==
11753 pWextState->roamProfile.BSSType)
11754 &&
11755 !((IW_AUTH_KEY_MGMT_802_1X ==
11756 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11757 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11758 pHddStaCtx->conn_info.authType)
11759 )
11760 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11761 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11762 )
11763 ) {
11764 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011765 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011766
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011767 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011768 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11769 setKey.keyDirection);
11770
11771 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11772 pAdapter->sessionId, &setKey,
11773 &roamId);
11774
11775 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011776 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011777 pHddStaCtx->roam_info.roamingState =
11778 HDD_ROAM_STATE_NONE;
11779 return -EINVAL;
11780 }
11781 }
11782 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011783 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011784 return 0;
11785}
11786
11787static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11788 struct net_device *ndev,
11789 u8 key_index, bool pairwise,
11790 const u8 *mac_addr,
11791 struct key_params *params)
11792{
11793 int ret;
11794 cds_ssr_protect(__func__);
11795 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11796 mac_addr, params);
11797 cds_ssr_unprotect(__func__);
11798
11799 return ret;
11800}
11801
11802/*
11803 * FUNCTION: __wlan_hdd_cfg80211_get_key
11804 * This function is used to get the key information
11805 */
11806static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11807 struct net_device *ndev,
11808 u8 key_index, bool pairwise,
11809 const u8 *mac_addr, void *cookie,
11810 void (*callback)(void *cookie,
11811 struct key_params *)
11812 )
11813{
11814 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11815 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11816 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11817 struct key_params params;
11818
11819 ENTER();
11820
Anurag Chouhan6d760662016-02-20 16:05:43 +053011821 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011822 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011823 return -EINVAL;
11824 }
11825
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011826 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011827 hdd_device_mode_to_string(pAdapter->device_mode),
11828 pAdapter->device_mode);
11829
11830 memset(&params, 0, sizeof(params));
11831
11832 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011833 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 key_index);
11835 return -EINVAL;
11836 }
11837
11838 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11839 case eCSR_ENCRYPT_TYPE_NONE:
11840 params.cipher = IW_AUTH_CIPHER_NONE;
11841 break;
11842
11843 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11844 case eCSR_ENCRYPT_TYPE_WEP40:
11845 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11846 break;
11847
11848 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11849 case eCSR_ENCRYPT_TYPE_WEP104:
11850 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11851 break;
11852
11853 case eCSR_ENCRYPT_TYPE_TKIP:
11854 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11855 break;
11856
11857 case eCSR_ENCRYPT_TYPE_AES:
11858 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11859 break;
11860
11861 default:
11862 params.cipher = IW_AUTH_CIPHER_NONE;
11863 break;
11864 }
11865
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011866 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011867 TRACE_CODE_HDD_CFG80211_GET_KEY,
11868 pAdapter->sessionId, params.cipher));
11869
11870 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11871 params.seq_len = 0;
11872 params.seq = NULL;
11873 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11874 callback(cookie, &params);
11875
11876 EXIT();
11877 return 0;
11878}
11879
11880static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11881 struct net_device *ndev,
11882 u8 key_index, bool pairwise,
11883 const u8 *mac_addr, void *cookie,
11884 void (*callback)(void *cookie,
11885 struct key_params *)
11886 )
11887{
11888 int ret;
11889
11890 cds_ssr_protect(__func__);
11891 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11892 mac_addr, cookie, callback);
11893 cds_ssr_unprotect(__func__);
11894
11895 return ret;
11896}
11897
11898/**
11899 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
11900 * @wiphy: wiphy interface context
11901 * @ndev: pointer to net device
11902 * @key_index: Key index used in 802.11 frames
11903 * @unicast: true if it is unicast key
11904 * @multicast: true if it is multicast key
11905 *
11906 * This function is required for cfg80211_ops API.
11907 * It is used to delete the key information
11908 * Underlying hardware implementation does not have API to delete the
11909 * encryption key. It is automatically deleted when the peer is
11910 * removed. Hence this function currently does nothing.
11911 * Future implementation may interprete delete key operation to
11912 * replacing the key with a random junk value, effectively making it
11913 * useless.
11914 *
11915 * Return: status code, always 0.
11916 */
11917
11918static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11919 struct net_device *ndev,
11920 u8 key_index,
11921 bool pairwise, const u8 *mac_addr)
11922{
11923 EXIT();
11924 return 0;
11925}
11926
11927/**
11928 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
11929 * @wiphy: Pointer to wiphy structure.
11930 * @dev: Pointer to net_device structure.
11931 * @key_index: key index
11932 * @pairwise: pairwise
11933 * @mac_addr: mac address
11934 *
11935 * This is the cfg80211 delete key handler function which invokes
11936 * the internal function @__wlan_hdd_cfg80211_del_key with
11937 * SSR protection.
11938 *
11939 * Return: 0 for success, error number on failure.
11940 */
11941static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11942 struct net_device *dev,
11943 u8 key_index,
11944 bool pairwise, const u8 *mac_addr)
11945{
11946 int ret;
11947
11948 cds_ssr_protect(__func__);
11949 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
11950 pairwise, mac_addr);
11951 cds_ssr_unprotect(__func__);
11952
11953 return ret;
11954}
11955
11956/*
11957 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
11958 * This function is used to set the default tx key index
11959 */
11960static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
11961 struct net_device *ndev,
11962 u8 key_index,
11963 bool unicast, bool multicast)
11964{
11965 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11966 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11967 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11968 hdd_context_t *pHddCtx;
11969 int status;
11970
11971 ENTER();
11972
Anurag Chouhan6d760662016-02-20 16:05:43 +053011973 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011974 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011975 return -EINVAL;
11976 }
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
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011983 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011984 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
11985 pAdapter->sessionId, key_index));
11986
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011987 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011988 hdd_device_mode_to_string(pAdapter->device_mode),
11989 pAdapter->device_mode, key_index);
11990
11991 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011992 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011993 return -EINVAL;
11994 }
11995
11996 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11997 status = wlan_hdd_validate_context(pHddCtx);
11998
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011999 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012000 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012001
Krunal Sonib4326f22016-03-10 13:05:51 -080012002 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12003 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012004 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12005 pHddStaCtx->conn_info.ucEncryptionType) &&
12006 (eCSR_ENCRYPT_TYPE_AES !=
12007 pHddStaCtx->conn_info.ucEncryptionType)) {
12008 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012009 * then update the default key index
12010 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012011
12012 tCsrRoamSetKey setKey;
12013 uint32_t roamId = 0xFF;
12014 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12015
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012016 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012017
12018 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012019 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012020 setKey.keyId = key_index;
12021 setKey.keyLength = Keys->KeyLength[key_index];
12022
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012023 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012024 &Keys->KeyMaterial[key_index][0],
12025 Keys->KeyLength[key_index]);
12026
12027 setKey.keyDirection = eSIR_TX_RX;
12028
Anurag Chouhanc5548422016-02-24 18:33:27 +053012029 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012030 &pHddStaCtx->conn_info.bssId);
12031
12032 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12033 pWextState->roamProfile.EncryptionType.
12034 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012035 /* In the case of dynamic wep
12036 * supplicant hardcodes DWEP type to
12037 * eCSR_ENCRYPT_TYPE_WEP104 even
12038 * though ap is configured for WEP-40
12039 * encryption. In this canse the key
12040 * length is 5 but the encryption type
12041 * is 104 hence checking the key
12042 * lenght(5) and encryption type(104)
12043 * and switching encryption type to 40
12044 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012045 pWextState->roamProfile.EncryptionType.
12046 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12047 pWextState->roamProfile.mcEncryptionType.
12048 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12049 }
12050
12051 setKey.encType =
12052 pWextState->roamProfile.EncryptionType.
12053 encryptionType[0];
12054
12055 /* Issue set key request */
12056 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12057 pAdapter->sessionId, &setKey,
12058 &roamId);
12059
12060 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012061 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012062 status);
12063 return -EINVAL;
12064 }
12065 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012066 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012067 /* In SoftAp mode setting key direction for default mode */
12068 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12069 pWextState->roamProfile.EncryptionType.encryptionType[0])
12070 && (eCSR_ENCRYPT_TYPE_AES !=
12071 pWextState->roamProfile.EncryptionType.
12072 encryptionType[0])) {
12073 /* Saving key direction for default key index to TX default */
12074 hdd_ap_ctx_t *pAPCtx =
12075 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12076 pAPCtx->wepKey[key_index].keyDirection =
12077 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012078 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012079 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012080 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012081 }
12082 }
12083
12084 EXIT();
12085 return status;
12086}
12087
12088static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12089 struct net_device *ndev,
12090 u8 key_index,
12091 bool unicast, bool multicast)
12092{
12093 int ret;
12094 cds_ssr_protect(__func__);
12095 ret =
12096 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12097 multicast);
12098 cds_ssr_unprotect(__func__);
12099
12100 return ret;
12101}
12102
Abhishek Singhc9941602016-08-09 16:06:22 +053012103/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012104 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12105 * interface that BSS might have been lost.
12106 * @pAdapter: adaptor
12107 * @bssid: bssid which might have been lost
12108 *
12109 * Return: bss which is unlinked from kernel cache
12110 */
12111struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12112 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012113{
12114 struct net_device *dev = pAdapter->dev;
12115 struct wireless_dev *wdev = dev->ieee80211_ptr;
12116 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012117 struct cfg80211_bss *bss = NULL;
12118
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012119 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012120 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012121 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012122 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012123 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053012124 hdd_info("cfg80211_unlink_bss called for BSSID "
12125 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012126 cfg80211_unlink_bss(wiphy, bss);
12127 }
12128 return bss;
12129}
12130
Abhishek Singhc9941602016-08-09 16:06:22 +053012131
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012132/**
12133 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12134 * @pAdapter: Pointer to adapter
12135 * @bss_desc: Pointer to bss descriptor
12136 *
12137 * This function is used to inform the BSS details to nl80211 interface.
12138 *
12139 * Return: struct cfg80211_bss pointer
12140 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012141struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12142 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012143{
12144 /*
12145 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12146 * already exists in bss data base of cfg80211 for that particular BSS
12147 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12148 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12149 * As of now there is no possibility to get the mgmt(probe response)
12150 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12151 * and passing to cfg80211_inform_bss_frame.
12152 */
12153 struct net_device *dev = pAdapter->dev;
12154 struct wireless_dev *wdev = dev->ieee80211_ptr;
12155 struct wiphy *wiphy = wdev->wiphy;
12156 int chan_no = bss_desc->channelId;
12157#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12158 qcom_ie_age *qie_age = NULL;
12159 int ie_length =
12160 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12161#else
12162 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12163#endif
12164 const char *ie =
12165 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12166 unsigned int freq;
12167 struct ieee80211_channel *chan;
12168 struct ieee80211_mgmt *mgmt = NULL;
12169 struct cfg80211_bss *bss_status = NULL;
12170 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12171 int rssi = 0;
12172 hdd_context_t *pHddCtx;
12173 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012175 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012176
12177 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12178 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012179 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012180 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012181
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012182 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012183 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012184 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012185 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012186 return NULL;
12187 }
12188
12189 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012191 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012192 * Instead it wants a monotonic increasing value
12193 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012194 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012195 mgmt->u.probe_resp.timestamp =
12196 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012197
12198 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12199 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12200
12201#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12202 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12203 /* Assuming this is the last IE, copy at the end */
12204 ie_length -= sizeof(qcom_ie_age);
12205 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12206 qie_age->element_id = QCOM_VENDOR_IE_ID;
12207 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12208 qie_age->oui_1 = QCOM_OUI1;
12209 qie_age->oui_2 = QCOM_OUI2;
12210 qie_age->oui_3 = QCOM_OUI3;
12211 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012212 /*
12213 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12214 * all bss related timestamp is in units of ms. Due to this when scan
12215 * results are sent to lowi the scan age is high.To address this,
12216 * send age in units of 1/10 ms.
12217 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012218 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012219 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012220 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012221 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12222 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012223 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12224 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012225#endif
12226
12227 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12228 if (bss_desc->fProbeRsp) {
12229 mgmt->frame_control |=
12230 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12231 } else {
12232 mgmt->frame_control |=
12233 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12234 }
12235
12236 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012237 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012238 freq =
12239 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012240 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012241 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012242 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012243 freq =
12244 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012245 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012246 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012247 hdd_err("Invalid chan_no %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012248 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012249 return NULL;
12250 }
12251
12252 chan = __ieee80211_get_channel(wiphy, freq);
12253 /* When the band is changed on the fly using the GUI, three things are done
12254 * 1. scan abort
12255 * 2. flush scan results from cache
12256 * 3. update the band with the new band user specified (refer to the
12257 * hdd_set_band_helper function) as part of the scan abort, message will be
12258 * queued to PE and we proceed with flushing and changinh the band.
12259 * PE will stop the scanning further and report back the results what ever
12260 * it had till now by calling the call back function.
12261 * if the time between update band and scandone call back is sufficient
12262 * enough the band change reflects in SME, SME validates the channels
12263 * and discards the channels correponding to previous band and calls back
12264 * with zero bss results. but if the time between band update and scan done
12265 * callback is very small then band change will not reflect in SME and SME
12266 * reports to HDD all the channels correponding to previous band.this is due
12267 * to race condition.but those channels are invalid to the new band and so
12268 * this function __ieee80211_get_channel will return NULL.Each time we
12269 * report scan result with this pointer null warning kernel trace is printed.
12270 * if the scan results contain large number of APs continuosly kernel
12271 * warning trace is printed and it will lead to apps watch dog bark.
12272 * So drop the bss and continue to next bss.
12273 */
12274 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012275 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12276 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012277 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012278 return NULL;
12279 }
12280
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012281 /* Based on .ini configuration, raw rssi can be reported for bss.
12282 * Raw rssi is typically used for estimating power.
12283 */
12284
12285 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12286 bss_desc->rssi;
12287
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012288 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012289 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012290
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053012291 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012292 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012293 (int)(rssi / 100),
12294 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012295
12296 bss_status =
12297 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
12298 GFP_KERNEL);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012299 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012300 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012301 return bss_status;
12302}
12303
12304/**
12305 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12306 * @pAdapter: Pointer to adapter
12307 * @pRoamInfo: Pointer to roam info
12308 *
12309 * This function is used to update the BSS data base of CFG8011
12310 *
12311 * Return: struct cfg80211_bss pointer
12312 */
12313struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12314 tCsrRoamInfo *pRoamInfo)
12315{
12316 tCsrRoamConnectedProfile roamProfile;
12317 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12318 struct cfg80211_bss *bss = NULL;
12319
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012320 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12321 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12322
12323 if (NULL != roamProfile.pBssDesc) {
12324 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12325 roamProfile.pBssDesc);
12326
12327 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012328 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012329
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012330 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012331 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012332 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012333 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334 return bss;
12335}
12336/**
12337 * wlan_hdd_cfg80211_update_bss() - update bss
12338 * @wiphy: Pointer to wiphy
12339 * @pAdapter: Pointer to adapter
12340 * @scan_time: scan request timestamp
12341 *
12342 * Return: zero if success, non-zero otherwise
12343 */
12344int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12345 hdd_adapter_t *pAdapter,
12346 uint32_t scan_time)
12347{
12348 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12349 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012350 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012351 tScanResultHandle pResult;
12352 struct cfg80211_bss *bss_status = NULL;
12353 hdd_context_t *pHddCtx;
12354 int ret;
12355
12356 ENTER();
12357
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012358 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12359 hdd_err("invalid session id: %d", pAdapter->sessionId);
12360 return -EINVAL;
12361 }
12362
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012363 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012364 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12365 NO_SESSION, pAdapter->sessionId));
12366
12367 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12368 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012369 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012370 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012371
12372 /* start getting scan results and populate cgf80211 BSS database */
12373 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12374
12375 /* no scan results */
12376 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012377 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012378 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012379 }
12380
12381 pScanResult = sme_scan_result_get_first(hHal, pResult);
12382
12383 while (pScanResult) {
12384 /*
12385 * - cfg80211_inform_bss() is not updating ie field of bss
12386 * entry if entry already exists in bss data base of cfg80211
12387 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12388 * to update thebss entry instead of cfg80211_inform_bss,
12389 * But this call expects mgmt packet as input. As of now
12390 * there is no possibility to get the mgmt(probe response)
12391 * frame from PE, converting bss_desc to
12392 * ieee80211_mgmt(probe response) and passing to c
12393 * fg80211_inform_bss_frame.
12394 * - Update BSS only if beacon timestamp is later than
12395 * scan request timestamp.
12396 */
12397 if ((scan_time == 0) ||
12398 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012399 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012400 bss_status =
12401 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12402 &pScanResult->BssDescriptor);
12403
12404 if (NULL == bss_status) {
12405 hdd_info("NULL returned by cfg80211_inform_bss_frame");
12406 } else {
12407 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012408 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012409 bss_status);
12410 }
12411 } else {
12412 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
12413 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12414 }
12415 pScanResult = sme_scan_result_get_next(hHal, pResult);
12416 }
12417
12418 sme_scan_result_purge(hHal, pResult);
12419 /*
12420 * For SAP mode, scan is invoked by hostapd during SAP start
12421 * if hostapd is restarted, we need to flush previous scan
12422 * result so that it will reflect environment change
12423 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012424 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012425#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12426 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12427#endif
12428 )
12429 sme_scan_flush_result(hHal);
12430
12431 EXIT();
12432 return 0;
12433}
12434
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012435/**
12436 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12437 * @pAdapter: Pointer to adapter
12438 * @pRoamInfo: Pointer to roam info
12439 * @index: Index
12440 * @preauth: Preauth flag
12441 *
12442 * This function is used to notify the supplicant of a new PMKSA candidate.
12443 *
12444 * Return: 0 for success, non-zero for failure
12445 */
12446int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12447 tCsrRoamInfo *pRoamInfo,
12448 int index, bool preauth)
12449{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012450 struct net_device *dev = pAdapter->dev;
12451 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12452
12453 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012454 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012455
12456 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012457 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012458 return -EINVAL;
12459 }
12460
12461 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012462 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012463 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12464 cfg80211_pmksa_candidate_notify(dev, index,
12465 pRoamInfo->bssid.bytes,
12466 preauth, GFP_KERNEL);
12467 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012468 return 0;
12469}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012470
12471#ifdef FEATURE_WLAN_LFR_METRICS
12472/**
12473 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12474 * @pAdapter: Pointer to adapter
12475 * @pRoamInfo: Pointer to roam info
12476 *
12477 * 802.11r/LFR metrics reporting function to report preauth initiation
12478 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012479 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012480 */
12481#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012482QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012483 tCsrRoamInfo *pRoamInfo)
12484{
12485 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12486 union iwreq_data wrqu;
12487
12488 ENTER();
12489
12490 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012491 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012492 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012493 }
12494
12495 /* create the event */
12496 memset(&wrqu, 0, sizeof(wrqu));
12497 memset(metrics_notification, 0, sizeof(metrics_notification));
12498
12499 wrqu.data.pointer = metrics_notification;
12500 wrqu.data.length = scnprintf(metrics_notification,
12501 sizeof(metrics_notification),
12502 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12503 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12504
12505 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12506 metrics_notification);
12507
12508 EXIT();
12509
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012510 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012511}
12512
12513/**
12514 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12515 * @pAdapter: Pointer to adapter
12516 * @pRoamInfo: Pointer to roam info
12517 * @preauth_status: Preauth status
12518 *
12519 * 802.11r/LFR metrics reporting function to report handover initiation
12520 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012521 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012522 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012523QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012524wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12525 tCsrRoamInfo *pRoamInfo,
12526 bool preauth_status)
12527{
12528 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12529 union iwreq_data wrqu;
12530
12531 ENTER();
12532
12533 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012534 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012535 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012536 }
12537
12538 /* create the event */
12539 memset(&wrqu, 0, sizeof(wrqu));
12540 memset(metrics_notification, 0, sizeof(metrics_notification));
12541
12542 scnprintf(metrics_notification, sizeof(metrics_notification),
12543 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12544 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12545
12546 if (1 == preauth_status)
12547 strlcat(metrics_notification, " true",
12548 sizeof(metrics_notification));
12549 else
12550 strlcat(metrics_notification, " false",
12551 sizeof(metrics_notification));
12552
12553 wrqu.data.pointer = metrics_notification;
12554 wrqu.data.length = strlen(metrics_notification);
12555
12556 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12557 metrics_notification);
12558
12559 EXIT();
12560
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012561 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012562}
12563
12564/**
12565 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12566 * @pAdapter: Pointer to adapter
12567 * @pRoamInfo: Pointer to roam info
12568 *
12569 * 802.11r/LFR metrics reporting function to report handover initiation
12570 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012571 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012572 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012573QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012574 tCsrRoamInfo *pRoamInfo)
12575{
12576 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12577 union iwreq_data wrqu;
12578
12579 ENTER();
12580
12581 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012582 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012583 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012584 }
12585
12586 /* create the event */
12587 memset(&wrqu, 0, sizeof(wrqu));
12588 memset(metrics_notification, 0, sizeof(metrics_notification));
12589
12590 wrqu.data.pointer = metrics_notification;
12591 wrqu.data.length = scnprintf(metrics_notification,
12592 sizeof(metrics_notification),
12593 "QCOM: LFR_PREAUTH_HANDOVER "
12594 MAC_ADDRESS_STR,
12595 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12596
12597 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12598 metrics_notification);
12599
12600 EXIT();
12601
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012602 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012603}
12604#endif
12605
12606/**
12607 * hdd_select_cbmode() - select channel bonding mode
12608 * @pAdapter: Pointer to adapter
12609 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012610 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012611 *
12612 * Return: none
12613 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012614void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12615 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012616{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012617 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012618 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012619 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012620
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012621 /*
12622 * CDS api expects secondary channel for calculating
12623 * the channel params
12624 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012625 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012626 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12627 if (operationChannel >= 1 && operationChannel <= 5)
12628 sec_ch = operationChannel + 4;
12629 else if (operationChannel >= 6 && operationChannel <= 13)
12630 sec_ch = operationChannel - 4;
12631 }
12632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012633 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012634 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012635
12636 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012637 eHddDot11Mode hdd_dot11_mode;
12638 uint8_t iniDot11Mode =
12639 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12640
12641 hdd_notice("Dot11Mode is %u", iniDot11Mode);
12642 switch (iniDot11Mode) {
12643 case eHDD_DOT11_MODE_AUTO:
12644 case eHDD_DOT11_MODE_11ac:
12645 case eHDD_DOT11_MODE_11ac_ONLY:
12646 if (sme_is_feature_supported_by_fw(DOT11AC))
12647 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12648 else
12649 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12650 break;
12651 case eHDD_DOT11_MODE_11n:
12652 case eHDD_DOT11_MODE_11n_ONLY:
12653 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12654 break;
12655 default:
12656 hdd_dot11_mode = iniDot11Mode;
12657 break;
12658 }
12659 ch_info->channel_width = ch_params->ch_width;
12660 ch_info->phy_mode =
12661 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012662 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012663 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012664 hdd_info("ch_info width %d, phymode %d channel %d",
12665 ch_info->channel_width, ch_info->phy_mode,
12666 ch_info->channel);
12667 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012668}
12669
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012670/**
12671 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12672 * @adapter: STA adapter
12673 * @roam_profile: STA roam profile
12674 *
12675 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12676 *
12677 * Return: false if sta-sap conc is not allowed, else return true
12678 */
12679static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12680 tCsrRoamProfile *roam_profile)
12681{
12682 hdd_context_t *hdd_ctx;
12683 hdd_adapter_t *ap_adapter;
12684 hdd_ap_ctx_t *hdd_ap_ctx;
12685 hdd_hostapd_state_t *hostapd_state;
12686 uint8_t channel = 0;
12687 QDF_STATUS status;
12688
12689 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12690 if (!hdd_ctx) {
12691 hdd_err("HDD context is NULL");
12692 return true;
12693 }
12694
12695 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12696 /* probably no sap running, no handling required */
12697 if (ap_adapter == NULL)
12698 return true;
12699
12700 /*
12701 * sap is not in started state, so it is fine to go ahead with sta.
12702 * if sap is currently doing CAC then don't allow sta to go further.
12703 */
12704 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12705 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12706 return true;
12707
12708 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12709 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12710 return false;
12711 }
12712
12713 /*
12714 * log and return error, if we allow STA to go through, we don't
12715 * know what is going to happen better stop sta connection
12716 */
12717 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12718 if (NULL == hdd_ap_ctx) {
12719 hdd_err("AP context not found");
12720 return false;
12721 }
12722
12723 /* sap is on non-dfs channel, nothing to handle */
12724 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
12725 hdd_info("sap is on non-dfs channel, sta is allowed");
12726 return true;
12727 }
12728 /*
12729 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012730 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012731 */
12732 status = cds_get_channel_from_scan_result(adapter,
12733 roam_profile, &channel);
12734
Nitesh Shah59774522016-09-16 15:14:21 +053012735 /*
12736 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12737 * channels for roaming case.
12738 */
12739 if (CDS_IS_CHANNEL_24GHZ(channel)) {
12740 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
12741 return true;
12742 }
12743
12744 /*
12745 * If channel is 0 or DFS then better to call pcl and find out the
12746 * best channel. If channel is non-dfs 5 GHz then better move SAP
12747 * to STA's channel to make scc, so we have room for 3port MCC
12748 * scenario.
12749 */
12750 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012751 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
12752 true);
12753
12754 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12755 qdf_event_reset(&hostapd_state->qdf_event);
12756 status = wlansap_set_channel_change_with_csa(
12757 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12758 hdd_ap_ctx->sapConfig.ch_width_orig);
12759
12760 if (QDF_STATUS_SUCCESS != status) {
12761 hdd_err("Set channel with CSA IE failed, can't allow STA");
12762 return false;
12763 }
12764
12765 /*
12766 * wait here for SAP to finish the channel switch. When channel
12767 * switch happens, SAP sends few beacons with CSA_IE. After
12768 * successfully Transmission of those beacons, it will move its
12769 * state from started to disconnected and move to new channel.
12770 * once it moves to new channel, sap again moves its state
12771 * machine from disconnected to started and set this event.
12772 * wait for 10 secs to finish this.
12773 */
12774 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12775 if (!QDF_IS_STATUS_SUCCESS(status)) {
12776 hdd_err("wait for qdf_event failed, STA not allowed!!");
12777 return false;
12778 }
12779
12780 return true;
12781}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012782
Krunal Soni31949422016-07-29 17:17:53 -070012783/**
12784 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012785 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012786 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012787 * @ssid_len: Length of ssid
12788 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012789 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012790 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012791 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012792 *
12793 * This function is used to start the association process
12794 *
12795 * Return: 0 for success, non-zero for failure
12796 */
Krunal Soni31949422016-07-29 17:17:53 -070012797static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012798 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012799 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012800 u8 operatingChannel,
12801 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012802{
12803 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012804 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012805 hdd_wext_state_t *pWextState;
12806 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012807 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012808 uint32_t roamId;
12809 tCsrRoamProfile *pRoamProfile;
12810 eCsrAuthType RSNAuthType;
12811 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012812 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012813
12814 ENTER();
12815
12816 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12817 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012818 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012819
12820 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012821 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012822 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012823
12824 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012825 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012826 status = -EINVAL;
12827 goto ret_status;
12828 }
12829
12830 if (true == cds_is_connection_in_progress()) {
12831 hdd_err("Connection refused: conn in progress");
12832 status = -EINVAL;
12833 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012834 }
12835
12836 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053012837 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
12838 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012839
12840 if (pRoamProfile) {
12841 hdd_station_ctx_t *pHddStaCtx;
12842 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12843
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012844 /* Restart the opportunistic timer
12845 *
12846 * If hw_mode_change_in_progress is true, then wait
12847 * till firmware sends the callback for hw_mode change.
12848 *
12849 * Else set connect_in_progress as true and proceed.
12850 */
12851 cds_restart_opportunistic_timer(false);
12852 if (cds_is_hw_mode_change_in_progress()) {
12853 status = qdf_wait_for_connection_update();
12854 if (!QDF_IS_STATUS_SUCCESS(status)) {
12855 hdd_err("qdf wait for event failed!!");
12856 status = -EINVAL;
12857 goto ret_status;
12858 }
12859 }
12860 cds_set_connection_in_progress(true);
12861
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012862 if (HDD_WMM_USER_MODE_NO_QOS ==
12863 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
12864 /*QoS not enabled in cfg file */
12865 pRoamProfile->uapsd_mask = 0;
12866 } else {
12867 /*QoS enabled, update uapsd mask from cfg file */
12868 pRoamProfile->uapsd_mask =
12869 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
12870 }
12871
12872 pRoamProfile->SSIDs.numOfSSIDs = 1;
12873 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012874 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012875 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012876 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012877 ssid, ssid_len);
12878
Deepak Dhamdherea2785822016-11-17 01:17:45 -080012879 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012880 /* cleanup bssid hint */
12881 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
12882 QDF_MAC_ADDR_SIZE);
12883 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
12884 QDF_MAC_ADDR_SIZE);
12885
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012886 if (bssid) {
12887 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053012888 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012889 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012890 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012891 /*
12892 * Save BSSID in seperate variable as
12893 * pRoamProfile's BSSID is getting zeroed out in the
12894 * association process. In case of join failure
12895 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012896 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012897 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012898 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012899 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012900 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012901 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
12902 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012903 /*
12904 * Save BSSID in a separate variable as
12905 * pRoamProfile's BSSID is getting zeroed out in the
12906 * association process. In case of join failure
12907 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012908 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012909 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012910 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012911 hdd_info("bssid_hint is given by upper layer %pM",
12912 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012913 }
12914
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012915 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012916 pRoamProfile->SSIDs.SSIDList->SSID.length,
12917 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
12918 operatingChannel);
12919
12920 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
12921 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012922 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012923 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
12924 }
12925#ifdef FEATURE_WLAN_WAPI
12926 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012927 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012928 switch (pAdapter->wapi_info.wapiAuthMode) {
12929 case WAPI_AUTH_MODE_PSK:
12930 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012931 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012932 pAdapter->wapi_info.wapiAuthMode);
12933 pRoamProfile->AuthType.authType[0] =
12934 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
12935 break;
12936 }
12937 case WAPI_AUTH_MODE_CERT:
12938 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012939 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012940 pAdapter->wapi_info.wapiAuthMode);
12941 pRoamProfile->AuthType.authType[0] =
12942 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
12943 break;
12944 }
12945 } /* End of switch */
12946 if (pAdapter->wapi_info.wapiAuthMode ==
12947 WAPI_AUTH_MODE_PSK
12948 || pAdapter->wapi_info.wapiAuthMode ==
12949 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012950 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012951 pRoamProfile->AuthType.numEntries = 1;
12952 pRoamProfile->EncryptionType.numEntries = 1;
12953 pRoamProfile->EncryptionType.encryptionType[0] =
12954 eCSR_ENCRYPT_TYPE_WPI;
12955 pRoamProfile->mcEncryptionType.numEntries = 1;
12956 pRoamProfile->mcEncryptionType.
12957 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
12958 }
12959 }
Krunal Soni31949422016-07-29 17:17:53 -070012960#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012961#ifdef WLAN_FEATURE_GTK_OFFLOAD
12962 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080012963 if ((QDF_STA_MODE == pAdapter->device_mode) ||
12964 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012965 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
12966 sizeof(tSirGtkOffloadParams));
12967 pHddStaCtx->gtkOffloadReqParams.ulFlags =
12968 GTK_OFFLOAD_DISABLE;
12969 }
12970#endif
12971 pRoamProfile->csrPersona = pAdapter->device_mode;
12972
12973 if (operatingChannel) {
12974 pRoamProfile->ChannelInfo.ChannelList =
12975 &operatingChannel;
12976 pRoamProfile->ChannelInfo.numOfChannels = 1;
12977 } else {
12978 pRoamProfile->ChannelInfo.ChannelList = NULL;
12979 pRoamProfile->ChannelInfo.numOfChannels = 0;
12980 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012981 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012982 && operatingChannel) {
12983 /*
12984 * Need to post the IBSS power save parameters
12985 * to WMA. WMA will configure this parameters
12986 * to firmware if power save is enabled by the
12987 * firmware.
12988 */
12989 status = hdd_set_ibss_power_save_params(pAdapter);
12990
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012991 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012992 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053012993 status = -EINVAL;
12994 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012995 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012996 pRoamProfile->ch_params.ch_width =
12997 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053012998 /*
12999 * In IBSS mode while operating in 2.4 GHz,
13000 * the device supports only 20 MHz.
13001 */
13002 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13003 pRoamProfile->ch_params.ch_width =
13004 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013005 hdd_select_cbmode(pAdapter, operatingChannel,
13006 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013007 }
Abhishek Singh99bce862016-06-20 15:10:51 +053013008 /*
13009 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13010 * or pmf=2 is an explicit configuration in the supplicant
13011 * configuration, drop the connection request.
13012 */
13013 if (pWextState->roamProfile.MFPEnabled &&
13014 !(pWextState->roamProfile.MFPRequired ||
13015 pWextState->roamProfile.MFPCapable)) {
13016 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13017 pWextState->roamProfile.MFPEnabled,
13018 pWextState->roamProfile.MFPRequired,
13019 pWextState->roamProfile.MFPCapable);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013020
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013021 status = -EINVAL;
13022 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013023 }
13024
Krunal Soni31949422016-07-29 17:17:53 -070013025 /*
13026 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013027 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013028 * enhancements, the supplicant is not issuing the scan command
13029 * now. So the unicast frames which are sent from the host are
13030 * not having the additional IEs. If it is P2P CLIENT and there
13031 * is no additional IE present in roamProfile, then use the
13032 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013033 */
13034
Krunal Sonib4326f22016-03-10 13:05:51 -080013035 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013036 (!pRoamProfile->pAddIEScan)) {
13037 pRoamProfile->pAddIEScan =
13038 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13039 pRoamProfile->nAddIEScanLength =
13040 pAdapter->scan_info.scanAddIE.length;
13041 }
13042 /*
13043 * When policy manager is enabled from ini file, we shouldn't
13044 * check for other concurrency rules.
13045 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070013046 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080013047 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013048 if (true != cds_handle_conc_rule2(
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013049 pAdapter, pRoamProfile, &roamId)) {
13050 status = 0;
13051 goto conn_failure;
13052 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013053 }
13054
Krunal Soni3091bcc2016-06-23 12:28:21 -070013055 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013056 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
13057 pRoamProfile))) {
13058 hdd_err("sap-sta conc will fail, can't allow sta");
13059 hdd_conn_set_connection_state(pAdapter,
13060 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013061 status = -ENOMEM;
13062 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013063 }
13064
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013065 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013066 if (!sme_config) {
13067 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013068 hdd_conn_set_connection_state(pAdapter,
13069 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013070 status = -ENOMEM;
13071 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013072 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013073 sme_get_config_param(pHddCtx->hHal, sme_config);
13074 /* These values are not sessionized. So, any change in these SME
13075 * configs on an older or parallel interface will affect the
13076 * cb mode. So, restoring the default INI params before starting
13077 * interfaces such as sta, cli etc.,
13078 */
13079 sme_config->csrConfig.channelBondingMode5GHz =
13080 pHddCtx->config->nChannelBondingMode5GHz;
13081 sme_config->csrConfig.channelBondingMode24GHz =
13082 pHddCtx->config->nChannelBondingMode24GHz;
13083 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013084 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013085 /*
13086 * Change conn_state to connecting before sme_roam_connect(),
13087 * because sme_roam_connect() has a direct path to call
13088 * hdd_sme_roam_callback(), which will change the conn_state
13089 * If direct path, conn_state will be accordingly changed to
13090 * NotConnected or Associated by either
13091 * hdd_association_completion_handler() or
13092 * hdd_dis_connect_handler() in sme_RoamCallback()if
13093 * sme_RomConnect is to be queued,
13094 * Connecting state will remain until it is completed.
13095 *
13096 * If connection state is not changed, connection state will
13097 * remain in eConnectionState_NotConnected state.
13098 * In hdd_association_completion_handler, "hddDisconInProgress"
13099 * is set to true if conn state is
13100 * eConnectionState_NotConnected.
13101 * If "hddDisconInProgress" is set to true then cfg80211 layer
13102 * is not informed of connect result indication which
13103 * is an issue.
13104 */
13105 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013106 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013107 hdd_conn_set_connection_state(pAdapter,
13108 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013109
Komal Seelama89be8d2016-09-29 11:09:26 +053013110 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13111 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013112 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013113 pAdapter->sessionId, pRoamProfile,
13114 &roamId);
13115
Rajeev Kumard31e1542017-01-13 14:37:42 -080013116 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013117 (QDF_STA_MODE == pAdapter->device_mode ||
13118 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013119 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013120 "qdf_status %d. -> NotConnected",
13121 pAdapter->sessionId, qdf_status);
13122 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013123 /* change back to NotAssociated */
13124 hdd_conn_set_connection_state(pAdapter,
13125 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013126 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13127 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013128 }
13129
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013130 /* Reset connect_in_progress */
13131 cds_set_connection_in_progress(false);
13132
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013133 pRoamProfile->ChannelInfo.ChannelList = NULL;
13134 pRoamProfile->ChannelInfo.numOfChannels = 0;
13135
Nitesh Shah044fd672016-10-13 18:53:25 +053013136 if ((QDF_STA_MODE == pAdapter->device_mode)
Krunal Soni4274f362016-12-14 19:55:25 -080013137 && wma_is_current_hwmode_dbs()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053013138 cds_get_channel_from_scan_result(pAdapter,
13139 pRoamProfile, &channel);
13140 if (channel)
13141 cds_checkn_update_hw_mode_single_mac_mode
13142 (channel);
13143 }
13144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013145 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013146 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013147 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013148 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013149 goto ret_status;
13150
13151conn_failure:
13152 /* Reset connect_in_progress */
13153 cds_set_connection_in_progress(false);
13154
13155ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013156 EXIT();
13157 return status;
13158}
13159
13160/**
13161 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13162 * @pAdapter: Pointer to adapter
13163 * @auth_type: Auth type
13164 *
13165 * This function is used to set the authentication type (OPEN/SHARED).
13166 *
13167 * Return: 0 for success, non-zero for failure
13168 */
13169static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13170 enum nl80211_auth_type auth_type)
13171{
13172 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13173 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13174
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013175 /*set authentication type */
13176 switch (auth_type) {
13177 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013178 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013179 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13180 break;
13181
13182 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013183 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013184 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013185 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13186 break;
13187
13188 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013189 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013190 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13191 break;
13192#ifdef FEATURE_WLAN_ESE
13193 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013194 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013195 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13196 break;
13197#endif
13198
13199 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013200 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013201 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13202 return -EINVAL;
13203 }
13204
13205 pWextState->roamProfile.AuthType.authType[0] =
13206 pHddStaCtx->conn_info.authType;
13207 return 0;
13208}
13209
13210/**
13211 * wlan_hdd_set_akm_suite() - set key management type
13212 * @pAdapter: Pointer to adapter
13213 * @key_mgmt: Key management type
13214 *
13215 * This function is used to set the key mgmt type(PSK/8021x).
13216 *
13217 * Return: 0 for success, non-zero for failure
13218 */
13219static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13220{
13221 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13222
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013223#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
13224#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
13225 /*set key mgmt type */
13226 switch (key_mgmt) {
13227 case WLAN_AKM_SUITE_PSK:
13228 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013229 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013230 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013231 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13232 break;
13233
13234 case WLAN_AKM_SUITE_8021X_SHA256:
13235 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013236 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013237 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013238 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13239 break;
13240#ifdef FEATURE_WLAN_ESE
13241#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13242#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13243 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013244 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013245 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13246 break;
13247#endif
13248#ifndef WLAN_AKM_SUITE_OSEN
13249#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13250#endif
13251 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013252 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013253 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13254 break;
13255
13256 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013257 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013258 return -EINVAL;
13259
13260 }
13261 return 0;
13262}
13263
13264/**
13265 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13266 * @pAdapter: Pointer to adapter
13267 * @cipher: Cipher type
13268 * @ucast: Unicast flag
13269 *
13270 * This function is used to set the encryption type
13271 * (NONE/WEP40/WEP104/TKIP/CCMP).
13272 *
13273 * Return: 0 for success, non-zero for failure
13274 */
13275static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13276 u32 cipher, bool ucast)
13277{
13278 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13279 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13280 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13281
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013282 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013283 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013284 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13285 } else {
13286
13287 /*set encryption method */
13288 switch (cipher) {
13289 case IW_AUTH_CIPHER_NONE:
13290 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13291 break;
13292
13293 case WLAN_CIPHER_SUITE_WEP40:
13294 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13295 break;
13296
13297 case WLAN_CIPHER_SUITE_WEP104:
13298 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13299 break;
13300
13301 case WLAN_CIPHER_SUITE_TKIP:
13302 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13303 break;
13304
13305 case WLAN_CIPHER_SUITE_CCMP:
13306 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13307 break;
13308#ifdef FEATURE_WLAN_WAPI
13309 case WLAN_CIPHER_SUITE_SMS4:
13310 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13311 break;
13312#endif
13313
13314#ifdef FEATURE_WLAN_ESE
13315 case WLAN_CIPHER_SUITE_KRK:
13316 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13317 break;
13318#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13319 case WLAN_CIPHER_SUITE_BTK:
13320 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13321 break;
13322#endif
13323#endif
13324 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013325 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013326 return -EOPNOTSUPP;
13327 }
13328 }
13329
13330 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013331 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013332 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13333 pWextState->roamProfile.EncryptionType.numEntries = 1;
13334 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13335 encryptionType;
13336 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013337 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013338 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13339 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13340 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13341 encryptionType;
13342 }
13343
13344 return 0;
13345}
13346
13347/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013348 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13349 * @wext_state: Pointer to wext state
13350 * @gen_ie: Pointer to IE data
13351 * @len: length of IE data
13352 *
13353 * Return: 0 for success, non-zero for failure
13354 */
13355static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13356 const uint8_t *gen_ie, uint16_t len)
13357{
13358 uint16_t cur_add_ie_len =
13359 wext_state->assocAddIE.length;
13360
13361 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13362 (wext_state->assocAddIE.length + len)) {
13363 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13364 QDF_ASSERT(0);
13365 return -ENOMEM;
13366 }
13367 memcpy(wext_state->assocAddIE.addIEdata +
13368 cur_add_ie_len, gen_ie, len);
13369 wext_state->assocAddIE.length += len;
13370
13371 wext_state->roamProfile.pAddIEAssoc =
13372 wext_state->assocAddIE.addIEdata;
13373 wext_state->roamProfile.nAddIEAssocLength =
13374 wext_state->assocAddIE.length;
13375 return 0;
13376}
13377
13378/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013379 * wlan_hdd_cfg80211_set_ie() - set IEs
13380 * @pAdapter: Pointer to adapter
13381 * @ie: Pointer ot ie
13382 * @ie: IE length
13383 *
13384 * Return: 0 for success, non-zero for failure
13385 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013386static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013387 size_t ie_len)
13388{
13389 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13390 const uint8_t *genie = ie;
13391 uint16_t remLen = ie_len;
13392#ifdef FEATURE_WLAN_WAPI
13393 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13394 u16 *tmp;
13395 uint16_t akmsuiteCount;
13396 int *akmlist;
13397#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013398 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013399
13400 /* clear previous assocAddIE */
13401 pWextState->assocAddIE.length = 0;
13402 pWextState->roamProfile.bWPSAssociation = false;
13403 pWextState->roamProfile.bOSENAssociation = false;
13404
13405 while (remLen >= 2) {
13406 uint16_t eLen = 0;
13407 uint8_t elementId;
13408 elementId = *genie++;
13409 eLen = *genie++;
13410 remLen -= 2;
13411
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013412 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013413
13414 switch (elementId) {
13415 case DOT11F_EID_WPA:
13416 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 -070013417 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013418 return -EINVAL;
13419 } else if (0 ==
13420 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13421 uint16_t curAddIELen =
13422 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013423 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013424
13425 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13426 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013427 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013428 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013429 return -ENOMEM;
13430 }
13431 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13432 memcpy(pWextState->assocAddIE.addIEdata +
13433 curAddIELen, genie - 2, eLen + 2);
13434 pWextState->assocAddIE.length += eLen + 2;
13435
13436 pWextState->roamProfile.bWPSAssociation = true;
13437 pWextState->roamProfile.pAddIEAssoc =
13438 pWextState->assocAddIE.addIEdata;
13439 pWextState->roamProfile.nAddIEAssocLength =
13440 pWextState->assocAddIE.length;
13441 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013442 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013443 memset(pWextState->WPARSNIE, 0,
13444 MAX_WPA_RSN_IE_LEN);
13445 memcpy(pWextState->WPARSNIE, genie - 2,
13446 (eLen + 2));
13447 pWextState->roamProfile.pWPAReqIE =
13448 pWextState->WPARSNIE;
13449 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13450 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13451 P2P_OUI_TYPE_SIZE))) {
13452 uint16_t curAddIELen =
13453 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013454 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013455
13456 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13457 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013458 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013459 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013460 return -ENOMEM;
13461 }
13462 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13463 memcpy(pWextState->assocAddIE.addIEdata +
13464 curAddIELen, genie - 2, eLen + 2);
13465 pWextState->assocAddIE.length += eLen + 2;
13466
13467 pWextState->roamProfile.pAddIEAssoc =
13468 pWextState->assocAddIE.addIEdata;
13469 pWextState->roamProfile.nAddIEAssocLength =
13470 pWextState->assocAddIE.length;
13471 }
13472#ifdef WLAN_FEATURE_WFD
13473 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13474 WFD_OUI_TYPE_SIZE)) &&
13475 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013476 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013477 pAdapter->device_mode)) {
13478 uint16_t curAddIELen =
13479 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013480 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013481
13482 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13483 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013484 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013485 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013486 return -ENOMEM;
13487 }
13488 /* WFD IE is saved to Additional IE ; it should
13489 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013490 * WFD IE
13491 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013492 memcpy(pWextState->assocAddIE.addIEdata +
13493 curAddIELen, genie - 2, eLen + 2);
13494 pWextState->assocAddIE.length += eLen + 2;
13495
13496 pWextState->roamProfile.pAddIEAssoc =
13497 pWextState->assocAddIE.addIEdata;
13498 pWextState->roamProfile.nAddIEAssocLength =
13499 pWextState->assocAddIE.length;
13500 }
13501#endif
13502 /* Appending HS 2.0 Indication Element in Assiciation Request */
13503 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13504 HS20_OUI_TYPE_SIZE))) {
13505 uint16_t curAddIELen =
13506 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013507 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013508
13509 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13510 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013511 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013512 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013513 return -ENOMEM;
13514 }
13515 memcpy(pWextState->assocAddIE.addIEdata +
13516 curAddIELen, genie - 2, eLen + 2);
13517 pWextState->assocAddIE.length += eLen + 2;
13518
13519 pWextState->roamProfile.pAddIEAssoc =
13520 pWextState->assocAddIE.addIEdata;
13521 pWextState->roamProfile.nAddIEAssocLength =
13522 pWextState->assocAddIE.length;
13523 }
13524 /* Appending OSEN Information Element in Assiciation Request */
13525 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13526 OSEN_OUI_TYPE_SIZE))) {
13527 uint16_t curAddIELen =
13528 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013529 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013530
13531 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13532 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013533 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013534 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013535 return -ENOMEM;
13536 }
13537 memcpy(pWextState->assocAddIE.addIEdata +
13538 curAddIELen, genie - 2, eLen + 2);
13539 pWextState->assocAddIE.length += eLen + 2;
13540
13541 pWextState->roamProfile.bOSENAssociation = true;
13542 pWextState->roamProfile.pAddIEAssoc =
13543 pWextState->assocAddIE.addIEdata;
13544 pWextState->roamProfile.nAddIEAssocLength =
13545 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013546 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13547 MBO_OUI_TYPE_SIZE))){
13548 hdd_info("Set MBO IE(len %d)", eLen + 2);
13549 status = wlan_hdd_add_assoc_ie(pWextState,
13550 genie - 2, eLen + 2);
13551 if (status)
13552 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013553 } else {
13554 uint16_t add_ie_len =
13555 pWextState->assocAddIE.length;
13556
13557 hdd_info("Set OSEN IE(len %d)", eLen + 2);
13558
13559 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13560 (pWextState->assocAddIE.length + eLen)) {
13561 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013562 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013563 return -ENOMEM;
13564 }
13565
13566 memcpy(pWextState->assocAddIE.addIEdata +
13567 add_ie_len, genie - 2, eLen + 2);
13568 pWextState->assocAddIE.length += eLen + 2;
13569
13570 pWextState->roamProfile.pAddIEAssoc =
13571 pWextState->assocAddIE.addIEdata;
13572 pWextState->roamProfile.nAddIEAssocLength =
13573 pWextState->assocAddIE.length;
13574 }
13575 break;
13576 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013577 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013578 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13579 memcpy(pWextState->WPARSNIE, genie - 2,
13580 (eLen + 2));
13581 pWextState->roamProfile.pRSNReqIE =
13582 pWextState->WPARSNIE;
13583 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13584 break;
13585 /*
13586 * Appending Extended Capabilities with Interworking bit set
13587 * in Assoc Req.
13588 *
13589 * In assoc req this EXT Cap will only be taken into account if
13590 * interworkingService bit is set to 1. Currently
13591 * driver is only interested in interworkingService capability
13592 * from supplicant. If in future any other EXT Cap info is
13593 * required from supplicat, it needs to be handled while
13594 * sending Assoc Req in LIM.
13595 */
13596 case DOT11F_EID_EXTCAP:
13597 {
13598 uint16_t curAddIELen =
13599 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013600 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013601
13602 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13603 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013604 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013605 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013606 return -ENOMEM;
13607 }
13608 memcpy(pWextState->assocAddIE.addIEdata +
13609 curAddIELen, genie - 2, eLen + 2);
13610 pWextState->assocAddIE.length += eLen + 2;
13611
13612 pWextState->roamProfile.pAddIEAssoc =
13613 pWextState->assocAddIE.addIEdata;
13614 pWextState->roamProfile.nAddIEAssocLength =
13615 pWextState->assocAddIE.length;
13616 break;
13617 }
13618#ifdef FEATURE_WLAN_WAPI
13619 case WLAN_EID_WAPI:
13620 /* Setting WAPI Mode to ON=1 */
13621 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013622 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013623 tmp = (u16 *) ie;
13624 tmp = tmp + 2; /* Skip element Id and Len, Version */
13625 akmsuiteCount = WPA_GET_LE16(tmp);
13626 tmp = tmp + 1;
13627 akmlist = (int *)(tmp);
13628 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13629 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13630 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013631 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013632 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013633 return -EINVAL;
13634 }
13635
13636 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013637 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013638 pAdapter->wapi_info.wapiAuthMode =
13639 WAPI_AUTH_MODE_PSK;
13640 }
13641 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013642 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013643 pAdapter->wapi_info.wapiAuthMode =
13644 WAPI_AUTH_MODE_CERT;
13645 }
13646 break;
13647#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013648 case DOT11F_EID_SUPPOPERATINGCLASSES:
13649 {
13650 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
13651 status = wlan_hdd_add_assoc_ie(pWextState,
13652 genie - 2, eLen + 2);
13653 if (status)
13654 return status;
13655 break;
13656 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013657 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013658 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013659 /* when Unknown IE is received we break
13660 * and continue to the next IE in the buffer
13661 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013662 break;
13663 }
13664 genie += eLen;
13665 remLen -= eLen;
13666 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013667 return 0;
13668}
13669
13670/**
13671 * hdd_is_wpaie_present() - check for WPA ie
13672 * @ie: Pointer to ie
13673 * @ie_len: Ie length
13674 *
13675 * Parse the received IE to find the WPA IE
13676 *
13677 * Return: true if wpa ie is found else false
13678 */
13679static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13680{
13681 uint8_t eLen = 0;
13682 uint16_t remLen = ie_len;
13683 uint8_t elementId = 0;
13684
13685 while (remLen >= 2) {
13686 elementId = *ie++;
13687 eLen = *ie++;
13688 remLen -= 2;
13689 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013690 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013691 return false;
13692 }
13693 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13694 /* OUI - 0x00 0X50 0XF2
13695 * WPA Information Element - 0x01
13696 * WPA version - 0x01
13697 */
13698 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13699 return true;
13700 }
13701 ie += eLen;
13702 remLen -= eLen;
13703 }
13704 return false;
13705}
13706
13707/**
13708 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13709 * @pAdapter: Pointer to adapter
13710 * @req: Pointer to security parameters
13711 *
13712 * Return: 0 for success, non-zero for failure
13713 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013714static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13715 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013716{
13717 int status = 0;
13718 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13719 ENTER();
13720
13721 /*set wpa version */
13722 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13723
13724 if (req->crypto.wpa_versions) {
13725 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13726 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13727 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13728 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13729 }
13730 }
13731
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013732 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013733
13734 /*set authentication type */
13735 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13736
13737 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013738 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013739 return status;
13740 }
13741
13742 /*set key mgmt type */
13743 if (req->crypto.n_akm_suites) {
13744 status =
13745 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13746 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013747 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013748 return status;
13749 }
13750 }
13751
13752 /*set pairwise cipher type */
13753 if (req->crypto.n_ciphers_pairwise) {
13754 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13755 req->crypto.
13756 ciphers_pairwise[0],
13757 true);
13758 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013759 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013760 return status;
13761 }
13762 } else {
13763 /*Reset previous cipher suite to none */
13764 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13765 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013766 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013767 return status;
13768 }
13769 }
13770
13771 /*set group cipher type */
13772 status =
13773 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13774 false);
13775
13776 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013777 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013778 return status;
13779 }
13780#ifdef WLAN_FEATURE_11W
13781 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13782#endif
13783
13784 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13785 if (req->ie_len) {
13786 status =
13787 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13788 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013789 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013790 return status;
13791 }
13792 }
13793
13794 /*incase of WEP set default key information */
13795 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013796 u8 key_len = req->key_len;
13797 u8 key_idx = req->key_idx;
13798
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013799 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13800 || (WLAN_CIPHER_SUITE_WEP104 ==
13801 req->crypto.ciphers_pairwise[0])
13802 ) {
13803 if (IW_AUTH_KEY_MGMT_802_1X
13804 ==
13805 (pWextState->
13806 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013807 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013808 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013809 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013810
Jeff Johnson68755312017-02-10 11:46:55 -080013811 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13812 && (CSR_MAX_NUM_KEY > key_idx)) {
13813 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
13814 key_idx, key_len);
13815 qdf_mem_copy(&pWextState->roamProfile.
13816 Keys.
13817 KeyMaterial[key_idx][0],
13818 req->key, key_len);
13819 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013820 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013821 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013822 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013823 }
13824 }
13825 }
13826
13827 return status;
13828}
13829
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013830int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013831{
13832 unsigned long rc;
13833 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013834 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013835
13836 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13837
Jeff Johnson9edf9572016-10-03 15:24:49 -070013838 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053013839 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
13840 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
13841 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013842 hdd_conn_set_connection_state(pAdapter,
13843 eConnectionState_Disconnecting);
13844 /* Issue disconnect to CSR */
13845 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013846
13847 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13848 pAdapter->sessionId,
13849 eCSR_DISCONNECT_REASON_UNSPECIFIED);
13850 /*
13851 * Wait here instead of returning directly, this will block the
13852 * next connect command and allow processing of the scan for
13853 * ssid and the previous connect command in CSR. Else we might
13854 * hit some race conditions leading to SME and HDD out of sync.
13855 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013856 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013857 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
13858 } else if (0 != status) {
13859 hdd_err("csrRoamDisconnect failure, returned %d",
13860 (int)status);
13861 pHddStaCtx->staDebugState = status;
13862 result = -EINVAL;
13863 goto disconnected;
13864 }
13865
13866 rc = wait_for_completion_timeout(
13867 &pAdapter->disconnect_comp_var,
13868 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013869 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013870 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
13871 pAdapter->sessionId, pHddStaCtx->staDebugState);
13872 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013873 }
13874 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013875 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013876 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013877 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013878 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013879 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013880 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013881 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013882 }
13883 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013884disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013885 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13886 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013887}
13888
13889/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013890 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
13891 * @adapter: Pointer to the HDD adapter
13892 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070013893 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013894 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013895 * This function will start reassociation if prev_bssid is set and bssid/
13896 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013897 *
Naveen Rawat07332902016-07-27 09:13:17 -070013898 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013899 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053013900#if defined(CFG80211_CONNECT_PREV_BSSID) || \
13901 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070013902static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13903 struct cfg80211_connect_params *req,
13904 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013905{
Naveen Rawat07332902016-07-27 09:13:17 -070013906 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013907 const uint8_t *bssid = NULL;
13908 uint16_t channel = 0;
13909
13910 if (req->bssid)
13911 bssid = req->bssid;
13912 else if (req->bssid_hint)
13913 bssid = req->bssid_hint;
13914
13915 if (req->channel)
13916 channel = req->channel->hw_value;
13917 else if (req->channel_hint)
13918 channel = req->channel_hint->hw_value;
13919
13920 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070013921 reassoc = true;
13922 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013923 channel, MAC_ADDR_ARRAY(bssid));
13924 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013925 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070013926 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013927 }
Naveen Rawat07332902016-07-27 09:13:17 -070013928 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013929}
13930#else
Naveen Rawat07332902016-07-27 09:13:17 -070013931static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13932 struct cfg80211_connect_params *req,
13933 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013934{
Naveen Rawat07332902016-07-27 09:13:17 -070013935 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013936}
13937#endif
13938
13939/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013940 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
13941 * @wiphy: Pointer to wiphy
13942 * @dev: Pointer to network device
13943 * @req: Pointer to cfg80211 connect request
13944 *
13945 * This function is used to start the association process
13946 *
13947 * Return: 0 for success, non-zero for failure
13948 */
13949static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13950 struct net_device *ndev,
13951 struct cfg80211_connect_params *req)
13952{
13953 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013954 u16 channel;
13955#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
13956 const u8 *bssid_hint = req->bssid_hint;
13957#else
13958 const u8 *bssid_hint = NULL;
13959#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013960 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
13961 hdd_context_t *pHddCtx;
13962
13963 ENTER();
13964
Anurag Chouhan6d760662016-02-20 16:05:43 +053013965 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013966 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013967 return -EINVAL;
13968 }
13969
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013970 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13971 hdd_err("invalid session id: %d", pAdapter->sessionId);
13972 return -EINVAL;
13973 }
13974
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013975 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013976 TRACE_CODE_HDD_CFG80211_CONNECT,
13977 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013978 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013979 hdd_device_mode_to_string(pAdapter->device_mode),
13980 pAdapter->device_mode);
13981
Krunal Sonib4326f22016-03-10 13:05:51 -080013982 if (pAdapter->device_mode != QDF_STA_MODE &&
13983 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013984 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013985 hdd_device_mode_to_string(pAdapter->device_mode),
13986 pAdapter->device_mode);
13987 return -EINVAL;
13988 }
13989
13990 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13991 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013992 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013993 return -EINVAL;
13994 }
13995
13996 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013997 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013998 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013999
Naveen Rawat07332902016-07-27 09:13:17 -070014000 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014001 return status;
14002
Agrawal Ashishf156e942016-08-04 14:54:47 +053014003 /* Try disconnecting if already in connected state */
14004 status = wlan_hdd_try_disconnect(pAdapter);
14005 if (0 > status) {
14006 hdd_err("Failed to disconnect the existing connection");
14007 return -EALREADY;
14008 }
14009
14010 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014011 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014012 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014013 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014014 pAdapter->device_mode),
14015 req->channel->hw_value, HW_MODE_20_MHZ)) {
14016 hdd_err("This concurrency combination is not allowed");
14017 return -ECONNREFUSED;
14018 }
14019 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014020 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080014021 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014022 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
14023 hdd_err("This concurrency combination is not allowed");
14024 return -ECONNREFUSED;
14025 }
14026 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014027
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014028 /*initialise security parameters */
14029 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14030
14031 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014032 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014033 return status;
14034 }
14035
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014036 if (req->channel)
14037 channel = req->channel->hw_value;
14038 else
14039 channel = 0;
14040 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14041 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014042 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014043 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014044 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014045 return status;
14046 }
14047 EXIT();
14048 return status;
14049}
14050
14051/**
14052 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14053 * @wiphy: Pointer to wiphy
14054 * @dev: Pointer to network device
14055 * @req: Pointer to cfg80211 connect request
14056 *
14057 * Return: 0 for success, non-zero for failure
14058 */
14059static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14060 struct net_device *ndev,
14061 struct cfg80211_connect_params *req)
14062{
14063 int ret;
14064 cds_ssr_protect(__func__);
14065 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14066 cds_ssr_unprotect(__func__);
14067
14068 return ret;
14069}
14070
14071/**
14072 * wlan_hdd_disconnect() - hdd disconnect api
14073 * @pAdapter: Pointer to adapter
14074 * @reason: Disconnect reason code
14075 *
14076 * This function is used to issue a disconnect request to SME
14077 *
14078 * Return: 0 for success, non-zero for failure
14079 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014080static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014081{
14082 int status, result = 0;
14083 unsigned long rc;
14084 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14085 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14086
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014087 ENTER();
14088
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014089 status = wlan_hdd_validate_context(pHddCtx);
14090
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014091 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014092 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014093
14094 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014095 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014096 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
14097 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014098 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014099 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14100 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14101
14102 /*issue disconnect */
14103
14104 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14105 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053014106 /*
14107 * Wait here instead of returning directly, this will block the next
14108 * connect command and allow processing of the scan for ssid and
14109 * the previous connect command in CSR. Else we might hit some
14110 * race conditions leading to SME and HDD out of sync.
14111 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014112 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014113 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014114 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014115 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014116 (int)status);
14117 pHddStaCtx->staDebugState = status;
14118 result = -EINVAL;
14119 goto disconnected;
14120 }
14121 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14122 msecs_to_jiffies
14123 (WLAN_WAIT_TIME_DISCONNECT));
14124
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014125 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014126 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014127 result = -ETIMEDOUT;
14128 }
14129disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014130 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14131#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14132 /* Sending disconnect event to userspace for kernel version < 3.11
14133 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14134 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014135 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014136 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14137 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014138#endif
14139
14140 return result;
14141}
14142
14143/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014144 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14145 * @reason: ieee80211 reason code.
14146 *
14147 * This utility function helps log string conversion of reason code.
14148 *
14149 * Return: string conversion of reason code, if match found;
14150 * "Unknown" otherwise.
14151 */
14152static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14153{
14154 switch (reason) {
14155 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14156 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14157 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14158 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14159 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14160 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14161 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14162 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14163 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14164 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14165 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14166 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14167 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14168 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14169 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14170 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14171 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14172 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14173 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14174 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14175 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14176 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14177 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14178 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14179 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14180 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14181 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14182 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14183 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14184 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14185 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14186 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14187 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14188 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14189 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14190 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14191 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14192 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14193 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14194 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14195 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14196 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14197 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14198 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14199 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14200 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14201 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14202 default:
14203 return "Unknown";
14204 }
14205}
14206
14207/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014208 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14209 * @wiphy: Pointer to wiphy
14210 * @dev: Pointer to network device
14211 * @reason: Disconnect reason code
14212 *
14213 * This function is used to issue a disconnect request to SME
14214 *
14215 * Return: 0 for success, non-zero for failure
14216 */
14217static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14218 struct net_device *dev, u16 reason)
14219{
14220 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14221 int status;
14222 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14223 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14224#ifdef FEATURE_WLAN_TDLS
14225 uint8_t staIdx;
14226#endif
14227
14228 ENTER();
14229
Anurag Chouhan6d760662016-02-20 16:05:43 +053014230 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014231 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014232 return -EINVAL;
14233 }
14234
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014235 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14236 hdd_err("invalid session id: %d", pAdapter->sessionId);
14237 return -EINVAL;
14238 }
14239
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014240 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014241 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14242 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014243 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014244 hdd_device_mode_to_string(pAdapter->device_mode),
14245 pAdapter->device_mode, reason);
14246
14247 status = wlan_hdd_validate_context(pHddCtx);
14248
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080014249 if (hdd_is_roaming_in_progress()) {
14250 hdd_err("Roaming In Progress. Ignore!!!");
14251 return -EAGAIN;
14252 }
14253
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014254 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014255 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014256
14257 /* Issue disconnect request to SME, if station is in connected state */
14258 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14259 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14260 eCsrRoamDisconnectReason reasonCode =
14261 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14262 hdd_scaninfo_t *pScanInfo;
14263
14264 switch (reason) {
14265 case WLAN_REASON_MIC_FAILURE:
14266 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14267 break;
14268
14269 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14270 case WLAN_REASON_DISASSOC_AP_BUSY:
14271 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14272 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14273 break;
14274
14275 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14276 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14277 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14278 break;
14279
14280 case WLAN_REASON_DEAUTH_LEAVING:
14281 reasonCode =
14282 pHddCtx->config->
14283 gEnableDeauthToDisassocMap ?
14284 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14285 eCSR_DISCONNECT_REASON_DEAUTH;
14286 break;
14287 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14288 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14289 break;
14290 default:
14291 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14292 break;
14293 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014294 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014295 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014296 pScanInfo = &pAdapter->scan_info;
14297 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014298 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014299 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014300 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014301 eCSR_SCAN_ABORT_DEFAULT);
14302 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014303 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014304#ifdef FEATURE_WLAN_TDLS
14305 /* First clean up the tdls peers if any */
14306 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14307 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14308 pAdapter->sessionId)
14309 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14310 uint8_t *mac;
14311 mac =
14312 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014313 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
14314 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014315 pHddCtx->tdlsConnInfo[staIdx].staId,
14316 pAdapter->sessionId,
14317 MAC_ADDR_ARRAY(mac));
14318 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14319 (pAdapter),
14320 pAdapter->sessionId, mac);
14321 }
14322 }
14323#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014324 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014325 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014326 hdd_info("Disconnect request from user space with reason: %s",
14327 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014328 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14329 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014330 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014331 return -EINVAL;
14332 }
14333 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014334 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014335 pHddStaCtx->conn_info.connState);
14336 }
14337
14338 return status;
14339}
14340
14341/**
14342 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14343 * @wiphy: Pointer to wiphy
14344 * @dev: Pointer to network device
14345 * @reason: Disconnect reason code
14346 *
14347 * Return: 0 for success, non-zero for failure
14348 */
14349static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14350 struct net_device *dev, u16 reason)
14351{
14352 int ret;
14353 cds_ssr_protect(__func__);
14354 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14355 cds_ssr_unprotect(__func__);
14356
14357 return ret;
14358}
14359
14360/**
14361 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14362 * @pAdapter: Pointer to adapter
14363 * @param: Pointer to IBSS parameters
14364 *
14365 * This function is used to initialize the security settings in IBSS mode
14366 *
14367 * Return: 0 for success, non-zero for failure
14368 */
14369static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14370 struct cfg80211_ibss_params
14371 *params)
14372{
14373 int status = 0;
14374 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14375 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14376 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14377
14378 ENTER();
14379
14380 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014381 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014382 pHddStaCtx->ibss_enc_key_installed = 0;
14383
14384 if (params->ie_len && (NULL != params->ie)) {
14385 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14386 params->ie_len, WLAN_EID_RSN)) {
14387 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14388 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14389 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14390 tDot11fIEWPA dot11WPAIE;
14391 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14392 u8 *ie;
14393
14394 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14395 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14396 params->ie_len,
14397 DOT11F_EID_WPA);
14398 if (NULL != ie) {
14399 pWextState->wpaVersion =
14400 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014401 /* Unpack the WPA IE
14402 * Skip past the EID byte and length byte
14403 * and four byte WiFi OUI
14404 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014405 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14406 &ie[2 + 4],
14407 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014408 /* Extract the multicast cipher, the
14409 * encType for unicast cipher for
14410 * wpa-none is none
14411 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014412 encryptionType =
14413 hdd_translate_wpa_to_csr_encryption_type
14414 (dot11WPAIE.multicast_cipher);
14415 }
14416 }
14417
14418 status =
14419 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14420 params->ie_len);
14421
14422 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014423 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014424 return status;
14425 }
14426 }
14427
14428 pWextState->roamProfile.AuthType.authType[0] =
14429 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14430
14431 if (params->privacy) {
14432 /* Security enabled IBSS, At this time there is no information
14433 * available about the security paramters, so initialise the
14434 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14435 * The correct security parameters will be updated later in
14436 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14437 * set inorder enable privacy bit in beacons
14438 */
14439
14440 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14441 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014442 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014443 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14444 pWextState->roamProfile.EncryptionType.numEntries = 1;
14445 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14446 encryptionType;
14447 return status;
14448}
14449
14450/**
14451 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14452 * @wiphy: Pointer to wiphy
14453 * @dev: Pointer to network device
14454 * @param: Pointer to IBSS join parameters
14455 *
14456 * This function is used to create/join an IBSS network
14457 *
14458 * Return: 0 for success, non-zero for failure
14459 */
14460static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14461 struct net_device *dev,
14462 struct cfg80211_ibss_params *params)
14463{
14464 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14465 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14466 tCsrRoamProfile *pRoamProfile;
14467 int status;
14468 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14469 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014470 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014471 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014472
14473 ENTER();
14474
Anurag Chouhan6d760662016-02-20 16:05:43 +053014475 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014476 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014477 return -EINVAL;
14478 }
14479
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014480 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14481 hdd_err("invalid session id: %d", pAdapter->sessionId);
14482 return -EINVAL;
14483 }
14484
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014485 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014486 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14487 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014488 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014489 hdd_device_mode_to_string(pAdapter->device_mode),
14490 pAdapter->device_mode);
14491
14492 status = wlan_hdd_validate_context(pHddCtx);
14493
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014494 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014495 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014496
14497 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014498 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014499 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14500 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14501 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14502 int indx;
14503
14504 /* Get channel number */
14505 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014506 params->
14507 chandef.
14508 chan->
14509 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014510
14511 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14512 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014513 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014514 return -EOPNOTSUPP;
14515 }
14516
14517 for (indx = 0; indx < numChans; indx++) {
14518 if (channelNum == validChan[indx]) {
14519 break;
14520 }
14521 }
14522 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014523 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014524 return -EINVAL;
14525 }
14526 }
14527
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014528 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014529 HW_MODE_20_MHZ)) {
14530 hdd_err("This concurrency combination is not allowed");
14531 return -ECONNREFUSED;
14532 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014533
Krunal Soni3091bcc2016-06-23 12:28:21 -070014534 status = qdf_reset_connection_update();
14535 if (!QDF_IS_STATUS_SUCCESS(status))
14536 hdd_err("ERR: clear event failed");
14537
14538 status = cds_current_connections_update(pAdapter->sessionId,
14539 channelNum,
14540 SIR_UPDATE_REASON_JOIN_IBSS);
14541 if (QDF_STATUS_E_FAILURE == status) {
14542 hdd_err("ERROR: connections update failed!!");
14543 return -EINVAL;
14544 }
14545
14546 if (QDF_STATUS_SUCCESS == status) {
14547 status = qdf_wait_for_connection_update();
14548 if (!QDF_IS_STATUS_SUCCESS(status)) {
14549 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014550 return -EINVAL;
14551 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014552 }
14553
14554 /*Try disconnecting if already in connected state */
14555 status = wlan_hdd_try_disconnect(pAdapter);
14556 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014557 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014558 return -EALREADY;
14559 }
14560
14561 pRoamProfile = &pWextState->roamProfile;
14562
14563 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014564 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014565 return -EINVAL;
14566 }
14567
14568 /* enable selected protection checks in IBSS mode */
14569 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14570
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014571 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014572 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14573 pHddCtx->config->
14574 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014575 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014576 }
14577
14578 /* BSSID is provided by upper layers hence no need to AUTO generate */
14579 if (NULL != params->bssid) {
14580 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014581 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014582 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014583 return -EIO;
14584 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014585 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014586 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14587 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014588 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014589 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014590 return -EIO;
14591 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014592 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014593 }
14594 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14595 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14596 pRoamProfile->beaconInterval = params->beacon_interval;
14597 else {
14598 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014599 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014600 params->beacon_interval, pRoamProfile->beaconInterval);
14601 }
14602
14603 /* Set Channel */
14604 if (channelNum) {
14605 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014606 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014607 pRoamProfile->ChannelInfo.numOfChannels = 1;
14608 pHddStaCtx->conn_info.operationChannel = channelNum;
14609 pRoamProfile->ChannelInfo.ChannelList =
14610 &pHddStaCtx->conn_info.operationChannel;
14611 }
14612
14613 /* Initialize security parameters */
14614 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14615 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014616 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014617 return status;
14618 }
14619
14620 /* Issue connect start */
14621 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14622 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014623 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014624 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014625 operationChannel,
14626 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014627
14628 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014629 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014630 return status;
14631 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014632 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014633 return 0;
14634}
14635
14636/**
14637 * wlan_hdd_cfg80211_join_ibss() - join ibss
14638 * @wiphy: Pointer to wiphy
14639 * @dev: Pointer to network device
14640 * @param: Pointer to IBSS join parameters
14641 *
14642 * This function is used to create/join an IBSS network
14643 *
14644 * Return: 0 for success, non-zero for failure
14645 */
14646static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14647 struct net_device *dev,
14648 struct cfg80211_ibss_params *params)
14649{
14650 int ret = 0;
14651
14652 cds_ssr_protect(__func__);
14653 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14654 cds_ssr_unprotect(__func__);
14655
14656 return ret;
14657}
14658
14659/**
14660 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14661 * @wiphy: Pointer to wiphy
14662 * @dev: Pointer to network device
14663 *
14664 * This function is used to leave an IBSS network
14665 *
14666 * Return: 0 for success, non-zero for failure
14667 */
14668static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14669 struct net_device *dev)
14670{
14671 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14672 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14673 tCsrRoamProfile *pRoamProfile;
14674 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14675 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014676 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014677 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014678 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014679
14680 ENTER();
14681
Anurag Chouhan6d760662016-02-20 16:05:43 +053014682 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014683 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014684 return -EINVAL;
14685 }
14686
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014687 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14688 hdd_err("invalid session id: %d", pAdapter->sessionId);
14689 return -EINVAL;
14690 }
14691
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014692 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014693 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14694 pAdapter->sessionId,
14695 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14696 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014697 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014698 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014699
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014700 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014701 hdd_device_mode_to_string(pAdapter->device_mode),
14702 pAdapter->device_mode);
14703 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014704 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014705 return -EIO;
14706 }
14707
14708 pRoamProfile = &pWextState->roamProfile;
14709
14710 /* Issue disconnect only if interface type is set to IBSS */
14711 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014712 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014713 return -EINVAL;
14714 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014715 /* Clearing add IE of beacon */
14716 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14717 sizeof(tSirMacAddr));
14718 updateIE.smeSessionId = pAdapter->sessionId;
14719 updateIE.ieBufferlength = 0;
14720 updateIE.pAdditionIEBuffer = NULL;
14721 updateIE.append = true;
14722 updateIE.notify = true;
14723 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14724 &updateIE,
14725 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014726 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014727 }
14728
14729 /* Reset WNI_CFG_PROBE_RSP Flags */
14730 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014731
14732 /* Issue Disconnect request */
14733 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14734 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14735 pAdapter->sessionId,
14736 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014737 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014738 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014739 hal_status);
14740 return -EAGAIN;
14741 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014742
14743 /* wait for mc thread to cleanup and then return to upper stack
14744 * so by the time upper layer calls the change interface, we are
14745 * all set to proceed further
14746 */
14747 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14748 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14749 if (!rc) {
14750 hdd_err("Failed to disconnect, timed out");
14751 return -ETIMEDOUT;
14752 }
14753
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014754 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014755 return 0;
14756}
14757
14758/**
14759 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14760 * @wiphy: Pointer to wiphy
14761 * @dev: Pointer to network device
14762 *
14763 * This function is used to leave an IBSS network
14764 *
14765 * Return: 0 for success, non-zero for failure
14766 */
14767static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14768 struct net_device *dev)
14769{
14770 int ret = 0;
14771
14772 cds_ssr_protect(__func__);
14773 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14774 cds_ssr_unprotect(__func__);
14775
14776 return ret;
14777}
14778
14779/**
14780 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14781 * @wiphy: Pointer to wiphy
14782 * @changed: Parameters changed
14783 *
14784 * This function is used to set the phy parameters. RTS Threshold/FRAG
14785 * Threshold/Retry Count etc.
14786 *
14787 * Return: 0 for success, non-zero for failure
14788 */
14789static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
14790 u32 changed)
14791{
14792 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14793 tHalHandle hHal = pHddCtx->hHal;
14794 int status;
14795
14796 ENTER();
14797
Anurag Chouhan6d760662016-02-20 16:05:43 +053014798 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014799 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014800 return -EINVAL;
14801 }
14802
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014803 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014804 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
14805 NO_SESSION, wiphy->rts_threshold));
14806 status = wlan_hdd_validate_context(pHddCtx);
14807
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014808 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014809 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014810
14811 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
14812 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
14813 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
14814
14815 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
14816 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014817 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014818 rts_threshold);
14819 return -EINVAL;
14820 }
14821
14822 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
14823 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014824 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014825 rts_threshold);
14826 return -EIO;
14827 }
14828
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014829 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014830 }
14831
14832 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
14833 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
14834 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
14835 wiphy->frag_threshold;
14836
14837 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
14838 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014839 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014840 frag_threshold);
14841 return -EINVAL;
14842 }
14843
14844 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
14845 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014846 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014847 frag_threshold);
14848 return -EIO;
14849 }
14850
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014851 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014852 }
14853
14854 if ((changed & WIPHY_PARAM_RETRY_SHORT)
14855 || (changed & WIPHY_PARAM_RETRY_LONG)) {
14856 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
14857 wiphy->retry_short : wiphy->retry_long;
14858
14859 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
14860 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014861 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014862 return -EINVAL;
14863 }
14864
14865 if (changed & WIPHY_PARAM_RETRY_SHORT) {
14866 if (0 != sme_cfg_set_int(hHal,
14867 WNI_CFG_LONG_RETRY_LIMIT,
14868 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014869 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014870 retry_value);
14871 return -EIO;
14872 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014873 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014874 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
14875 if (0 != sme_cfg_set_int(hHal,
14876 WNI_CFG_SHORT_RETRY_LIMIT,
14877 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014878 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014879 retry_value);
14880 return -EIO;
14881 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014882 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014883 }
14884 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014885 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014886 return 0;
14887}
14888
14889/**
14890 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14891 * @wiphy: Pointer to wiphy
14892 * @changed: Parameters changed
14893 *
14894 * Return: 0 for success, non-zero for failure
14895 */
14896static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
14897{
14898 int ret;
14899
14900 cds_ssr_protect(__func__);
14901 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
14902 cds_ssr_unprotect(__func__);
14903
14904 return ret;
14905}
14906
14907/**
14908 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
14909 * key
14910 * @wiphy: Pointer to wiphy
14911 * @dev: Pointer to network device
14912 * @key_index: Key index
14913 *
14914 * Return: 0
14915 */
14916static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14917 struct net_device *netdev,
14918 u8 key_index)
14919{
14920 ENTER();
14921 return 0;
14922}
14923
14924/**
14925 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
14926 * wlan_hdd_set_default_mgmt_key
14927 * @wiphy: pointer to wiphy
14928 * @netdev: pointer to net_device structure
14929 * @key_index: key index
14930 *
14931 * Return: 0 on success, error number on failure
14932 */
14933static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14934 struct net_device *netdev,
14935 u8 key_index)
14936{
14937 int ret;
14938
14939 cds_ssr_protect(__func__);
14940 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
14941 cds_ssr_unprotect(__func__);
14942
14943 return ret;
14944}
14945
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014946/**
14947 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
14948 * @wiphy: Pointer to wiphy
14949 * @dev: Pointer to network device
14950 * @params: Pointer to tx queue parameters
14951 *
14952 * Return: 0
14953 */
14954static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
14955 struct net_device *dev,
14956 struct ieee80211_txq_params *params)
14957{
14958 ENTER();
14959 return 0;
14960}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014961
14962/**
14963 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
14964 * @wiphy: pointer to wiphy
14965 * @netdev: pointer to net_device structure
14966 * @params: pointer to ieee80211_txq_params
14967 *
14968 * Return: 0 on success, error number on failure
14969 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014970static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
14971 struct net_device *dev,
14972 struct ieee80211_txq_params *params)
14973{
14974 int ret;
14975
14976 cds_ssr_protect(__func__);
14977 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
14978 cds_ssr_unprotect(__func__);
14979
14980 return ret;
14981}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014982
14983/**
14984 * __wlan_hdd_cfg80211_del_station() - delete station v2
14985 * @wiphy: Pointer to wiphy
14986 * @param: Pointer to delete station parameter
14987 *
14988 * Return: 0 for success, non-zero for failure
14989 */
14990static
14991int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14992 struct net_device *dev,
14993 struct tagCsrDelStaParams *pDelStaParams)
14994{
14995 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14996 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053014997 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014998 hdd_hostapd_state_t *hapd_state;
14999 int status;
15000 uint8_t staId;
15001 uint8_t *mac;
15002
15003 ENTER();
15004
Anurag Chouhan6d760662016-02-20 16:05:43 +053015005 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015006 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015007 return -EINVAL;
15008 }
15009
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015010 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15011 hdd_err("invalid session id: %d", pAdapter->sessionId);
15012 return -EINVAL;
15013 }
15014
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015015 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015016 TRACE_CODE_HDD_CFG80211_DEL_STA,
15017 pAdapter->sessionId, pAdapter->device_mode));
15018
15019 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15020 status = wlan_hdd_validate_context(pHddCtx);
15021
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015022 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015023 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015024
15025 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15026
Krunal Sonib4326f22016-03-10 13:05:51 -080015027 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15028 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015029
15030 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15031 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015032 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015033 return 0;
15034 }
15035
Anurag Chouhanc5548422016-02-24 18:33:27 +053015036 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015037 uint16_t i;
15038 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15039 if ((pAdapter->aStaInfo[i].isUsed) &&
15040 (!pAdapter->aStaInfo[i].
15041 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015042 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015043 mac,
15044 pAdapter->aStaInfo[i].
15045 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015046 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015047 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15048 hdd_ipa_wlan_evt(pAdapter,
15049 pAdapter->
15050 aStaInfo[i].
15051 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015052 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015053 mac);
15054 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015055 hdd_notice("Delete STA with MAC::"
15056 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015057 MAC_ADDR_ARRAY(mac));
15058
15059 if (pHddCtx->dev_dfs_cac_status ==
15060 DFS_CAC_IN_PROGRESS)
15061 goto fn_end;
15062
Wei Song2f76f642016-11-18 16:32:53 +080015063 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015064 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015065 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015066 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015067 hdd_softap_sta_deauth(pAdapter,
15068 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015069 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015070 pAdapter->aStaInfo[i].
15071 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015072 qdf_status =
15073 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015074 &hapd_state->
15075 qdf_sta_disassoc_event,
15076 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015077 if (!QDF_IS_STATUS_SUCCESS(
15078 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015079 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015080 }
15081 }
15082 }
15083 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015084 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015085 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015086 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015087 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015088 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015089 hdd_notice("Skip DEL STA as this is not used::"
15090 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015091 MAC_ADDR_ARRAY(mac));
15092 return -ENOENT;
15093 }
15094
15095 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15096 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015097 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015098 }
15099
15100 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15101 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015102 hdd_notice("Skip DEL STA as deauth is in progress::"
15103 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015104 MAC_ADDR_ARRAY(mac));
15105 return -ENOENT;
15106 }
15107
15108 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15109
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015110 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015111 MAC_ADDR_ARRAY(mac));
15112
15113 /* Case: SAP in ACS selected DFS ch and client connected
15114 * Now Radar detected. Then if random channel is another
15115 * DFS ch then new CAC is initiated and no TX allowed.
15116 * So do not send any mgmt frames as it will timeout
15117 * during CAC.
15118 */
15119
15120 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15121 goto fn_end;
15122
Wei Song2f76f642016-11-18 16:32:53 +080015123 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015124 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15125 (pAdapter), pAdapter->sessionId,
15126 (uint8_t *)&pDelStaParams->peerMacAddr,
15127 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015128 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015129 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015130 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015131 pAdapter->aStaInfo[staId].isDeauthInProgress =
15132 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015133 hdd_notice("STA removal failed for ::"
15134 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015135 MAC_ADDR_ARRAY(mac));
15136 return -ENOENT;
15137 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015138 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015139 &hapd_state->
15140 qdf_sta_disassoc_event,
15141 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015142 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015143 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015144 }
15145 }
15146 }
15147
15148fn_end:
15149 EXIT();
15150 return 0;
15151}
15152
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015153#if defined(USE_CFG80211_DEL_STA_V2)
15154/**
15155 * wlan_hdd_del_station() - delete station wrapper
15156 * @adapter: pointer to the hdd adapter
15157 *
15158 * Return: None
15159 */
15160void wlan_hdd_del_station(hdd_adapter_t *adapter)
15161{
15162 struct station_del_parameters del_sta;
15163 del_sta.mac = NULL;
15164 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15165 del_sta.reason_code = eCsrForcedDeauthSta;
15166
15167 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15168 &del_sta);
15169}
15170#else
15171void wlan_hdd_del_station(hdd_adapter_t *adapter)
15172{
15173 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15174}
15175#endif
15176
15177#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015178/**
15179 * wlan_hdd_cfg80211_del_station() - delete station v2
15180 * @wiphy: Pointer to wiphy
15181 * @param: Pointer to delete station parameter
15182 *
15183 * Return: 0 for success, non-zero for failure
15184 */
15185int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15186 struct net_device *dev,
15187 struct station_del_parameters *param)
15188#else
15189/**
15190 * wlan_hdd_cfg80211_del_station() - delete station
15191 * @wiphy: Pointer to wiphy
15192 * @mac: Pointer to station mac address
15193 *
15194 * Return: 0 for success, non-zero for failure
15195 */
15196#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15197int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15198 struct net_device *dev,
15199 const uint8_t *mac)
15200#else
15201int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15202 struct net_device *dev,
15203 uint8_t *mac)
15204#endif
15205#endif
15206{
15207 int ret;
15208 struct tagCsrDelStaParams delStaParams;
15209
15210 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015211#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015212 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015213 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015214 return -EINVAL;
15215 }
15216 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15217 param->subtype, &delStaParams);
15218#else
15219 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15220 (SIR_MAC_MGMT_DEAUTH >> 4),
15221 &delStaParams);
15222#endif
15223 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15224 cds_ssr_unprotect(__func__);
15225
15226 return ret;
15227}
15228
15229/**
15230 * __wlan_hdd_cfg80211_add_station() - add station
15231 * @wiphy: Pointer to wiphy
15232 * @mac: Pointer to station mac address
15233 * @pmksa: Pointer to add station parameter
15234 *
15235 * Return: 0 for success, non-zero for failure
15236 */
15237static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15238 struct net_device *dev,
15239 const uint8_t *mac,
15240 struct station_parameters *params)
15241{
15242 int status = -EPERM;
15243#ifdef FEATURE_WLAN_TDLS
15244 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15245 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15246 u32 mask, set;
15247
15248 ENTER();
15249
Anurag Chouhan6d760662016-02-20 16:05:43 +053015250 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015251 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015252 return -EINVAL;
15253 }
15254
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015255 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15256 hdd_err("invalid session id: %d", pAdapter->sessionId);
15257 return -EINVAL;
15258 }
15259
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015260 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015261 TRACE_CODE_HDD_CFG80211_ADD_STA,
15262 pAdapter->sessionId, params->listen_interval));
15263
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015264 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015265 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015266
15267 mask = params->sta_flags_mask;
15268
15269 set = params->sta_flags_set;
15270
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015271 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015272 MAC_ADDR_ARRAY(mac));
15273
15274 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15275 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15276 status =
15277 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15278 }
15279 }
15280#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015281 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015282 return status;
15283}
15284
15285/**
15286 * wlan_hdd_cfg80211_add_station() - add station
15287 * @wiphy: Pointer to wiphy
15288 * @mac: Pointer to station mac address
15289 * @pmksa: Pointer to add station parameter
15290 *
15291 * Return: 0 for success, non-zero for failure
15292 */
15293#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15294static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15295 struct net_device *dev,
15296 const uint8_t *mac,
15297 struct station_parameters *params)
15298#else
15299static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15300 struct net_device *dev, uint8_t *mac,
15301 struct station_parameters *params)
15302#endif
15303{
15304 int ret;
15305
15306 cds_ssr_protect(__func__);
15307 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15308 cds_ssr_unprotect(__func__);
15309
15310 return ret;
15311}
15312
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015313/**
15314 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15315 * @wiphy: Pointer to wiphy
15316 * @dev: Pointer to network device
15317 * @pmksa: Pointer to set pmksa parameter
15318 *
15319 * Return: 0 for success, non-zero for failure
15320 */
15321static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15322 struct net_device *dev,
15323 struct cfg80211_pmksa *pmksa)
15324{
15325 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15326 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15327 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015328 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015329 int status;
15330 tPmkidCacheInfo pmk_id;
15331
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015332 ENTER();
15333
Anurag Chouhan6d760662016-02-20 16:05:43 +053015334 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015335 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015336 return -EINVAL;
15337 }
15338
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015339 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15340 hdd_err("invalid session id: %d", pAdapter->sessionId);
15341 return -EINVAL;
15342 }
15343
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015344 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015345 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015346 return -EINVAL;
15347 }
15348
15349 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015350 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015351 pmksa->bssid, pmksa->pmkid);
15352 return -EINVAL;
15353 }
15354
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015355 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015356 MAC_ADDR_ARRAY(pmksa->bssid));
15357
15358 status = wlan_hdd_validate_context(pHddCtx);
15359
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015360 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015361 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015362
15363 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15364
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015365 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15366 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015367
15368 /* Add to the PMKSA ID Cache in CSR */
15369 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15370 &pmk_id, 1, false);
15371
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015372 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015373 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15374 pAdapter->sessionId, result));
15375
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015376 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015377 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015378}
15379
15380/**
15381 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15382 * @wiphy: Pointer to wiphy
15383 * @dev: Pointer to network device
15384 * @pmksa: Pointer to set pmksa parameter
15385 *
15386 * Return: 0 for success, non-zero for failure
15387 */
15388static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15389 struct net_device *dev,
15390 struct cfg80211_pmksa *pmksa)
15391{
15392 int ret;
15393
15394 cds_ssr_protect(__func__);
15395 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15396 cds_ssr_unprotect(__func__);
15397
15398 return ret;
15399}
15400
15401/**
15402 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15403 * @wiphy: Pointer to wiphy
15404 * @dev: Pointer to network device
15405 * @pmksa: Pointer to pmksa parameter
15406 *
15407 * Return: 0 for success, non-zero for failure
15408 */
15409static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15410 struct net_device *dev,
15411 struct cfg80211_pmksa *pmksa)
15412{
15413 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15414 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15415 tHalHandle halHandle;
15416 int status = 0;
15417
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015418 ENTER();
15419
Anurag Chouhan6d760662016-02-20 16:05:43 +053015420 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015421 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015422 return -EINVAL;
15423 }
15424
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015425 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15426 hdd_err("invalid session id: %d", pAdapter->sessionId);
15427 return -EINVAL;
15428 }
15429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015430 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015431 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015432 return -EINVAL;
15433 }
15434
15435 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015436 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015437 return -EINVAL;
15438 }
15439
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015440 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015441 MAC_ADDR_ARRAY(pmksa->bssid));
15442
15443 status = wlan_hdd_validate_context(pHddCtx);
15444
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015445 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015446 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015447
15448 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15449
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015450 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015451 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15452 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015453 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015454 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015455 sme_roam_del_pmkid_from_cache(halHandle,
15456 pAdapter->sessionId, pmksa->bssid,
15457 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015458 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015459 MAC_ADDR_ARRAY(pmksa->bssid));
15460 status = -EINVAL;
15461 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015462 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015463 return status;
15464}
15465
15466/**
15467 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15468 * @wiphy: Pointer to wiphy
15469 * @dev: Pointer to network device
15470 * @pmksa: Pointer to pmksa parameter
15471 *
15472 * Return: 0 for success, non-zero for failure
15473 */
15474static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15475 struct net_device *dev,
15476 struct cfg80211_pmksa *pmksa)
15477{
15478 int ret;
15479
15480 cds_ssr_protect(__func__);
15481 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15482 cds_ssr_unprotect(__func__);
15483
15484 return ret;
15485
15486}
15487
15488/**
15489 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15490 * @wiphy: Pointer to wiphy
15491 * @dev: Pointer to network device
15492 *
15493 * Return: 0 for success, non-zero for failure
15494 */
15495static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15496 struct net_device *dev)
15497{
15498 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15499 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15500 tHalHandle halHandle;
15501 int status = 0;
15502
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015503 ENTER();
15504
Anurag Chouhan6d760662016-02-20 16:05:43 +053015505 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015506 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015507 return -EINVAL;
15508 }
15509
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015510 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15511 hdd_err("invalid session id: %d", pAdapter->sessionId);
15512 return -EINVAL;
15513 }
15514
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015515 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015516
15517 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15518 status = wlan_hdd_validate_context(pHddCtx);
15519
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015520 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015521 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015522
15523 /* Retrieve halHandle */
15524 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15525
15526 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015527 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015528 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15529 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015530 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015531 status = -EINVAL;
15532 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015533 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015534 return status;
15535}
15536
15537/**
15538 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15539 * @wiphy: Pointer to wiphy
15540 * @dev: Pointer to network device
15541 *
15542 * Return: 0 for success, non-zero for failure
15543 */
15544static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15545 struct net_device *dev)
15546{
15547 int ret;
15548
15549 cds_ssr_protect(__func__);
15550 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15551 cds_ssr_unprotect(__func__);
15552
15553 return ret;
15554}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015555
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015556#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015557/**
15558 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15559 * @wiphy: Pointer to wiphy
15560 * @dev: Pointer to network device
15561 * @ftie: Pointer to fast transition ie parameter
15562 *
15563 * Return: 0 for success, non-zero for failure
15564 */
15565static int
15566__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15567 struct net_device *dev,
15568 struct cfg80211_update_ft_ies_params *ftie)
15569{
15570 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15571 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15572 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15573 int status;
15574
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015575 ENTER();
15576
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015577 status = wlan_hdd_validate_context(hdd_ctx);
15578 if (status)
15579 return status;
15580
Anurag Chouhan6d760662016-02-20 16:05:43 +053015581 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015582 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015583 return -EINVAL;
15584 }
15585
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015586 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15587 hdd_err("invalid session id: %d", pAdapter->sessionId);
15588 return -EINVAL;
15589 }
15590
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015591 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015592 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15593 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15594 /* Added for debug on reception of Re-assoc Req. */
15595 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015596 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015597 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015598 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015599 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015600 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015601 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015602
15603 /* Pass the received FT IEs to SME */
15604 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15605 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015606 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015607 return 0;
15608}
15609
15610/**
15611 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15612 * @wiphy: Pointer to wiphy
15613 * @dev: Pointer to network device
15614 * @ftie: Pointer to fast transition ie parameter
15615 *
15616 * Return: 0 for success, non-zero for failure
15617 */
15618static int
15619wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15620 struct net_device *dev,
15621 struct cfg80211_update_ft_ies_params *ftie)
15622{
15623 int ret;
15624
15625 cds_ssr_protect(__func__);
15626 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15627 cds_ssr_unprotect(__func__);
15628
15629 return ret;
15630}
15631#endif
15632
15633#ifdef WLAN_FEATURE_GTK_OFFLOAD
15634/**
15635 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
15636 * @callbackContext: Callback context
15637 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
15638 *
15639 * Callback rountine called upon receiving response for get offload info
15640 *
15641 * Return: none
15642 */
15643void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
15644 tpSirGtkOffloadGetInfoRspParams
15645 pGtkOffloadGetInfoRsp)
15646{
15647 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
15648 uint8_t tempReplayCounter[8];
15649 hdd_station_ctx_t *pHddStaCtx;
15650
15651 ENTER();
15652
15653 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015654 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015655 return;
15656 }
15657
15658 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015659 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015660 return;
15661 }
15662
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015663 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015664 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015665 return;
15666 }
15667
15668 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15669 /* Update replay counter */
15670 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
15671 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
15672
15673 {
15674 /* changing from little to big endian since supplicant
15675 * works on big endian format
15676 */
15677 int i;
15678 uint8_t *p =
15679 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
15680
15681 for (i = 0; i < 8; i++) {
15682 tempReplayCounter[7 - i] = (uint8_t) p[i];
15683 }
15684 }
15685
15686 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015687 cfg80211_gtk_rekey_notify(pAdapter->dev,
15688 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015689 tempReplayCounter, GFP_KERNEL);
15690}
15691
15692/**
15693 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15694 * @wiphy: Pointer to wiphy
15695 * @dev: Pointer to network device
15696 * @data: Pointer to rekey data
15697 *
15698 * This function is used to offload GTK rekeying job to the firmware.
15699 *
15700 * Return: 0 for success, non-zero for failure
15701 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015702static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015703int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15704 struct net_device *dev,
15705 struct cfg80211_gtk_rekey_data *data)
15706{
15707 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15708 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15709 hdd_station_ctx_t *pHddStaCtx;
15710 tHalHandle hHal;
15711 int result;
15712 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015713 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015714
15715 ENTER();
15716
Anurag Chouhan6d760662016-02-20 16:05:43 +053015717 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015718 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015719 return -EINVAL;
15720 }
15721
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015722 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15723 hdd_err("invalid session id: %d", pAdapter->sessionId);
15724 return -EINVAL;
15725 }
15726
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015727 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015728 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15729 pAdapter->sessionId, pAdapter->device_mode));
15730
15731 result = wlan_hdd_validate_context(pHddCtx);
15732
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015733 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015734 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015735
15736 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15737 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15738 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015739 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015740 return -EAGAIN;
15741 }
15742
15743 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
15744 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
15745 NL80211_KCK_LEN);
15746 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
15747 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053015748 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015749 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015750 {
15751 /* changing from big to little endian since driver
15752 * works on little endian format
15753 */
15754 uint8_t *p =
15755 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
15756 ullKeyReplayCounter;
15757 int i;
15758
15759 for (i = 0; i < 8; i++) {
15760 p[7 - i] = data->replay_ctr[i];
15761 }
15762 }
15763
15764 if (true == pHddCtx->hdd_wlan_suspended) {
15765 /* if wlan is suspended, enable GTK offload directly from here */
15766 memcpy(&hddGtkOffloadReqParams,
15767 &pHddStaCtx->gtkOffloadReqParams,
15768 sizeof(tSirGtkOffloadParams));
15769 status =
15770 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
15771 pAdapter->sessionId);
15772
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015773 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015774 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015775 status);
15776 return -EINVAL;
15777 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015778 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015779 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015780 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015781 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015782 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015783 return result;
15784}
15785
15786/**
15787 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15788 * @wiphy: Pointer to wiphy
15789 * @dev: Pointer to network device
15790 * @data: Pointer to rekey data
15791 *
15792 * This function is used to offload GTK rekeying job to the firmware.
15793 *
15794 * Return: 0 for success, non-zero for failure
15795 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015796static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015797int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15798 struct net_device *dev,
15799 struct cfg80211_gtk_rekey_data *data)
15800{
15801 int ret;
15802
15803 cds_ssr_protect(__func__);
15804 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15805 cds_ssr_unprotect(__func__);
15806
15807 return ret;
15808}
15809#endif /*WLAN_FEATURE_GTK_OFFLOAD */
15810
15811/**
15812 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15813 * @wiphy: Pointer to wiphy
15814 * @dev: Pointer to network device
15815 * @param: Pointer to access control parameter
15816 *
15817 * Return: 0 for success, non-zero for failure
15818 */
15819static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15820 struct net_device *dev,
15821 const struct cfg80211_acl_data *params)
15822{
15823 int i;
15824 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15825 hdd_hostapd_state_t *pHostapdState;
15826 tsap_Config_t *pConfig;
15827 v_CONTEXT_t p_cds_context = NULL;
15828 hdd_context_t *pHddCtx;
15829 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015830 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015831
15832 ENTER();
15833
Anurag Chouhan6d760662016-02-20 16:05:43 +053015834 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015835 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015836 return -EINVAL;
15837 }
15838
15839 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015840 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015841 return -EINVAL;
15842 }
15843
15844 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15845 status = wlan_hdd_validate_context(pHddCtx);
15846
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015847 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015848 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015849
15850 p_cds_context = pHddCtx->pcds_context;
15851 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15852
15853 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015854 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015855 return -EINVAL;
15856 }
15857
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015858 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015859 params->n_acl_entries);
15860
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015861 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015862 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
15863 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080015864 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015865 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
15866
15867 /* default value */
15868 pConfig->num_accept_mac = 0;
15869 pConfig->num_deny_mac = 0;
15870
15871 /**
15872 * access control policy
15873 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
15874 * listed in hostapd.deny file.
15875 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
15876 * listed in hostapd.accept file.
15877 */
15878 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
15879 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
15880 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
15881 params->acl_policy) {
15882 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
15883 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015884 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015885 params->acl_policy);
15886 return -ENOTSUPP;
15887 }
15888
15889 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
15890 pConfig->num_accept_mac = params->n_acl_entries;
15891 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015892 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
15893 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015894 MAC_ADDR_ARRAY(
15895 params->mac_addrs[i].addr));
15896
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015897 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015898 params->mac_addrs[i].addr,
15899 sizeof(qcmacaddr));
15900 }
15901 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
15902 pConfig->num_deny_mac = params->n_acl_entries;
15903 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015904 hdd_notice("** Add ACL MAC entry %i in BlackList :"
15905 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015906 MAC_ADDR_ARRAY(
15907 params->mac_addrs[i].addr));
15908
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015909 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015910 params->mac_addrs[i].addr,
15911 sizeof(qcmacaddr));
15912 }
15913 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070015914 qdf_status = wlansap_set_mac_acl(
15915 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015916 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015917 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015918 return -EINVAL;
15919 }
15920 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015921 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015922 hdd_device_mode_to_string(pAdapter->device_mode),
15923 pAdapter->device_mode);
15924 return -EINVAL;
15925 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015926 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015927 return 0;
15928}
15929
15930/**
15931 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
15932 * __wlan_hdd_cfg80211_set_mac_acl
15933 * @wiphy: pointer to wiphy structure
15934 * @dev: pointer to net_device
15935 * @params: pointer to cfg80211_acl_data
15936 *
15937 * Return; 0 on success, error number otherwise
15938 */
15939static int
15940wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15941 struct net_device *dev,
15942 const struct cfg80211_acl_data *params)
15943{
15944 int ret;
15945
15946 cds_ssr_protect(__func__);
15947 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
15948 cds_ssr_unprotect(__func__);
15949
15950 return ret;
15951}
15952
15953#ifdef WLAN_NL80211_TESTMODE
15954#ifdef FEATURE_WLAN_LPHB
15955/**
15956 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
15957 * @pHddCtx: Pointer to hdd context
15958 * @lphbInd: Pointer to low power heart beat indication parameter
15959 *
15960 * Return: none
15961 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015962static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
15963 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015964{
15965 struct sk_buff *skb;
15966
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015967 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015968
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015969 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015970 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015971
15972 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015973 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015974 return;
15975 }
15976
15977 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
15978 wiphy, sizeof(tSirLPHBInd),
15979 GFP_ATOMIC);
15980 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015981 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015982 return;
15983 }
15984
15985 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015986 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015987 goto nla_put_failure;
15988 }
15989 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015990 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015991 goto nla_put_failure;
15992 }
15993 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015994 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015995 goto nla_put_failure;
15996 }
15997 cfg80211_testmode_event(skb, GFP_ATOMIC);
15998 return;
15999
16000nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016001 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016002 kfree_skb(skb);
16003
16004 return;
16005}
16006#endif /* FEATURE_WLAN_LPHB */
16007
16008/**
16009 * __wlan_hdd_cfg80211_testmode() - test mode
16010 * @wiphy: Pointer to wiphy
16011 * @data: Data pointer
16012 * @len: Data length
16013 *
16014 * Return: 0 for success, non-zero for failure
16015 */
16016static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16017 void *data, int len)
16018{
16019 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16020 int err;
16021 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16022
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016023 ENTER();
16024
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016025 err = wlan_hdd_validate_context(pHddCtx);
16026 if (err)
16027 return err;
16028
16029 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16030 len, wlan_hdd_tm_policy);
16031 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016032 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016033 return err;
16034 }
16035
16036 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016037 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016038 return -EINVAL;
16039 }
16040
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016041 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016042 TRACE_CODE_HDD_CFG80211_TESTMODE,
16043 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016044 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16045#ifdef FEATURE_WLAN_LPHB
16046 /* Low Power Heartbeat configuration request */
16047 case WLAN_HDD_TM_CMD_WLAN_HB:
16048 {
16049 int buf_len;
16050 void *buf;
16051 tSirLPHBReq *hb_params = NULL;
16052 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016053 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016054
16055 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016056 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016057 return -EINVAL;
16058 }
16059
16060 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16061 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16062
16063 hb_params_temp = (tSirLPHBReq *) buf;
16064 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
16065 && (hb_params_temp->params.lphbTcpParamReq.
16066 timePeriodSec == 0))
16067 return -EINVAL;
16068
16069 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016070 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016071 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016072 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016073 return -ENOMEM;
16074 }
16075
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016076 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016077 smeStatus =
16078 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
16079 hb_params,
16080 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016081 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016082 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016083 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016084 }
16085 return 0;
16086 }
16087#endif /* FEATURE_WLAN_LPHB */
16088
16089#if defined(QCA_WIFI_FTM)
16090 case WLAN_HDD_TM_CMD_WLAN_FTM:
16091 {
16092 int buf_len;
16093 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016094 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016095 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016096 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016097 return -EINVAL;
16098 }
16099
16100 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16101 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16102
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016103 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016104
16105 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16106
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016107 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016108 err = -EBUSY;
16109 break;
16110 }
16111#endif
16112
16113 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016114 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016115 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16116 return -EOPNOTSUPP;
16117 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016118 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016119 return err;
16120}
16121
16122/**
16123 * wlan_hdd_cfg80211_testmode() - test mode
16124 * @wiphy: Pointer to wiphy
16125 * @dev: Pointer to network device
16126 * @data: Data pointer
16127 * @len: Data length
16128 *
16129 * Return: 0 for success, non-zero for failure
16130 */
16131static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16132#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16133 struct wireless_dev *wdev,
16134#endif
16135 void *data, int len)
16136{
16137 int ret;
16138
16139 cds_ssr_protect(__func__);
16140 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16141 cds_ssr_unprotect(__func__);
16142
16143 return ret;
16144}
16145
16146#if defined(QCA_WIFI_FTM)
16147/**
16148 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16149 * @buf: Pointer to buffer
16150 * @buf_len: Buffer length
16151 *
16152 * Return: none
16153 */
16154void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16155{
16156 struct sk_buff *skb;
16157 hdd_context_t *hdd_ctx;
16158
16159 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016160 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016161 return;
16162 }
16163
Anurag Chouhan6d760662016-02-20 16:05:43 +053016164 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016165 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016166 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016167 return;
16168 }
16169
16170 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16171 buf_len, GFP_KERNEL);
16172 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016173 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016174 return;
16175 }
16176
16177 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16178 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16179 goto nla_put_failure;
16180
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016181 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016182
16183 cfg80211_testmode_event(skb, GFP_KERNEL);
16184 return;
16185
16186nla_put_failure:
16187 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016188 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016189}
16190#endif
16191#endif /* CONFIG_NL80211_TESTMODE */
16192
16193#ifdef QCA_HT_2040_COEX
16194/**
16195 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16196 * @wiphy: Pointer to wiphy
16197 * @dev: Pointer to network device
16198 * @chandef: Pointer to channel definition parameter
16199 *
16200 * Return: 0 for success, non-zero for failure
16201 */
16202static int
16203__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16204 struct net_device *dev,
16205 struct cfg80211_chan_def *chandef)
16206{
16207 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16208 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016209 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016210 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016211 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016212
Anurag Chouhan6d760662016-02-20 16:05:43 +053016213 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016214 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016215 return -EINVAL;
16216 }
16217
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016218 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16219 hdd_err("invalid session id: %d", pAdapter->sessionId);
16220 return -EINVAL;
16221 }
16222
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016223 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16224 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016225 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016226 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016227
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016228 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016229 sme_get_config_param(pHddCtx->hHal, &sme_config);
16230 switch (chandef->width) {
16231 case NL80211_CHAN_WIDTH_20:
16232 if (sme_config.csrConfig.channelBondingMode24GHz !=
16233 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16234 sme_config.csrConfig.channelBondingMode24GHz =
16235 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16236 sme_update_config(pHddCtx->hHal, &sme_config);
16237 cbModeChange = true;
16238 }
16239 break;
16240
16241 case NL80211_CHAN_WIDTH_40:
16242 if (sme_config.csrConfig.channelBondingMode24GHz ==
16243 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16244 if (NL80211_CHAN_HT40MINUS ==
16245 cfg80211_get_chandef_type(chandef))
16246 sme_config.csrConfig.channelBondingMode24GHz =
16247 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16248 else
16249 sme_config.csrConfig.channelBondingMode24GHz =
16250 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16251 sme_update_config(pHddCtx->hHal, &sme_config);
16252 cbModeChange = true;
16253 }
16254 break;
16255
16256 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016257 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016258 return -EINVAL;
16259 }
16260
16261 if (!cbModeChange)
16262 return 0;
16263
Krunal Sonib4326f22016-03-10 13:05:51 -080016264 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016265 return 0;
16266
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016267 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016268 sme_config.csrConfig.channelBondingMode24GHz);
16269
16270 /* Change SAP ht2040 mode */
16271 status = hdd_set_sap_ht2040_mode(pAdapter,
16272 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016273 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016274 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016275 return -EINVAL;
16276 }
16277
16278 return 0;
16279}
16280
16281/**
16282 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16283 * @wiphy: Pointer to wiphy
16284 * @dev: Pointer to network device
16285 * @chandef: Pointer to channel definition parameter
16286 *
16287 * Return: 0 for success, non-zero for failure
16288 */
16289static int
16290wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16291 struct net_device *dev,
16292 struct cfg80211_chan_def *chandef)
16293{
16294 int ret;
16295
16296 cds_ssr_protect(__func__);
16297 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16298 cds_ssr_unprotect(__func__);
16299
16300 return ret;
16301}
16302#endif
16303
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016304#ifdef CHANNEL_SWITCH_SUPPORTED
16305/**
16306 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16307 * channel in SAP/GO
16308 * @wiphy: wiphy pointer
16309 * @dev: dev pointer.
16310 * @csa_params: Change channel params
16311 *
16312 * This function is called to switch channel in SAP/GO
16313 *
16314 * Return: 0 if success else return non zero
16315 */
16316static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16317 struct net_device *dev,
16318 struct cfg80211_csa_settings *csa_params)
16319{
16320 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16321 hdd_context_t *hdd_ctx;
16322 uint8_t channel;
16323 uint16_t freq;
16324 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016325 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016326
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016327 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016328 csa_params->chandef.chan->center_freq);
16329
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016330 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16331 hdd_err("invalid session id: %d", adapter->sessionId);
16332 return -EINVAL;
16333 }
16334
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016335 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16336 ret = wlan_hdd_validate_context(hdd_ctx);
16337
16338 if (0 != ret)
16339 return ret;
16340
Krunal Sonib4326f22016-03-10 13:05:51 -080016341 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16342 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016343 return -ENOTSUPP;
16344
16345 freq = csa_params->chandef.chan->center_freq;
16346 channel = cds_freq_to_chan(freq);
16347
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016348 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16349
16350 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016351 return ret;
16352}
16353
16354/**
16355 * wlan_hdd_cfg80211_channel_switch()- function to switch
16356 * channel in SAP/GO
16357 * @wiphy: wiphy pointer
16358 * @dev: dev pointer.
16359 * @csa_params: Change channel params
16360 *
16361 * This function is called to switch channel in SAP/GO
16362 *
16363 * Return: 0 if success else return non zero
16364 */
16365static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16366 struct net_device *dev,
16367 struct cfg80211_csa_settings *csa_params)
16368{
16369 int ret;
16370
16371 cds_ssr_protect(__func__);
16372 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16373 cds_ssr_unprotect(__func__);
16374 return ret;
16375}
16376#endif
16377
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016378/**
16379 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16380 * translation from NL to policy manager type
16381 * @type: Generic connection mode type defined in NL
16382 *
16383 *
16384 * This function provides the type translation
16385 *
16386 * Return: cds_con_mode enum
16387 */
16388enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
16389 enum nl80211_iftype type)
16390{
16391 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
16392 switch (type) {
16393 case NL80211_IFTYPE_STATION:
16394 mode = CDS_STA_MODE;
16395 break;
16396 case NL80211_IFTYPE_P2P_CLIENT:
16397 mode = CDS_P2P_CLIENT_MODE;
16398 break;
16399 case NL80211_IFTYPE_P2P_GO:
16400 mode = CDS_P2P_GO_MODE;
16401 break;
16402 case NL80211_IFTYPE_AP:
16403 mode = CDS_SAP_MODE;
16404 break;
16405 case NL80211_IFTYPE_ADHOC:
16406 mode = CDS_IBSS_MODE;
16407 break;
16408 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016409 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016410 type);
16411 }
16412 return mode;
16413}
16414
16415/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016416 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16417 * @wiphy: Handle to struct wiphy to get handle to module context.
16418 * @chandef: Contains information about the capture channel to be set.
16419 *
16420 * This interface is called if and only if monitor mode interface alone is
16421 * active.
16422 *
16423 * Return: 0 success or error code on failure.
16424 */
16425static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16426 struct cfg80211_chan_def *chandef)
16427{
16428 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16429 hdd_adapter_t *adapter;
16430 hdd_station_ctx_t *sta_ctx;
16431 struct hdd_mon_set_ch_info *ch_info;
16432 QDF_STATUS status;
16433 tHalHandle hal_hdl;
16434 struct qdf_mac_addr bssid;
16435 tCsrRoamProfile roam_profile;
16436 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016437 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016438 int ret;
16439 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16440
16441 ENTER();
16442
16443 ret = wlan_hdd_validate_context(hdd_ctx);
16444 if (ret)
16445 return ret;
16446
16447 hal_hdl = hdd_ctx->hHal;
16448
16449 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16450 if (!adapter)
16451 return -EIO;
16452
16453 hdd_info("%s: set monitor mode Channel %d and freq %d",
16454 adapter->dev->name, chan_num, chandef->chan->center_freq);
16455
16456 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16457 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016458 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16459 roam_profile.ChannelInfo.numOfChannels = 1;
16460 roam_profile.phyMode = ch_info->phy_mode;
16461 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016462 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016463
16464 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16465 QDF_MAC_ADDR_SIZE);
16466
16467 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016468 /*
16469 * CDS api expects secondary channel for calculating
16470 * the channel params
16471 */
16472 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16473 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16474 if (chan_num >= 1 && chan_num <= 5)
16475 sec_ch = chan_num + 4;
16476 else if (chan_num >= 6 && chan_num <= 13)
16477 sec_ch = chan_num - 4;
16478 }
16479 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016480 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16481 &roam_profile);
16482 if (status) {
16483 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
16484 status);
16485 ret = qdf_status_to_os_return(status);
16486 return ret;
16487 }
16488 EXIT();
16489 return 0;
16490}
16491
16492/**
16493 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16494 * @wiphy: Handle to struct wiphy to get handle to module context.
16495 * @chandef: Contains information about the capture channel to be set.
16496 *
16497 * This interface is called if and only if monitor mode interface alone is
16498 * active.
16499 *
16500 * Return: 0 success or error code on failure.
16501 */
16502static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16503 struct cfg80211_chan_def *chandef)
16504{
16505 int ret;
16506
16507 cds_ssr_protect(__func__);
16508 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16509 cds_ssr_unprotect(__func__);
16510 return ret;
16511}
16512
16513/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016514 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16515 * @adapter: pointer to adapter
16516 *
16517 * Wrapper function to clear link layer stats.
16518 * return - void
16519 */
16520void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16521{
16522 tSirLLStatsClearReq link_layer_stats_clear_req;
16523 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16524
Mukul Sharma491021c2016-09-29 21:39:19 +053016525 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16526 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016527 link_layer_stats_clear_req.stopReq = 0;
16528 link_layer_stats_clear_req.reqId = 1;
16529 link_layer_stats_clear_req.staId = adapter->sessionId;
16530 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16531
16532 return;
16533}
16534
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016535#define CNT_DIFF(cur, prev) \
16536 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16537#define MAX_COUNT 0xffffffff
16538static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16539 struct scan_chan_info *chan,
16540 struct scan_chan_info *info, uint32_t cmd_flag)
16541{
16542 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16543 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16544 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16545
16546 mutex_lock(&hdd_ctx->chan_info_lock);
16547
16548 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16549 qdf_mem_zero(chan, sizeof(*chan));
16550
16551 chan->freq = info->freq;
16552 chan->noise_floor = info->noise_floor;
16553 chan->clock_freq = info->clock_freq;
16554 chan->cmd_flag = info->cmd_flag;
16555 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16556
16557 chan->rx_clear_count =
16558 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16559
16560 chan->tx_frame_count =
16561 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16562
16563 mutex_unlock(&hdd_ctx->chan_info_lock);
16564
16565}
16566#undef CNT_DIFF
16567#undef MAX_COUNT
16568
16569/**
16570 * wlan_hdd_chan_info_cb() - channel info callback
16571 * @chan_info: struct scan_chan_info
16572 *
16573 * Store channel info into HDD context
16574 *
16575 * Return: None.
16576 */
16577static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16578{
16579 hdd_context_t *hdd_ctx;
16580 struct scan_chan_info *chan;
16581 uint8_t idx;
16582
16583 ENTER();
16584
16585 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16586 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16587 hdd_err("hdd_ctx is invalid");
16588 return;
16589 }
16590
16591 if (!hdd_ctx->chan_info) {
16592 hdd_err("chan_info is NULL");
16593 return;
16594 }
16595
16596 chan = hdd_ctx->chan_info;
16597 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16598 if (chan[idx].freq == info->freq) {
16599 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16600 info->cmd_flag);
16601 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16602 chan[idx].cmd_flag, chan[idx].freq,
16603 chan[idx].noise_floor,
16604 chan[idx].cycle_count, chan[idx].rx_clear_count,
16605 chan[idx].clock_freq, chan[idx].cmd_flag,
16606 chan[idx].tx_frame_count, idx);
16607 if (chan[idx].freq == 0)
16608 break;
16609
16610 }
16611 }
16612
16613 EXIT();
16614}
16615
16616/**
16617 * wlan_hdd_init_chan_info() - init chan info in hdd context
16618 * @hdd_ctx: HDD context pointer
16619 *
16620 * Return: none
16621 */
16622void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16623{
16624 uint8_t num_2g, num_5g, index = 0;
16625
16626 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16627 hdd_info("SNR monitoring is disabled");
16628 return;
16629 }
16630
16631 hdd_ctx->chan_info =
16632 qdf_mem_malloc(sizeof(struct scan_chan_info)
16633 * QDF_MAX_NUM_CHAN);
16634 if (hdd_ctx->chan_info == NULL) {
16635 hdd_err("Failed to malloc for chan info");
16636 return;
16637 }
16638 mutex_init(&hdd_ctx->chan_info_lock);
16639
16640 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16641 for (; index < num_2g; index++) {
16642 hdd_ctx->chan_info[index].freq =
16643 hdd_channels_2_4_ghz[index].center_freq;
16644 }
16645
16646 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16647 for (; (index - num_2g) < num_5g; index++) {
16648 if (cds_is_dsrc_channel(
16649 hdd_channels_5_ghz[index - num_2g].center_freq))
16650 continue;
16651 hdd_ctx->chan_info[index].freq =
16652 hdd_channels_5_ghz[index - num_2g].center_freq;
16653 }
16654 sme_set_chan_info_callback(hdd_ctx->hHal,
16655 &wlan_hdd_chan_info_cb);
16656}
16657
16658/**
16659 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16660 * @hdd_ctx: hdd context pointer
16661 *
16662 * Return: none
16663 */
16664void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16665{
16666 struct scan_chan_info *chan;
16667
16668 chan = hdd_ctx->chan_info;
16669 hdd_ctx->chan_info = NULL;
16670 if (chan)
16671 qdf_mem_free(chan);
16672}
16673
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016674/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016675 * struct cfg80211_ops - cfg80211_ops
16676 *
16677 * @add_virtual_intf: Add virtual interface
16678 * @del_virtual_intf: Delete virtual interface
16679 * @change_virtual_intf: Change virtual interface
16680 * @change_station: Change station
16681 * @add_beacon: Add beacon in sap mode
16682 * @del_beacon: Delete beacon in sap mode
16683 * @set_beacon: Set beacon in sap mode
16684 * @start_ap: Start ap
16685 * @change_beacon: Change beacon
16686 * @stop_ap: Stop ap
16687 * @change_bss: Change bss
16688 * @add_key: Add key
16689 * @get_key: Get key
16690 * @del_key: Delete key
16691 * @set_default_key: Set default key
16692 * @set_channel: Set channel
16693 * @scan: Scan
16694 * @connect: Connect
16695 * @disconnect: Disconnect
16696 * @join_ibss = Join ibss
16697 * @leave_ibss = Leave ibss
16698 * @set_wiphy_params = Set wiphy params
16699 * @set_tx_power = Set tx power
16700 * @get_tx_power = get tx power
16701 * @remain_on_channel = Remain on channel
16702 * @cancel_remain_on_channel = Cancel remain on channel
16703 * @mgmt_tx = Tx management frame
16704 * @mgmt_tx_cancel_wait = Cancel management tx wait
16705 * @set_default_mgmt_key = Set default management key
16706 * @set_txq_params = Set tx queue parameters
16707 * @get_station = Get station
16708 * @set_power_mgmt = Set power management
16709 * @del_station = Delete station
16710 * @add_station = Add station
16711 * @set_pmksa = Set pmksa
16712 * @del_pmksa = Delete pmksa
16713 * @flush_pmksa = Flush pmksa
16714 * @update_ft_ies = Update FT IEs
16715 * @tdls_mgmt = Tdls management
16716 * @tdls_oper = Tdls operation
16717 * @set_rekey_data = Set rekey data
16718 * @sched_scan_start = Scheduled scan start
16719 * @sched_scan_stop = Scheduled scan stop
16720 * @resume = Resume wlan
16721 * @suspend = Suspend wlan
16722 * @set_mac_acl = Set mac acl
16723 * @testmode_cmd = Test mode command
16724 * @set_ap_chanwidth = Set AP channel bandwidth
16725 * @dump_survey = Dump survey
16726 * @key_mgmt_set_pmk = Set pmk key management
16727 */
16728static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16729 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16730 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16731 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16732 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016733 .start_ap = wlan_hdd_cfg80211_start_ap,
16734 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16735 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016736 .change_bss = wlan_hdd_cfg80211_change_bss,
16737 .add_key = wlan_hdd_cfg80211_add_key,
16738 .get_key = wlan_hdd_cfg80211_get_key,
16739 .del_key = wlan_hdd_cfg80211_del_key,
16740 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16741 .scan = wlan_hdd_cfg80211_scan,
16742 .connect = wlan_hdd_cfg80211_connect,
16743 .disconnect = wlan_hdd_cfg80211_disconnect,
16744 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16745 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16746 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16747 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16748 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16749 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16750 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16751 .mgmt_tx = wlan_hdd_mgmt_tx,
16752 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16753 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16754 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016755 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016756 .get_station = wlan_hdd_cfg80211_get_station,
16757 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16758 .del_station = wlan_hdd_cfg80211_del_station,
16759 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016760 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16761 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16762 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016763#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016764 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16765#endif
16766#ifdef FEATURE_WLAN_TDLS
16767 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16768 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16769#endif
16770#ifdef WLAN_FEATURE_GTK_OFFLOAD
16771 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16772#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16773#ifdef FEATURE_WLAN_SCAN_PNO
16774 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16775 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16776#endif /*FEATURE_WLAN_SCAN_PNO */
16777 .resume = wlan_hdd_cfg80211_resume_wlan,
16778 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16779 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16780#ifdef WLAN_NL80211_TESTMODE
16781 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16782#endif
16783#ifdef QCA_HT_2040_COEX
16784 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16785#endif
16786 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016787#ifdef CHANNEL_SWITCH_SUPPORTED
16788 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16789#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016790 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016791#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16792 defined(CFG80211_ABORT_SCAN)
16793 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16794#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016795};