blob: 81245551e91911c3ffb4161163a05924ddb60e0e [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"
Agrawal Ashish65634612016-08-18 13:24:32 +053077
Paul Zhang3a210c52016-12-08 10:18:12 +080078#ifdef WLAN_UMAC_CONVERGENCE
79#include "wlan_cfg80211.h"
80#endif
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"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800101
Leo Changfdb45c32016-10-28 11:09:23 -0700102#include <cdp_txrx_cmn.h>
103#include <cdp_txrx_misc.h>
104
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105#define g_mode_rates_size (12)
106#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
108 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
109
110/*
111 * Android CTS verifier needs atleast this much wait time (in msec)
112 */
113#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
114
115/*
116 * Refer @tCfgProtection structure for definition of the bit map.
117 * below value is obtained by setting the following bit-fields.
118 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
119 */
120#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
121
122#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700123 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800124 .center_freq = (freq), \
125 .hw_value = (chan), \
126 .flags = (flag), \
127 .max_antenna_gain = 0, \
128 .max_power = 30, \
129}
130
131#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700132 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800133 .center_freq = (freq), \
134 .hw_value = (chan), \
135 .flags = (flag), \
136 .max_antenna_gain = 0, \
137 .max_power = 30, \
138}
139
140#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
141 { \
142 .bitrate = rate, \
143 .hw_value = rate_id, \
144 .flags = flag, \
145 }
146
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
148#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149
150#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151
Agrawal Ashish65634612016-08-18 13:24:32 +0530152#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
153 mode <= DFS_MODE_DEPRIORITIZE))
154#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
155 || (channel >= 36 && channel <= 184))
156
Peng Xu4d67c8f2015-10-16 16:02:26 -0700157#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530158#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700159
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160static const u32 hdd_cipher_suites[] = {
161 WLAN_CIPHER_SUITE_WEP40,
162 WLAN_CIPHER_SUITE_WEP104,
163 WLAN_CIPHER_SUITE_TKIP,
164#ifdef FEATURE_WLAN_ESE
165#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
166#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
167 WLAN_CIPHER_SUITE_BTK,
168 WLAN_CIPHER_SUITE_KRK,
169 WLAN_CIPHER_SUITE_CCMP,
170#else
171 WLAN_CIPHER_SUITE_CCMP,
172#endif
173#ifdef FEATURE_WLAN_WAPI
174 WLAN_CIPHER_SUITE_SMS4,
175#endif
176#ifdef WLAN_FEATURE_11W
177 WLAN_CIPHER_SUITE_AES_CMAC,
178#endif
179};
180
Abhishek Singhf512bf32016-05-04 16:47:46 +0530181static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800182 HDD2GHZCHAN(2412, 1, 0),
183 HDD2GHZCHAN(2417, 2, 0),
184 HDD2GHZCHAN(2422, 3, 0),
185 HDD2GHZCHAN(2427, 4, 0),
186 HDD2GHZCHAN(2432, 5, 0),
187 HDD2GHZCHAN(2437, 6, 0),
188 HDD2GHZCHAN(2442, 7, 0),
189 HDD2GHZCHAN(2447, 8, 0),
190 HDD2GHZCHAN(2452, 9, 0),
191 HDD2GHZCHAN(2457, 10, 0),
192 HDD2GHZCHAN(2462, 11, 0),
193 HDD2GHZCHAN(2467, 12, 0),
194 HDD2GHZCHAN(2472, 13, 0),
195 HDD2GHZCHAN(2484, 14, 0),
196};
197
Abhishek Singhf512bf32016-05-04 16:47:46 +0530198static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199 HDD5GHZCHAN(5180, 36, 0),
200 HDD5GHZCHAN(5200, 40, 0),
201 HDD5GHZCHAN(5220, 44, 0),
202 HDD5GHZCHAN(5240, 48, 0),
203 HDD5GHZCHAN(5260, 52, 0),
204 HDD5GHZCHAN(5280, 56, 0),
205 HDD5GHZCHAN(5300, 60, 0),
206 HDD5GHZCHAN(5320, 64, 0),
207 HDD5GHZCHAN(5500, 100, 0),
208 HDD5GHZCHAN(5520, 104, 0),
209 HDD5GHZCHAN(5540, 108, 0),
210 HDD5GHZCHAN(5560, 112, 0),
211 HDD5GHZCHAN(5580, 116, 0),
212 HDD5GHZCHAN(5600, 120, 0),
213 HDD5GHZCHAN(5620, 124, 0),
214 HDD5GHZCHAN(5640, 128, 0),
215 HDD5GHZCHAN(5660, 132, 0),
216 HDD5GHZCHAN(5680, 136, 0),
217 HDD5GHZCHAN(5700, 140, 0),
218 HDD5GHZCHAN(5720, 144, 0),
219 HDD5GHZCHAN(5745, 149, 0),
220 HDD5GHZCHAN(5765, 153, 0),
221 HDD5GHZCHAN(5785, 157, 0),
222 HDD5GHZCHAN(5805, 161, 0),
223 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224 HDD5GHZCHAN(5852, 170, 0),
225 HDD5GHZCHAN(5855, 171, 0),
226 HDD5GHZCHAN(5860, 172, 0),
227 HDD5GHZCHAN(5865, 173, 0),
228 HDD5GHZCHAN(5870, 174, 0),
229 HDD5GHZCHAN(5875, 175, 0),
230 HDD5GHZCHAN(5880, 176, 0),
231 HDD5GHZCHAN(5885, 177, 0),
232 HDD5GHZCHAN(5890, 178, 0),
233 HDD5GHZCHAN(5895, 179, 0),
234 HDD5GHZCHAN(5900, 180, 0),
235 HDD5GHZCHAN(5905, 181, 0),
236 HDD5GHZCHAN(5910, 182, 0),
237 HDD5GHZCHAN(5915, 183, 0),
238 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800239};
240
241static struct ieee80211_rate g_mode_rates[] = {
242 HDD_G_MODE_RATETAB(10, 0x1, 0),
243 HDD_G_MODE_RATETAB(20, 0x2, 0),
244 HDD_G_MODE_RATETAB(55, 0x4, 0),
245 HDD_G_MODE_RATETAB(110, 0x8, 0),
246 HDD_G_MODE_RATETAB(60, 0x10, 0),
247 HDD_G_MODE_RATETAB(90, 0x20, 0),
248 HDD_G_MODE_RATETAB(120, 0x40, 0),
249 HDD_G_MODE_RATETAB(180, 0x80, 0),
250 HDD_G_MODE_RATETAB(240, 0x100, 0),
251 HDD_G_MODE_RATETAB(360, 0x200, 0),
252 HDD_G_MODE_RATETAB(480, 0x400, 0),
253 HDD_G_MODE_RATETAB(540, 0x800, 0),
254};
255
256static struct ieee80211_rate a_mode_rates[] = {
257 HDD_G_MODE_RATETAB(60, 0x10, 0),
258 HDD_G_MODE_RATETAB(90, 0x20, 0),
259 HDD_G_MODE_RATETAB(120, 0x40, 0),
260 HDD_G_MODE_RATETAB(180, 0x80, 0),
261 HDD_G_MODE_RATETAB(240, 0x100, 0),
262 HDD_G_MODE_RATETAB(360, 0x200, 0),
263 HDD_G_MODE_RATETAB(480, 0x400, 0),
264 HDD_G_MODE_RATETAB(540, 0x800, 0),
265};
266
267static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530268 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800269 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700270 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800271 .bitrates = g_mode_rates,
272 .n_bitrates = g_mode_rates_size,
273 .ht_cap.ht_supported = 1,
274 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
275 | IEEE80211_HT_CAP_GRN_FLD
276 | IEEE80211_HT_CAP_DSSSCCK40
277 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
278 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
279 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
280 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
281 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
282 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
283 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
284};
285
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530287 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700289 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800290 .bitrates = a_mode_rates,
291 .n_bitrates = a_mode_rates_size,
292 .ht_cap.ht_supported = 1,
293 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
294 | IEEE80211_HT_CAP_GRN_FLD
295 | IEEE80211_HT_CAP_DSSSCCK40
296 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
297 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
298 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
299 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
300 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
301 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
302 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
303 .vht_cap.vht_supported = 1,
304};
305
306/* This structure contain information what kind of frame are expected in
307 TX/RX direction for each kind of interface */
308static const struct ieee80211_txrx_stypes
309 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
310 [NL80211_IFTYPE_STATION] = {
311 .tx = 0xffff,
312 .rx = BIT(SIR_MAC_MGMT_ACTION) |
313 BIT(SIR_MAC_MGMT_PROBE_REQ),
314 },
315 [NL80211_IFTYPE_AP] = {
316 .tx = 0xffff,
317 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
318 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
319 BIT(SIR_MAC_MGMT_PROBE_REQ) |
320 BIT(SIR_MAC_MGMT_DISASSOC) |
321 BIT(SIR_MAC_MGMT_AUTH) |
322 BIT(SIR_MAC_MGMT_DEAUTH) |
323 BIT(SIR_MAC_MGMT_ACTION),
324 },
325 [NL80211_IFTYPE_ADHOC] = {
326 .tx = 0xffff,
327 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
328 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_PROBE_REQ) |
330 BIT(SIR_MAC_MGMT_DISASSOC) |
331 BIT(SIR_MAC_MGMT_AUTH) |
332 BIT(SIR_MAC_MGMT_DEAUTH) |
333 BIT(SIR_MAC_MGMT_ACTION),
334 },
335 [NL80211_IFTYPE_P2P_CLIENT] = {
336 .tx = 0xffff,
337 .rx = BIT(SIR_MAC_MGMT_ACTION) |
338 BIT(SIR_MAC_MGMT_PROBE_REQ),
339 },
340 [NL80211_IFTYPE_P2P_GO] = {
341 /* This is also same as for SoftAP */
342 .tx = 0xffff,
343 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
344 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
345 BIT(SIR_MAC_MGMT_PROBE_REQ) |
346 BIT(SIR_MAC_MGMT_DISASSOC) |
347 BIT(SIR_MAC_MGMT_AUTH) |
348 BIT(SIR_MAC_MGMT_DEAUTH) |
349 BIT(SIR_MAC_MGMT_ACTION),
350 },
351};
352
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800353/* Interface limits and combinations registered by the driver */
354
355/* STA ( + STA ) combination */
356static const struct ieee80211_iface_limit
357 wlan_hdd_sta_iface_limit[] = {
358 {
359 .max = 3, /* p2p0 is a STA as well */
360 .types = BIT(NL80211_IFTYPE_STATION),
361 },
362};
363
364/* ADHOC (IBSS) limit */
365static const struct ieee80211_iface_limit
366 wlan_hdd_adhoc_iface_limit[] = {
367 {
368 .max = 1,
369 .types = BIT(NL80211_IFTYPE_STATION),
370 },
371 {
372 .max = 1,
373 .types = BIT(NL80211_IFTYPE_ADHOC),
374 },
375};
376
377/* AP ( + AP ) combination */
378static const struct ieee80211_iface_limit
379 wlan_hdd_ap_iface_limit[] = {
380 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530381 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800382 .types = BIT(NL80211_IFTYPE_AP),
383 },
384};
385
386/* P2P limit */
387static const struct ieee80211_iface_limit
388 wlan_hdd_p2p_iface_limit[] = {
389 {
390 .max = 1,
391 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
392 },
393 {
394 .max = 1,
395 .types = BIT(NL80211_IFTYPE_P2P_GO),
396 },
397};
398
399static const struct ieee80211_iface_limit
400 wlan_hdd_sta_ap_iface_limit[] = {
401 {
402 /* We need 1 extra STA interface for OBSS scan when SAP starts
403 * with HT40 in STA+SAP concurrency mode
404 */
405 .max = (1 + SAP_MAX_OBSS_STA_CNT),
406 .types = BIT(NL80211_IFTYPE_STATION),
407 },
408 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530409 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800410 .types = BIT(NL80211_IFTYPE_AP),
411 },
412};
413
414/* STA + P2P combination */
415static const struct ieee80211_iface_limit
416 wlan_hdd_sta_p2p_iface_limit[] = {
417 {
418 /* One reserved for dedicated P2PDEV usage */
419 .max = 2,
420 .types = BIT(NL80211_IFTYPE_STATION)
421 },
422 {
423 /* Support for two identical (GO + GO or CLI + CLI)
424 * or dissimilar (GO + CLI) P2P interfaces
425 */
426 .max = 2,
427 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
428 },
429};
430
431/* STA + AP + P2PGO combination */
432static const struct ieee80211_iface_limit
433wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
434 /* Support for AP+P2PGO interfaces */
435 {
436 .max = 2,
437 .types = BIT(NL80211_IFTYPE_STATION)
438 },
439 {
440 .max = 1,
441 .types = BIT(NL80211_IFTYPE_P2P_GO)
442 },
443 {
444 .max = 1,
445 .types = BIT(NL80211_IFTYPE_AP)
446 }
447};
448
449/* SAP + P2P combination */
450static const struct ieee80211_iface_limit
451wlan_hdd_sap_p2p_iface_limit[] = {
452 {
453 /* 1 dedicated for p2p0 which is a STA type */
454 .max = 1,
455 .types = BIT(NL80211_IFTYPE_STATION)
456 },
457 {
458 /* The p2p interface in SAP+P2P can be GO/CLI.
459 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
460 */
461 .max = 1,
462 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
463 },
464 {
465 /* SAP+GO to support only one SAP interface */
466 .max = 1,
467 .types = BIT(NL80211_IFTYPE_AP)
468 }
469};
470
471/* P2P + P2P combination */
472static const struct ieee80211_iface_limit
473wlan_hdd_p2p_p2p_iface_limit[] = {
474 {
475 /* 1 dedicated for p2p0 which is a STA type */
476 .max = 1,
477 .types = BIT(NL80211_IFTYPE_STATION)
478 },
479 {
480 /* The p2p interface in P2P+P2P can be GO/CLI.
481 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
482 */
483 .max = 2,
484 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
485 },
486};
487
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700488static const struct ieee80211_iface_limit
489 wlan_hdd_mon_iface_limit[] = {
490 {
491 .max = 3, /* Monitor interface */
492 .types = BIT(NL80211_IFTYPE_MONITOR),
493 },
494};
495
496static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497 wlan_hdd_iface_combination[] = {
498 /* STA */
499 {
500 .limits = wlan_hdd_sta_iface_limit,
501 .num_different_channels = 2,
502 .max_interfaces = 3,
503 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
504 },
505 /* ADHOC */
506 {
507 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700508 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800509 .max_interfaces = 2,
510 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
511 },
512 /* AP */
513 {
514 .limits = wlan_hdd_ap_iface_limit,
515 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530516 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
518 },
519 /* P2P */
520 {
521 .limits = wlan_hdd_p2p_iface_limit,
522 .num_different_channels = 2,
523 .max_interfaces = 2,
524 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
525 },
526 /* STA + AP */
527 {
528 .limits = wlan_hdd_sta_ap_iface_limit,
529 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530530 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800531 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
532 .beacon_int_infra_match = true,
533 },
534 /* STA + P2P */
535 {
536 .limits = wlan_hdd_sta_p2p_iface_limit,
537 .num_different_channels = 2,
538 /* one interface reserved for P2PDEV dedicated usage */
539 .max_interfaces = 4,
540 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
541 .beacon_int_infra_match = true,
542 },
543 /* STA + P2P GO + SAP */
544 {
545 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
546 /* we can allow 3 channels for three different persona
547 * but due to firmware limitation, allow max 2 concrnt channels.
548 */
549 .num_different_channels = 2,
550 /* one interface reserved for P2PDEV dedicated usage */
551 .max_interfaces = 4,
552 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
553 .beacon_int_infra_match = true,
554 },
555 /* SAP + P2P */
556 {
557 .limits = wlan_hdd_sap_p2p_iface_limit,
558 .num_different_channels = 2,
559 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
560 .max_interfaces = 3,
561 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
562 .beacon_int_infra_match = true,
563 },
564 /* P2P + P2P */
565 {
566 .limits = wlan_hdd_p2p_p2p_iface_limit,
567 .num_different_channels = 2,
568 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
569 .max_interfaces = 3,
570 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
571 .beacon_int_infra_match = true,
572 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530573 /* Monitor */
574 {
575 .limits = wlan_hdd_mon_iface_limit,
576 .max_interfaces = 3,
577 .num_different_channels = 2,
578 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
579 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581
582static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530583struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800584
585#ifdef WLAN_NL80211_TESTMODE
586enum wlan_hdd_tm_attr {
587 WLAN_HDD_TM_ATTR_INVALID = 0,
588 WLAN_HDD_TM_ATTR_CMD = 1,
589 WLAN_HDD_TM_ATTR_DATA = 2,
590 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
591 WLAN_HDD_TM_ATTR_TYPE = 4,
592 /* keep last */
593 WLAN_HDD_TM_ATTR_AFTER_LAST,
594 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
595};
596
597enum wlan_hdd_tm_cmd {
598 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
599 WLAN_HDD_TM_CMD_WLAN_HB = 1,
600};
601
602#define WLAN_HDD_TM_DATA_MAX_LEN 5000
603
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530604enum wlan_hdd_vendor_ie_access_policy {
605 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
606 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
607};
608
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800609static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
610 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
611 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
612 .len = WLAN_HDD_TM_DATA_MAX_LEN},
613};
614#endif /* WLAN_NL80211_TESTMODE */
615
616#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
617static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
618 .flags = WIPHY_WOWLAN_MAGIC_PKT,
619 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
620 .pattern_min_len = 1,
621 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
622};
623#endif
624
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800625/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530626 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
627 * @flags: Pointer to the flags to Add channel switch flag.
628 *
629 * This Function adds Channel Switch support flag, if channel switch is
630 * supported by kernel.
631 * Return: void.
632 */
633#ifdef CHANNEL_SWITCH_SUPPORTED
634static inline void hdd_add_channel_switch_support(uint32_t *flags)
635{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800636 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530637 return;
638}
639#else
640static inline void hdd_add_channel_switch_support(uint32_t *flags)
641{
642 return;
643}
644#endif
645
Manikandan Mohan22b83722015-12-15 15:03:23 -0800646#ifdef FEATURE_WLAN_TDLS
647
648/* TDLS capabilities params */
649#define PARAM_MAX_TDLS_SESSION \
650 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
651#define PARAM_TDLS_FEATURE_SUPPORT \
652 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
653
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530654/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800655 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
656 * @wiphy: WIPHY structure pointer
657 * @wdev: Wireless device structure pointer
658 * @data: Pointer to the data received
659 * @data_len: Length of the data received
660 *
661 * This function provides TDLS capabilities
662 *
663 * Return: 0 on success and errno on failure
664 */
665static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
666 struct wireless_dev *wdev,
667 const void *data,
668 int data_len)
669{
670 int status;
671 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
672 struct sk_buff *skb;
673 uint32_t set = 0;
674
Jeff Johnson1f61b612016-02-12 16:28:33 -0800675 ENTER_DEV(wdev->netdev);
676
Anurag Chouhan6d760662016-02-20 16:05:43 +0530677 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800678 hdd_err("Command not allowed in FTM mode");
679 return -EPERM;
680 }
681
682 status = wlan_hdd_validate_context(hdd_ctx);
683 if (status)
684 return status;
685
686 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
687 NLMSG_HDRLEN);
688 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700689 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800690 goto fail;
691 }
692
693 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700694 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800695 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
696 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700697 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698 goto fail;
699 }
700 } else {
701 set = set | WIFI_TDLS_SUPPORT;
702 set = set | (hdd_ctx->config->fTDLSExternalControl ?
703 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
704 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
705 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700706 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800707 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
708 hdd_ctx->max_num_tdls_sta) ||
709 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
710 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700711 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800712 goto fail;
713 }
714 }
715 return cfg80211_vendor_cmd_reply(skb);
716fail:
717 if (skb)
718 kfree_skb(skb);
719 return -EINVAL;
720}
721
722/**
723 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
724 * @wiphy: WIPHY structure pointer
725 * @wdev: Wireless device structure pointer
726 * @data: Pointer to the data received
727 * @data_len: Length of the data received
728 *
729 * This function provides TDLS capabilities
730 *
731 * Return: 0 on success and errno on failure
732 */
733static int
734wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
735 struct wireless_dev *wdev,
736 const void *data,
737 int data_len)
738{
739 int ret;
740
741 cds_ssr_protect(__func__);
742 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
743 data, data_len);
744 cds_ssr_unprotect(__func__);
745
746 return ret;
747}
748#endif
749
750#ifdef QCA_HT_2040_COEX
751static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
752#endif
753
754#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
755/*
756 * FUNCTION: wlan_hdd_send_avoid_freq_event
757 * This is called when wlan driver needs to send vendor specific
758 * avoid frequency range event to userspace
759 */
760int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
761 tHddAvoidFreqList *pAvoidFreqList)
762{
763 struct sk_buff *vendor_event;
764
765 ENTER();
766
767 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700768 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769 return -EINVAL;
770 }
771
772 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700773 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800774 return -EINVAL;
775 }
776
777 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
778 NULL,
779 sizeof(tHddAvoidFreqList),
780 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
781 GFP_KERNEL);
782 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700783 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784 return -EINVAL;
785 }
786
787 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
788 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
789
790 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
791
792 EXIT();
793 return 0;
794}
795#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
796
797/* vendor specific events */
798static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
799#ifdef FEATURE_WLAN_CH_AVOID
800 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
801 .vendor_id =
802 QCA_NL80211_VENDOR_ID,
803 .subcmd =
804 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
805 },
806#endif /* FEATURE_WLAN_CH_AVOID */
807
808#ifdef WLAN_FEATURE_NAN
809 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
810 .vendor_id =
811 QCA_NL80211_VENDOR_ID,
812 .subcmd =
813 QCA_NL80211_VENDOR_SUBCMD_NAN
814 },
815#endif
816
817#ifdef WLAN_FEATURE_STATS_EXT
818 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
819 .vendor_id =
820 QCA_NL80211_VENDOR_ID,
821 .subcmd =
822 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
823 },
824#endif /* WLAN_FEATURE_STATS_EXT */
825#ifdef FEATURE_WLAN_EXTSCAN
826 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
827 .vendor_id =
828 QCA_NL80211_VENDOR_ID,
829 .subcmd =
830 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
831 },
832 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
833 .vendor_id =
834 QCA_NL80211_VENDOR_ID,
835 .subcmd =
836 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
837 },
838 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
839 .
840 vendor_id
841 =
842 QCA_NL80211_VENDOR_ID,
843 .subcmd =
844 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
845 },
846 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
847 .
848 vendor_id
849 =
850 QCA_NL80211_VENDOR_ID,
851 .
852 subcmd =
853 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
854 },
855 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
856 .
857 vendor_id
858 =
859 QCA_NL80211_VENDOR_ID,
860 .
861 subcmd
862 =
863 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
864 },
865 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
866 .
867 vendor_id
868 =
869 QCA_NL80211_VENDOR_ID,
870 .subcmd =
871 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
872 },
873 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
874 .vendor_id =
875 QCA_NL80211_VENDOR_ID,
876 .subcmd =
877 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
878 },
879 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
880 .
881 vendor_id
882 =
883 QCA_NL80211_VENDOR_ID,
884 .subcmd =
885 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
886 },
887 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
888 .
889 vendor_id
890 =
891 QCA_NL80211_VENDOR_ID,
892 .subcmd =
893 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
894 },
895 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
896 .
897 vendor_id
898 =
899 QCA_NL80211_VENDOR_ID,
900 .
901 subcmd
902 =
903 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
904 },
905 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
906 .
907 vendor_id
908 =
909 QCA_NL80211_VENDOR_ID,
910 .
911 subcmd =
912 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
913 },
914 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
915 .
916 vendor_id
917 =
918 QCA_NL80211_VENDOR_ID,
919 .
920 subcmd
921 =
922 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
923 },
924 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
925 .
926 vendor_id
927 =
928 QCA_NL80211_VENDOR_ID,
929 .
930 subcmd
931 =
932 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
933 },
934 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
935 .vendor_id = QCA_NL80211_VENDOR_ID,
936 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
937 },
938 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
939 .vendor_id = QCA_NL80211_VENDOR_ID,
940 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
941 },
942#endif /* FEATURE_WLAN_EXTSCAN */
943
944#ifdef WLAN_FEATURE_LINK_LAYER_STATS
945 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
946 .vendor_id =
947 QCA_NL80211_VENDOR_ID,
948 .subcmd =
949 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
950 },
951 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
952 .vendor_id =
953 QCA_NL80211_VENDOR_ID,
954 .subcmd =
955 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
956 },
957 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
958 .vendor_id =
959 QCA_NL80211_VENDOR_ID,
960 .subcmd =
961 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
962 },
963 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
964 .vendor_id =
965 QCA_NL80211_VENDOR_ID,
966 .subcmd =
967 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
968 },
969 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
970 .vendor_id =
971 QCA_NL80211_VENDOR_ID,
972 .subcmd =
973 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
974 },
975 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
976 .vendor_id =
977 QCA_NL80211_VENDOR_ID,
978 .subcmd =
979 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
980 },
981#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
982 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
983 .vendor_id =
984 QCA_NL80211_VENDOR_ID,
985 .subcmd =
986 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
987 },
988 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
989 .vendor_id = QCA_NL80211_VENDOR_ID,
990 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
991 },
992#ifdef WLAN_FEATURE_ROAM_OFFLOAD
993 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
994 .vendor_id =
995 QCA_NL80211_VENDOR_ID,
996 .subcmd =
997 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
998 },
999#endif
1000 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1001 .vendor_id =
1002 QCA_NL80211_VENDOR_ID,
1003 .subcmd =
1004 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1005 },
1006 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1007 .vendor_id =
1008 QCA_NL80211_VENDOR_ID,
1009 .subcmd =
1010 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1011 },
1012 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1013 .vendor_id =
1014 QCA_NL80211_VENDOR_ID,
1015 .subcmd =
1016 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1017 },
1018 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1019 .vendor_id =
1020 QCA_NL80211_VENDOR_ID,
1021 .subcmd =
1022 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1023 },
1024 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1025 .vendor_id =
1026 QCA_NL80211_VENDOR_ID,
1027 .subcmd =
1028 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1029 },
1030#ifdef FEATURE_WLAN_EXTSCAN
1031 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1032 .vendor_id = QCA_NL80211_VENDOR_ID,
1033 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1034 },
1035 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1036 .vendor_id = QCA_NL80211_VENDOR_ID,
1037 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1038 },
1039 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1040 .vendor_id = QCA_NL80211_VENDOR_ID,
1041 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1042 },
1043 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1044 .vendor_id = QCA_NL80211_VENDOR_ID,
1045 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1046 },
1047 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1048 .vendor_id = QCA_NL80211_VENDOR_ID,
1049 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1050 },
1051#endif /* FEATURE_WLAN_EXTSCAN */
1052 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1053 .vendor_id = QCA_NL80211_VENDOR_ID,
1054 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1055 },
1056#ifdef WLAN_FEATURE_MEMDUMP
1057 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1058 .vendor_id = QCA_NL80211_VENDOR_ID,
1059 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1060 },
1061#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001062#ifdef WLAN_FEATURE_TSF
1063 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1064 .vendor_id = QCA_NL80211_VENDOR_ID,
1065 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1066 },
1067#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001068 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1069 .vendor_id = QCA_NL80211_VENDOR_ID,
1070 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1071 },
1072 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1073 .vendor_id = QCA_NL80211_VENDOR_ID,
1074 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1075 },
1076 /* OCB events */
1077 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1078 .vendor_id = QCA_NL80211_VENDOR_ID,
1079 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1080 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001081#ifdef FEATURE_LFR_SUBNET_DETECTION
1082 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1083 .vendor_id = QCA_NL80211_VENDOR_ID,
1084 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1085 },
1086#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001087
1088#ifdef WLAN_FEATURE_NAN_DATAPATH
1089 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1090 .vendor_id = QCA_NL80211_VENDOR_ID,
1091 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1092 },
1093#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001094
1095 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1096 .vendor_id = QCA_NL80211_VENDOR_ID,
1097 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1098 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301099 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1100 .vendor_id = QCA_NL80211_VENDOR_ID,
1101 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1102 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001103#ifdef WLAN_UMAC_CONVERGENCE
1104 COMMON_VENDOR_EVENTS
1105#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001106};
1107
1108/**
1109 * __is_driver_dfs_capable() - get driver DFS capability
1110 * @wiphy: pointer to wireless wiphy structure.
1111 * @wdev: pointer to wireless_dev structure.
1112 * @data: Pointer to the data to be passed via vendor interface
1113 * @data_len:Length of the data to be passed
1114 *
1115 * This function is called by userspace to indicate whether or not
1116 * the driver supports DFS offload.
1117 *
1118 * Return: 0 on success, negative errno on failure
1119 */
1120static int __is_driver_dfs_capable(struct wiphy *wiphy,
1121 struct wireless_dev *wdev,
1122 const void *data,
1123 int data_len)
1124{
1125 u32 dfs_capability = 0;
1126 struct sk_buff *temp_skbuff;
1127 int ret_val;
1128 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1129
Jeff Johnson1f61b612016-02-12 16:28:33 -08001130 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001131
1132 ret_val = wlan_hdd_validate_context(hdd_ctx);
1133 if (ret_val)
1134 return ret_val;
1135
Anurag Chouhan6d760662016-02-20 16:05:43 +05301136 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137 hdd_err("Command not allowed in FTM mode");
1138 return -EPERM;
1139 }
1140
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001141 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142
1143 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1144 NLMSG_HDRLEN);
1145
1146 if (temp_skbuff != NULL) {
1147 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1148 dfs_capability);
1149 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001150 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001151 kfree_skb(temp_skbuff);
1152
1153 return ret_val;
1154 }
1155
1156 return cfg80211_vendor_cmd_reply(temp_skbuff);
1157 }
1158
Jeff Johnson020db452016-06-29 14:37:26 -07001159 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001160 return -ENOMEM;
1161}
1162
1163/**
1164 * is_driver_dfs_capable() - get driver DFS capability
1165 * @wiphy: pointer to wireless wiphy structure.
1166 * @wdev: pointer to wireless_dev structure.
1167 * @data: Pointer to the data to be passed via vendor interface
1168 * @data_len:Length of the data to be passed
1169 *
1170 * This function is called by userspace to indicate whether or not
1171 * the driver supports DFS offload. This is an SSR-protected
1172 * wrapper function.
1173 *
1174 * Return: 0 on success, negative errno on failure
1175 */
1176static int is_driver_dfs_capable(struct wiphy *wiphy,
1177 struct wireless_dev *wdev,
1178 const void *data,
1179 int data_len)
1180{
1181 int ret;
1182
1183 cds_ssr_protect(__func__);
1184 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1185 cds_ssr_unprotect(__func__);
1186
1187 return ret;
1188}
1189
1190/**
1191 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1192 *
1193 * @adapter: SAP adapter pointer
1194 *
1195 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1196 * radio. So in case of DFS MCC scenario override current SAP given config
1197 * to follow concurrent SAP DFS config
1198 *
1199 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1200 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001201int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1202{
1203 hdd_adapter_t *con_sap_adapter;
1204 tsap_Config_t *sap_config, *con_sap_config;
1205 int con_ch;
1206
1207 /*
1208 * Check if AP+AP case, once primary AP chooses a DFS
1209 * channel secondary AP should always follow primary APs channel
1210 */
1211 if (!cds_concurrent_beaconing_sessions_running())
1212 return 0;
1213
1214 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1215 if (!con_sap_adapter)
1216 return 0;
1217
1218 sap_config = &adapter->sessionCtx.ap.sapConfig;
1219 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1220 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1221
1222 if (!CDS_IS_DFS_CH(con_ch))
1223 return 0;
1224
Jeff Johnson020db452016-06-29 14:37:26 -07001225 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001226 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001227 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001228 sap_config->channel = con_ch;
1229
1230 if (con_sap_config->acs_cfg.acs_mode == true) {
1231 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1232 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001233 hdd_err("Primary AP channel config error");
1234 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001235 con_ch, con_sap_config->acs_cfg.pri_ch,
1236 con_sap_config->acs_cfg.ht_sec_ch);
1237 return -EINVAL;
1238 }
1239 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1240 * MCC restriction. So free ch list allocated in do_acs
1241 * func for Sec AP and realloc for Pri AP ch list size
1242 */
1243 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301244 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001245
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301246 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001247 &con_sap_config->acs_cfg,
1248 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301249 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001250 sizeof(uint8_t) *
1251 con_sap_config->acs_cfg.ch_list_count);
1252 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001253 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001254 return -ENOMEM;
1255 }
1256
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301257 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258 con_sap_config->acs_cfg.ch_list,
1259 con_sap_config->acs_cfg.ch_list_count);
1260
1261 } else {
1262 sap_config->acs_cfg.pri_ch = con_ch;
1263 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1264 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1265 }
1266
1267 return con_ch;
1268}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001269
1270/**
1271 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1272 * @sap_cfg: pointer to SAP config struct
1273 *
1274 * This function sets the default ACS start and end channel for the given band
1275 * and also parses the given ACS channel list.
1276 *
1277 * Return: None
1278 */
1279
1280static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1281 bool vht_enabled)
1282{
1283 int i;
1284 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1285 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001286 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1287 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001288 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1289 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001290 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1291 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001292 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1293 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001294 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1295 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001296 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1297 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001298 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1299 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001300 }
1301
1302 if (ht_enabled)
1303 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1304
1305 if (vht_enabled)
1306 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1307
1308
1309 /* Parse ACS Chan list from hostapd */
1310 if (!sap_cfg->acs_cfg.ch_list)
1311 return;
1312
1313 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1314 sap_cfg->acs_cfg.end_ch =
1315 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1316 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301317 /* avoid channel as start channel */
1318 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1319 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001320 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1321 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1322 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1323 }
1324}
1325
1326
1327static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1328
1329/**
1330 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1331 * @adapter: pointer to SAP adapter struct
1332 *
1333 * This function starts the ACS procedure if there are no
1334 * constraints like MBSSID DFS restrictions.
1335 *
1336 * Return: Status of ACS Start procedure
1337 */
1338
1339static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1340{
1341
1342 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1343 tsap_Config_t *sap_config;
1344 tpWLAN_SAPEventCB acs_event_callback;
1345 int status;
1346
1347 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301348 if (hdd_ctx->acs_policy.acs_channel)
1349 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1350 else
1351 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001352
1353 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1354 if (status < 0) {
1355 return status;
1356 } else {
1357 if (status > 0) {
1358 /*notify hostapd about channel override */
1359 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1360 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1361 return 0;
1362 }
1363 }
1364 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1365 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001366 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001367 return -EINVAL;
1368 }
1369
1370 acs_event_callback = hdd_hostapd_sap_event_cb;
1371
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301372 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301373 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001374 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001375 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 acs_event_callback, sap_config, adapter->dev);
1378
1379
1380 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001381 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382 return -EINVAL;
1383 }
1384 sap_config->acs_cfg.acs_mode = true;
1385 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1386
1387 return 0;
1388}
1389
1390/**
1391 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1392 * @wiphy: Linux wiphy struct pointer
1393 * @wdev: Linux wireless device struct pointer
1394 * @data: ACS information from hostapd
1395 * @data_len: ACS information length
1396 *
1397 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1398 * and starts ACS procedure.
1399 *
1400 * Return: ACS procedure start status
1401 */
1402
1403static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1404 struct wireless_dev *wdev,
1405 const void *data, int data_len)
1406{
1407 struct net_device *ndev = wdev->netdev;
1408 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1409 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1410 tsap_Config_t *sap_config;
1411 struct sk_buff *temp_skbuff;
1412 int status = -EINVAL, i = 0;
1413 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1414 bool ht_enabled, ht40_enabled, vht_enabled;
1415 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301416 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001417
1418 /* ***Note*** Donot set SME config related to ACS operation here because
1419 * ACS operation is not synchronouse and ACS for Second AP may come when
1420 * ACS operation for first AP is going on. So only do_acs is split to
1421 * seperate start_acs routine. Also SME-PMAC struct that is used to
1422 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1423 * config shall be set only from start_acs.
1424 */
1425
1426 /* nla_policy Policy template. Policy not applied as some attributes are
1427 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1428 *
1429 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1430 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1431 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1432 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1433 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1434 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1435 */
1436
Jeff Johnson1f61b612016-02-12 16:28:33 -08001437 ENTER_DEV(ndev);
1438
Anurag Chouhan6d760662016-02-20 16:05:43 +05301439 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001440 hdd_err("Command not allowed in FTM mode");
1441 return -EPERM;
1442 }
1443
1444 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001445 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001446 return -EPERM;
1447 }
1448
1449 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301450 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001451 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301452
Naveen Rawat64e477e2016-05-20 10:34:56 -07001453 if (cds_is_sub_20_mhz_enabled()) {
1454 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1455 status = -EINVAL;
1456 goto out;
1457 }
1458
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001459 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301460 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001461
1462 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1463 NULL);
1464 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001465 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001466 goto out;
1467 }
1468
1469 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001470 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001471 goto out;
1472 }
1473 sap_config->acs_cfg.hw_mode = nla_get_u8(
1474 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1475
1476 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1477 ht_enabled =
1478 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1479 else
1480 ht_enabled = 0;
1481
1482 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1483 ht40_enabled =
1484 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1485 else
1486 ht40_enabled = 0;
1487
1488 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1489 vht_enabled =
1490 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1491 else
1492 vht_enabled = 0;
1493
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301494 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1495 vht_enabled = 0;
1496 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1497 }
1498
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001499 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1500 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1501 } else {
1502 if (ht_enabled && ht40_enabled)
1503 ch_width = 40;
1504 else
1505 ch_width = 20;
1506 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301507
1508 /* this may be possible, when sap_force_11n_for_11ac is set */
1509 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1510 if (ht_enabled && ht40_enabled)
1511 ch_width = 40;
1512 else
1513 ch_width = 20;
1514 }
1515
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001516 if (ch_width == 80)
1517 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1518 else if (ch_width == 40)
1519 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1520 else
1521 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1522
1523 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1524 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1525 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1526 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1527 * since it contains the frequency values of the channels in
1528 * the channel list.
1529 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1530 * is present
1531 */
1532 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1533 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1534 sap_config->acs_cfg.ch_list_count = nla_len(
1535 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1536 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301537 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001538 sizeof(uint8_t) *
1539 sap_config->acs_cfg.ch_list_count);
1540 if (sap_config->acs_cfg.ch_list == NULL)
1541 goto out;
1542
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301543 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001544 sap_config->acs_cfg.ch_list_count);
1545 }
1546 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1547 uint32_t *freq =
1548 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1549 sap_config->acs_cfg.ch_list_count = nla_len(
1550 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1551 sizeof(uint32_t);
1552 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301553 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001554 sap_config->acs_cfg.ch_list_count);
1555 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001556 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001557 status = -ENOMEM;
1558 goto out;
1559 }
1560
1561 /* convert frequency to channel */
1562 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1563 sap_config->acs_cfg.ch_list[i] =
1564 ieee80211_frequency_to_channel(freq[i]);
1565 }
1566 }
1567
1568 hdd_debug("get pcl for DO_ACS vendor command");
1569
1570 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001571 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301572 sap_config->acs_cfg.pcl_channels,
1573 &sap_config->acs_cfg.pcl_ch_count,
1574 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301575 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001576 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001577
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001578 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301579 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
1580 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07001581 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001582 vht_enabled = 1;
1583 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1584 sap_config->acs_cfg.ch_width =
1585 hdd_ctx->config->vhtChannelWidth;
1586 /* No VHT80 in 2.4G so perform ACS accordingly */
1587 if (sap_config->acs_cfg.end_ch <= 14 &&
1588 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1589 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1590 }
1591
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301592 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1593
Jeff Johnson020db452016-06-29 14:37:26 -07001594 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 -08001595 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1596 ch_width, ht_enabled, vht_enabled,
1597 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1598
1599 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001600 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001601 sap_config->acs_cfg.ch_list_count);
1602 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001603 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001604 }
1605 sap_config->acs_cfg.acs_mode = true;
1606 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001607 /* ***Note*** Completion variable usage is not allowed
1608 * here since ACS scan operation may take max 2.2 sec
1609 * for 5G band:
1610 * 9 Active channel X 40 ms active scan time +
1611 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001612 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1613 * for this long. So we split up the scanning part.
1614 */
1615 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001616 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001617 status = 0;
1618 } else {
1619 status = wlan_hdd_cfg80211_start_acs(adapter);
1620 }
1621
1622out:
1623 if (0 == status) {
1624 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1625 NLMSG_HDRLEN);
1626 if (temp_skbuff != NULL)
1627 return cfg80211_vendor_cmd_reply(temp_skbuff);
1628 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001629 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001630 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1631
1632 return status;
1633}
1634
1635 /**
1636 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1637 * @wiphy: Linux wiphy struct pointer
1638 * @wdev: Linux wireless device struct pointer
1639 * @data: ACS information from hostapd
1640 * @data_len: ACS information len
1641 *
1642 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1643 * and starts ACS procedure.
1644 *
1645 * Return: ACS procedure start status
1646 */
1647
1648static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1649 struct wireless_dev *wdev,
1650 const void *data, int data_len)
1651{
1652 int ret;
1653
1654 cds_ssr_protect(__func__);
1655 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1656 cds_ssr_unprotect(__func__);
1657
1658 return ret;
1659}
1660
1661/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001662 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
1663 * @adapter: Pointer to adapter struct
1664 *
1665 * This function handle cleanup of what was done in DO_ACS, including free
1666 * memory.
1667 *
1668 * Return: void
1669 */
1670
1671void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
1672{
1673 if (adapter == NULL)
1674 return;
1675 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
1676 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
1677 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
1678 }
1679}
1680
1681/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001682 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1683 * @work: Linux workqueue struct pointer for ACS work
1684 *
1685 * This function starts the ACS procedure which was marked pending when an ACS
1686 * procedure was in progress for a concurrent SAP interface.
1687 *
1688 * Return: None
1689 */
1690
1691static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1692{
1693 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1694 acs_pending_work.work);
1695 wlan_hdd_cfg80211_start_acs(adapter);
1696}
1697
1698/**
1699 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1700 * @adapter: Pointer to SAP adapter struct
1701 * @pri_channel: SAP ACS procedure selected Primary channel
1702 * @sec_channel: SAP ACS procedure selected secondary channel
1703 *
1704 * This is a callback function from SAP module on ACS procedure is completed.
1705 * This function send the ACS selected channel information to hostapd
1706 *
1707 * Return: None
1708 */
1709
1710void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1711{
1712 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1713 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1714 struct sk_buff *vendor_event;
1715 int ret_val;
1716 hdd_adapter_t *con_sap_adapter;
1717 uint16_t ch_width;
1718
1719 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001720 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001721 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1722 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1723 GFP_KERNEL);
1724
1725 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001726 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001727 return;
1728 }
1729
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001730 ret_val = nla_put_u8(vendor_event,
1731 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1732 sap_cfg->acs_cfg.pri_ch);
1733 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001734 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001735 kfree_skb(vendor_event);
1736 return;
1737 }
1738
1739 ret_val = nla_put_u8(vendor_event,
1740 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1741 sap_cfg->acs_cfg.ht_sec_ch);
1742 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001743 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001744 kfree_skb(vendor_event);
1745 return;
1746 }
1747
1748 ret_val = nla_put_u8(vendor_event,
1749 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1750 sap_cfg->acs_cfg.vht_seg0_center_ch);
1751 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001752 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001753 kfree_skb(vendor_event);
1754 return;
1755 }
1756
1757 ret_val = nla_put_u8(vendor_event,
1758 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1759 sap_cfg->acs_cfg.vht_seg1_center_ch);
1760 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001761 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001762 kfree_skb(vendor_event);
1763 return;
1764 }
1765
1766 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1767 ch_width = 80;
1768 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1769 ch_width = 40;
1770 else
1771 ch_width = 20;
1772
1773 ret_val = nla_put_u16(vendor_event,
1774 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1775 ch_width);
1776 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001777 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001778 kfree_skb(vendor_event);
1779 return;
1780 }
1781 if (sap_cfg->acs_cfg.pri_ch > 14)
1782 ret_val = nla_put_u8(vendor_event,
1783 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1784 QCA_ACS_MODE_IEEE80211A);
1785 else
1786 ret_val = nla_put_u8(vendor_event,
1787 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1788 QCA_ACS_MODE_IEEE80211G);
1789
1790 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001791 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001792 kfree_skb(vendor_event);
1793 return;
1794 }
1795
Jeff Johnson46b40792016-06-29 14:03:14 -07001796 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 -08001797 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1798 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1799 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1800
1801 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1802 /* ***Note*** As already mentioned Completion variable usage is not
1803 * allowed here since ACS scan operation may take max 2.2 sec.
1804 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1805 * operation.
1806 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1807 * when Primary AP ACS is complete and secondary AP ACS is started here
1808 * immediately, Primary AP start_bss may come inbetween ACS operation
1809 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1810 * delay. This path and below constraint will be removed on sessionizing
1811 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1812 * As per design constraint user space control application must take
1813 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1814 * this code path. Sec AP hostapd should be started after Primary AP
1815 * start beaconing which can be confirmed by getchannel iwpriv command
1816 */
1817
1818 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1819 if (con_sap_adapter &&
1820 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001821 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1822 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001823 /* Lets give 500ms for OBSS + START_BSS to complete */
1824 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1825 msecs_to_jiffies(500));
1826 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1827 }
1828
1829 return;
1830}
1831
1832static int
1833__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1834 struct wireless_dev *wdev,
1835 const void *data,
1836 int data_len)
1837{
1838 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1839 struct sk_buff *skb = NULL;
1840 uint32_t fset = 0;
1841 int ret;
1842
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001843 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301844
Anurag Chouhan6d760662016-02-20 16:05:43 +05301845 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001846 hdd_err("Command not allowed in FTM mode");
1847 return -EPERM;
1848 }
1849
1850 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301851 if (ret)
1852 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001853
1854 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001855 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001856 fset |= WIFI_FEATURE_INFRA;
1857 }
1858 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001859 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001860 fset |= WIFI_FEATURE_INFRA_5G;
1861 }
1862#ifdef WLAN_FEATURE_P2P
1863 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1864 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001865 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001866 fset |= WIFI_FEATURE_P2P;
1867 }
1868#endif
1869 fset |= WIFI_FEATURE_SOFT_AP;
1870
1871 /* HOTSPOT is a supplicant feature, enable it by default */
1872 fset |= WIFI_FEATURE_HOTSPOT;
1873
1874#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301875 if (pHddCtx->config->extscan_enabled &&
1876 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001877 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001878 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1879 }
1880#endif
1881 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001882 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001883 fset |= WIFI_FEATURE_NAN;
1884 }
1885 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001886 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001887 fset |= WIFI_FEATURE_D2D_RTT;
1888 fset |= WIFI_FEATURE_D2AP_RTT;
1889 }
1890#ifdef FEATURE_WLAN_SCAN_PNO
1891 if (pHddCtx->config->configPNOScanSupport &&
1892 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001893 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894 fset |= WIFI_FEATURE_PNO;
1895 }
1896#endif
1897 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1898#ifdef FEATURE_WLAN_TDLS
1899 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1900 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001901 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001902 fset |= WIFI_FEATURE_TDLS;
1903 }
1904 if (sme_is_feature_supported_by_fw(TDLS) &&
1905 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1906 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001907 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1909 }
1910#endif
1911#ifdef WLAN_AP_STA_CONCURRENCY
1912 fset |= WIFI_FEATURE_AP_STA;
1913#endif
1914 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07001915 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001916
1917 if (hdd_link_layer_stats_supported())
1918 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1919
1920 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1921 NLMSG_HDRLEN);
1922 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001923 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001924 return -EINVAL;
1925 }
Jeff Johnson020db452016-06-29 14:37:26 -07001926 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001928 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001929 goto nla_put_failure;
1930 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301931 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301932 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933nla_put_failure:
1934 kfree_skb(skb);
1935 return -EINVAL;
1936}
1937
1938/**
1939 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1940 * @wiphy: pointer to wireless wiphy structure.
1941 * @wdev: pointer to wireless_dev structure.
1942 * @data: Pointer to the data to be passed via vendor interface
1943 * @data_len:Length of the data to be passed
1944 *
1945 * Return: Return the Success or Failure code.
1946 */
1947static int
1948wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1949 struct wireless_dev *wdev,
1950 const void *data, int data_len)
1951{
1952 int ret = 0;
1953
1954 cds_ssr_protect(__func__);
1955 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1956 data, data_len);
1957 cds_ssr_unprotect(__func__);
1958
1959 return ret;
1960}
1961
1962/**
1963 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1964 * @wiphy: pointer to wireless wiphy structure.
1965 * @wdev: pointer to wireless_dev structure.
1966 * @data: Pointer to the data to be passed via vendor interface
1967 * @data_len:Length of the data to be passed
1968 *
1969 * Set the MAC address that is to be used for scanning.
1970 *
1971 * Return: Return the Success or Failure code.
1972 */
1973static int
1974__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1975 struct wireless_dev *wdev,
1976 const void *data,
1977 int data_len)
1978{
1979 tpSirScanMacOui pReqMsg = NULL;
1980 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1981 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301982 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983 int ret;
1984
Jeff Johnson1f61b612016-02-12 16:28:33 -08001985 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001986
Anurag Chouhan6d760662016-02-20 16:05:43 +05301987 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988 hdd_err("Command not allowed in FTM mode");
1989 return -EPERM;
1990 }
1991
1992 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301993 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001994 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001995
1996 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001997 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001998 return -ENOTSUPP;
1999 }
2000
2001 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2002 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002003 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002004 return -EINVAL;
2005 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302006 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002007 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002008 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002009 return -ENOMEM;
2010 }
2011 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002012 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002013 goto fail;
2014 }
2015 nla_memcpy(&pReqMsg->oui[0],
2016 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2017 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002018 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002019 pReqMsg->oui[1], pReqMsg->oui[2]);
2020 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302021 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002022 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002023 goto fail;
2024 }
2025 return 0;
2026fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302027 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028 return -EINVAL;
2029}
2030
2031/**
2032 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2033 * @wiphy: pointer to wireless wiphy structure.
2034 * @wdev: pointer to wireless_dev structure.
2035 * @data: Pointer to the data to be passed via vendor interface
2036 * @data_len:Length of the data to be passed
2037 *
2038 * Set the MAC address that is to be used for scanning. This is an
2039 * SSR-protecting wrapper function.
2040 *
2041 * Return: Return the Success or Failure code.
2042 */
2043static int
2044wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2045 struct wireless_dev *wdev,
2046 const void *data,
2047 int data_len)
2048{
2049 int ret;
2050
2051 cds_ssr_protect(__func__);
2052 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2053 data, data_len);
2054 cds_ssr_unprotect(__func__);
2055
2056 return ret;
2057}
2058
2059/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302060 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2061 * @wiphy: pointer phy adapter
2062 * @wdev: pointer to wireless device structure
2063 * @data: pointer to data buffer
2064 * @data_len: length of data
2065 *
2066 * This routine will give concurrency matrix
2067 *
2068 * Return: int status code
2069 */
2070static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2071 struct wireless_dev *wdev,
2072 const void *data,
2073 int data_len)
2074{
2075 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2076 uint8_t i, feature_sets, max_feature_sets;
2077 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2078 struct sk_buff *reply_skb;
2079 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2080 int ret;
2081
2082 ENTER_DEV(wdev->netdev);
2083
2084 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2085 hdd_err("Command not allowed in FTM mode");
2086 return -EPERM;
2087 }
2088
2089 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302090 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302091 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302092
2093 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2094 data, data_len, NULL)) {
2095 hdd_err("Invalid ATTR");
2096 return -EINVAL;
2097 }
2098
2099 /* Parse and fetch max feature set */
2100 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2101 hdd_err("Attr max feature set size failed");
2102 return -EINVAL;
2103 }
2104 max_feature_sets = nla_get_u32(tb[
2105 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2106 hdd_info("Max feature set size: %d", max_feature_sets);
2107
2108 /* Fill feature combination matrix */
2109 feature_sets = 0;
2110 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002111 WIFI_FEATURE_P2P;
2112 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2113 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302114 /* Add more feature combinations here */
2115
2116 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002117 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302118 hdd_info("Feature set matrix");
2119 for (i = 0; i < feature_sets; i++)
2120 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2121
2122 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2123 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2124 if (!reply_skb) {
2125 hdd_err("Feature set matrix: buffer alloc fail");
2126 return -ENOMEM;
2127 }
2128
2129 if (nla_put_u32(reply_skb,
2130 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2131 feature_sets) ||
2132 nla_put(reply_skb,
2133 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2134 sizeof(u32) * feature_sets,
2135 feature_set_matrix)) {
2136 hdd_err("nla put fail");
2137 kfree_skb(reply_skb);
2138 return -EINVAL;
2139 }
2140 return cfg80211_vendor_cmd_reply(reply_skb);
2141}
2142
2143/**
2144 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2145 * @wiphy: pointer to wireless wiphy structure.
2146 * @wdev: pointer to wireless_dev structure.
2147 * @data: Pointer to the data to be passed via vendor interface
2148 * @data_len:Length of the data to be passed
2149 *
2150 * Retrieves the concurrency feature set matrix
2151 *
2152 * Return: 0 on success, negative errno on failure
2153 */
2154static int
2155wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2156 struct wireless_dev *wdev,
2157 const void *data,
2158 int data_len)
2159{
2160 int ret;
2161
2162 cds_ssr_protect(__func__);
2163 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2164 data, data_len);
2165 cds_ssr_unprotect(__func__);
2166
2167 return ret;
2168}
2169
2170/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2172 * @feature_flags: pointer to the byte array of features.
2173 * @feature: Feature to be turned ON in the byte array.
2174 *
2175 * Return: None
2176 *
2177 * This is called to turn ON or SET the feature flag for the requested feature.
2178 **/
2179#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002180static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2181 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002182{
2183 uint32_t index;
2184 uint8_t bit_mask;
2185
2186 index = feature / NUM_BITS_IN_BYTE;
2187 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2188 feature_flags[index] |= bit_mask;
2189}
2190
2191/**
2192 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2193 * @wiphy: pointer to wireless wiphy structure.
2194 * @wdev: pointer to wireless_dev structure.
2195 * @data: Pointer to the data to be passed via vendor interface
2196 * @data_len:Length of the data to be passed
2197 *
2198 * This is called when wlan driver needs to send supported feature set to
2199 * supplicant upon a request/query from the supplicant.
2200 *
2201 * Return: Return the Success or Failure code.
2202 **/
2203#define MAX_CONCURRENT_CHAN_ON_24G 2
2204#define MAX_CONCURRENT_CHAN_ON_5G 2
2205static int
2206__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2207 struct wireless_dev *wdev,
2208 const void *data, int data_len)
2209{
2210 struct sk_buff *skb = NULL;
2211 uint32_t dbs_capability = 0;
2212 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302213 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002214 int ret_val;
2215
2216 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2217 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2218
Jeff Johnson1f61b612016-02-12 16:28:33 -08002219 ENTER_DEV(wdev->netdev);
2220
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002221 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2222 if (ret_val)
2223 return ret_val;
2224
Anurag Chouhan6d760662016-02-20 16:05:43 +05302225 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002226 hdd_err("Command not allowed in FTM mode");
2227 return -EPERM;
2228 }
2229
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002230 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002231 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002232 wlan_hdd_cfg80211_set_feature(feature_flags,
2233 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2234 }
2235
2236 wlan_hdd_cfg80211_set_feature(feature_flags,
2237 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2238 if (wma_is_scan_simultaneous_capable())
2239 wlan_hdd_cfg80211_set_feature(feature_flags,
2240 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002241
2242 if (wma_is_p2p_lo_capable())
2243 wlan_hdd_cfg80211_set_feature(feature_flags,
2244 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2245
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002246 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2247 NLMSG_HDRLEN);
2248
2249 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002250 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002251 return -ENOMEM;
2252 }
2253
2254 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2255 sizeof(feature_flags), feature_flags))
2256 goto nla_put_failure;
2257
2258 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302259 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002260 if (one_by_one_dbs)
2261 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2262
2263 if (two_by_two_dbs)
2264 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2265
2266 if (!one_by_one_dbs && !two_by_two_dbs)
2267 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2268 } else {
2269 hdd_err("wma_get_dbs_hw_mode failed");
2270 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2271 }
2272
2273 hdd_info("dbs_capability is %d", dbs_capability);
2274
2275 if (nla_put_u32(skb,
2276 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2277 MAX_CONCURRENT_CHAN_ON_24G))
2278 goto nla_put_failure;
2279
2280 if (nla_put_u32(skb,
2281 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2282 MAX_CONCURRENT_CHAN_ON_5G))
2283 goto nla_put_failure;
2284
2285 return cfg80211_vendor_cmd_reply(skb);
2286
2287nla_put_failure:
2288 kfree_skb(skb);
2289 return -EINVAL;
2290}
2291
2292/**
2293 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2294 * @wiphy: pointer to wireless wiphy structure.
2295 * @wdev: pointer to wireless_dev structure.
2296 * @data: Pointer to the data to be passed via vendor interface
2297 * @data_len:Length of the data to be passed
2298 *
2299 * This is called when wlan driver needs to send supported feature set to
2300 * supplicant upon a request/query from the supplicant.
2301 *
2302 * Return: Return the Success or Failure code.
2303 */
2304static int
2305wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2306 struct wireless_dev *wdev,
2307 const void *data, int data_len)
2308{
2309 int ret;
2310
2311 cds_ssr_protect(__func__);
2312 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2313 data, data_len);
2314 cds_ssr_unprotect(__func__);
2315
2316 return ret;
2317}
2318
2319
2320/**
2321 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2322 * @wiphy: The wiphy structure
2323 * @wdev: The wireless device
2324 * @data: Data passed by framework
2325 * @data_len: Parameters to be configured passed as data
2326 *
2327 * The roaming related parameters are configured by the framework
2328 * using this interface.
2329 *
2330 * Return: Return either success or failure code.
2331 */
2332static int
2333__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2334 struct wireless_dev *wdev, const void *data, int data_len)
2335{
2336 struct net_device *dev = wdev->netdev;
2337 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2338 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2339 uint8_t session_id;
2340 struct roam_ext_params roam_params;
2341 uint32_t cmd_type, req_id;
2342 struct nlattr *curr_attr;
2343 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2344 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2345 int rem, i;
2346 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002347 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002348 int ret;
2349
Jeff Johnson1f61b612016-02-12 16:28:33 -08002350 ENTER_DEV(dev);
2351
Anurag Chouhan6d760662016-02-20 16:05:43 +05302352 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002353 hdd_err("Command not allowed in FTM mode");
2354 return -EPERM;
2355 }
2356
2357 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302358 if (ret)
2359 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002360
2361 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2362 data, data_len,
2363 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002364 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002365 return -EINVAL;
2366 }
2367 /* Parse and fetch Command Type*/
2368 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002369 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002370 goto fail;
2371 }
2372 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302373 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002374 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2375 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002376 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002377 goto fail;
2378 }
2379 req_id = nla_get_u32(
2380 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002381 hdd_debug("Req Id (%d)", req_id);
2382 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383 switch (cmd_type) {
2384 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2385 i = 0;
2386 nla_for_each_nested(curr_attr,
2387 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2388 rem) {
2389 if (nla_parse(tb2,
2390 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2391 nla_data(curr_attr), nla_len(curr_attr),
2392 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002393 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002394 goto fail;
2395 }
2396 /* Parse and Fetch allowed SSID list*/
2397 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002398 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002399 goto fail;
2400 }
2401 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2402 /*
2403 * Upper Layers include a null termination character.
2404 * Check for the actual permissible length of SSID and
2405 * also ensure not to copy the NULL termination
2406 * character to the driver buffer.
2407 */
2408 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2409 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2410 nla_memcpy(
2411 roam_params.ssid_allowed_list[i].ssId,
2412 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2413 buf_len - 1);
2414 roam_params.ssid_allowed_list[i].length =
2415 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002416 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002417 roam_params.ssid_allowed_list[i].length,
2418 roam_params.ssid_allowed_list[i].ssId,
2419 roam_params.ssid_allowed_list[i].length);
2420 i++;
2421 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002422 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002423 }
2424 }
2425 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002426 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002427 roam_params.num_ssid_allowed_list);
2428 sme_update_roam_params(pHddCtx->hHal, session_id,
2429 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2430 break;
2431 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2432 /* Parse and fetch 5G Boost Threshold */
2433 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002434 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435 goto fail;
2436 }
2437 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2438 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002439 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440 roam_params.raise_rssi_thresh_5g);
2441 /* Parse and fetch 5G Penalty Threshold */
2442 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002443 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002444 goto fail;
2445 }
2446 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2447 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002448 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449 roam_params.drop_rssi_thresh_5g);
2450 /* Parse and fetch 5G Boost Factor */
2451 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002452 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453 goto fail;
2454 }
2455 roam_params.raise_factor_5g = nla_get_u32(
2456 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002457 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458 roam_params.raise_factor_5g);
2459 /* Parse and fetch 5G Penalty factor */
2460 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002461 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002462 goto fail;
2463 }
2464 roam_params.drop_factor_5g = nla_get_u32(
2465 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002466 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002467 roam_params.drop_factor_5g);
2468 /* Parse and fetch 5G Max Boost */
2469 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002470 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002471 goto fail;
2472 }
2473 roam_params.max_raise_rssi_5g = nla_get_u32(
2474 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002475 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476 roam_params.max_raise_rssi_5g);
2477 /* Parse and fetch Rssi Diff */
2478 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002479 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002480 goto fail;
2481 }
2482 roam_params.rssi_diff = nla_get_s32(
2483 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002484 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002485 roam_params.rssi_diff);
2486 /* Parse and fetch Alert Rssi Threshold */
2487 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002488 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489 goto fail;
2490 }
2491 roam_params.alert_rssi_threshold = nla_get_u32(
2492 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002493 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002494 roam_params.alert_rssi_threshold);
2495 sme_update_roam_params(pHddCtx->hHal, session_id,
2496 roam_params,
2497 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2498 break;
2499 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2500 /* Parse and fetch Activate Good Rssi Roam */
2501 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002502 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002503 goto fail;
2504 }
2505 roam_params.good_rssi_roam = nla_get_s32(
2506 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002507 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002508 roam_params.good_rssi_roam);
2509 sme_update_roam_params(pHddCtx->hHal, session_id,
2510 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2511 break;
2512 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2513 /* Parse and fetch number of preferred BSSID */
2514 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002515 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002516 goto fail;
2517 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002518 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002519 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002520 if (count > MAX_BSSID_FAVORED) {
2521 hdd_err("Preferred BSSID count %u exceeds max %u",
2522 count, MAX_BSSID_FAVORED);
2523 goto fail;
2524 }
2525 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 i = 0;
2527 nla_for_each_nested(curr_attr,
2528 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2529 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002530
2531 if (i == count) {
2532 hdd_warn("Ignoring excess Preferred BSSID");
2533 break;
2534 }
2535
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536 if (nla_parse(tb2,
2537 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2538 nla_data(curr_attr), nla_len(curr_attr),
2539 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002540 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002541 goto fail;
2542 }
2543 /* Parse and fetch MAC address */
2544 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002545 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002546 goto fail;
2547 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002548 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302550 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002551 hdd_debug(MAC_ADDRESS_STR,
2552 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553 /* Parse and fetch preference factor*/
2554 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002555 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002556 goto fail;
2557 }
2558 roam_params.bssid_favored_factor[i] = nla_get_u32(
2559 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002560 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002561 roam_params.bssid_favored_factor[i]);
2562 i++;
2563 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002564 if (i < count)
2565 hdd_warn("Num Preferred BSSID %u less than expected %u",
2566 i, count);
2567 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002568 sme_update_roam_params(pHddCtx->hHal, session_id,
2569 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2570 break;
2571 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2572 /* Parse and fetch number of blacklist BSSID */
2573 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002574 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002575 goto fail;
2576 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002577 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002578 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002579 if (count > MAX_BSSID_AVOID_LIST) {
2580 hdd_err("Blacklist BSSID count %u exceeds max %u",
2581 count, MAX_BSSID_AVOID_LIST);
2582 goto fail;
2583 }
2584 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002585 i = 0;
2586 nla_for_each_nested(curr_attr,
2587 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2588 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002589
2590 if (i == count) {
2591 hdd_warn("Ignoring excess Blacklist BSSID");
2592 break;
2593 }
2594
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595 if (nla_parse(tb2,
2596 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2597 nla_data(curr_attr), nla_len(curr_attr),
2598 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002599 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600 goto fail;
2601 }
2602 /* Parse and fetch MAC address */
2603 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002604 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002605 goto fail;
2606 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002607 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002608 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302609 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002610 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002611 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002612 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002613 i++;
2614 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002615 if (i < count)
2616 hdd_warn("Num Blacklist BSSID %u less than expected %u",
2617 i, count);
2618 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002619 sme_update_roam_params(pHddCtx->hHal, session_id,
2620 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2621 break;
2622 }
2623 return 0;
2624fail:
2625 return -EINVAL;
2626}
2627
2628/**
2629 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2630 * @wiphy: pointer to wireless wiphy structure.
2631 * @wdev: pointer to wireless_dev structure.
2632 * @data: Pointer to the data to be passed via vendor interface
2633 * @data_len:Length of the data to be passed
2634 *
2635 * Return: Return the Success or Failure code.
2636 */
2637static int
2638wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2639 struct wireless_dev *wdev,
2640 const void *data,
2641 int data_len)
2642{
2643 int ret;
2644
2645 cds_ssr_protect(__func__);
2646 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2647 data, data_len);
2648 cds_ssr_unprotect(__func__);
2649
2650 return ret;
2651}
2652
2653static const struct nla_policy
2654wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2655 +1] = {
2656 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2657};
2658
2659/**
2660 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2661 * @hdd_ctx: HDD context
2662 * @device_mode: device mode
2663 * Return: bool
2664 */
2665static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002666 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002667{
2668 hdd_adapter_t *adapter;
2669 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2670 hdd_ap_ctx_t *ap_ctx;
2671 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302672 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302674 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675 &adapter_node);
2676
2677 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302678 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002679 adapter = adapter_node->pAdapter;
2680
2681 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002682 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002683 ap_ctx =
2684 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2685
2686 /*
2687 * if there is SAP already running on DFS channel,
2688 * do not disable scan on dfs channels. Note that
2689 * with SAP on DFS, there cannot be conurrency on
2690 * single radio. But then we can have multiple
2691 * radios !!
2692 */
2693 if (CHANNEL_STATE_DFS ==
2694 cds_get_channel_state(
2695 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002696 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002697 return true;
2698 }
2699 }
2700
2701 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002702 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703 sta_ctx =
2704 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2705
2706 /*
2707 * if STA is already connected on DFS channel,
2708 * do not disable scan on dfs channels
2709 */
2710 if (hdd_conn_is_connected(sta_ctx) &&
2711 (CHANNEL_STATE_DFS ==
2712 cds_get_channel_state(
2713 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002714 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002715 return true;
2716 }
2717 }
2718
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302719 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002720 adapter_node,
2721 &next);
2722 adapter_node = next;
2723 }
2724
2725 return false;
2726}
2727
2728/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002729 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2730 * @hdd_ctx: HDD context within host driver
2731 * @adapter: Adapter pointer
2732 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2733 *
2734 * Loops through devices to see who is operating on DFS channels
2735 * and then disables/enables DFS channels by calling SME API.
2736 * Fails the disable request if any device is active on a DFS channel.
2737 *
2738 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002739 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002740
2741int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2742 hdd_adapter_t *adapter,
2743 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002744{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002745 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302746 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002747 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002748
2749 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2750 if (no_dfs_flag) {
2751 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002752 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002753
2754 if (true == status)
2755 return -EOPNOTSUPP;
2756
2757 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002758 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002759
2760 if (true == status)
2761 return -EOPNOTSUPP;
2762 }
2763
2764 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2765
2766 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2767
2768 /*
2769 * call the SME API to tunnel down the new channel list
2770 * to the firmware
2771 */
2772 status = sme_handle_dfs_chan_scan(
2773 h_hal, hdd_ctx->config->enableDFSChnlScan);
2774
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302775 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776 ret_val = 0;
2777
2778 /*
2779 * Clear the SME scan cache also. Note that the
2780 * clearing of scan results is independent of session;
2781 * so no need to iterate over
2782 * all sessions
2783 */
2784 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302785 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002786 ret_val = -EPERM;
2787 }
2788
2789 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002790 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791 ret_val = 0;
2792 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002793 return ret_val;
2794}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002795
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002796/**
2797 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2798 * @wiphy: corestack handler
2799 * @wdev: wireless device
2800 * @data: data
2801 * @data_len: data length
2802 * Return: success(0) or reason code for failure
2803 */
2804static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2805 struct wireless_dev *wdev,
2806 const void *data,
2807 int data_len)
2808{
2809 struct net_device *dev = wdev->netdev;
2810 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2811 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2812 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2813 int ret_val;
2814 uint32_t no_dfs_flag = 0;
2815
Jeff Johnson1f61b612016-02-12 16:28:33 -08002816 ENTER_DEV(dev);
2817
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002818 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302819 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002820 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002821
2822 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2823 data, data_len,
2824 wlan_hdd_set_no_dfs_flag_config_policy)) {
2825 hdd_err("invalid attr");
2826 return -EINVAL;
2827 }
2828
2829 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2830 hdd_err("attr dfs flag failed");
2831 return -EINVAL;
2832 }
2833
2834 no_dfs_flag = nla_get_u32(
2835 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2836
Jeff Johnson020db452016-06-29 14:37:26 -07002837 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002838
2839 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002840 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002841 return -EINVAL;
2842 }
2843
2844 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2845 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002846 return ret_val;
2847}
2848
2849/**
2850 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2851 *
2852 * @wiphy: wiphy device pointer
2853 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002854 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002855 * @data_len: Buffer length
2856 *
2857 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2858 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2859 *
2860 * Return: EOK or other error codes.
2861 */
2862
2863static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2864 struct wireless_dev *wdev,
2865 const void *data,
2866 int data_len)
2867{
2868 int ret;
2869
2870 cds_ssr_protect(__func__);
2871 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2872 data, data_len);
2873 cds_ssr_unprotect(__func__);
2874
2875 return ret;
2876}
2877
Manikandan Mohan80dea792016-04-28 16:36:48 -07002878static const struct nla_policy
2879wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2880 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2881};
2882
2883/**
2884 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2885 * @wiphy: wiphy device pointer
2886 * @wdev: wireless device pointer
2887 * @data: Vendor command data buffer
2888 * @data_len: Buffer length
2889 *
2890 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2891 * setup WISA Mode features.
2892 *
2893 * Return: Success(0) or reason code for failure
2894 */
2895static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2896 struct wireless_dev *wdev, const void *data, int data_len)
2897{
2898 struct net_device *dev = wdev->netdev;
2899 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2900 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2901 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2902 struct sir_wisa_params wisa;
2903 int ret_val;
2904 QDF_STATUS status;
2905 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07002906 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2907 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002908
2909 ENTER_DEV(dev);
2910 ret_val = wlan_hdd_validate_context(hdd_ctx);
2911 if (ret_val)
2912 goto err;
2913
2914 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2915 hdd_err("Command not allowed in FTM mode");
2916 return -EPERM;
2917 }
2918
2919 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2920 wlan_hdd_wisa_cmd_policy)) {
2921 hdd_err("Invalid WISA cmd attributes");
2922 ret_val = -EINVAL;
2923 goto err;
2924 }
2925 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2926 hdd_err("Invalid WISA mode");
2927 ret_val = -EINVAL;
2928 goto err;
2929 }
2930
2931 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2932 hdd_info("WISA Mode: %d", wisa_mode);
2933 wisa.mode = wisa_mode;
2934 wisa.vdev_id = adapter->sessionId;
2935 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002936 if (!QDF_IS_STATUS_SUCCESS(status)) {
2937 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002938 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002939 }
2940 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07002941 cdp_set_wisa_mode(soc,
2942 cdp_get_vdev_from_vdev_id(soc, pdev,
2943 adapter->sessionId),
2944 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002945err:
2946 EXIT();
2947 return ret_val;
2948}
2949
2950/**
2951 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2952 * @wiphy: corestack handler
2953 * @wdev: wireless device
2954 * @data: data
2955 * @data_len: data length
2956 *
2957 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2958 * setup WISA mode features.
2959 *
2960 * Return: Success(0) or reason code for failure
2961 */
2962static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2963 struct wireless_dev *wdev,
2964 const void *data,
2965 int data_len)
2966{
2967 int ret;
2968
2969 cds_ssr_protect(__func__);
2970 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2971 cds_ssr_unprotect(__func__);
2972
2973 return ret;
2974}
2975
Anurag Chouhan96919482016-07-13 16:36:57 +05302976/*
2977 * define short names for the global vendor params
2978 * used by __wlan_hdd_cfg80211_get_station_cmd()
2979 */
2980#define STATION_INVALID \
2981 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2982#define STATION_INFO \
2983 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2984#define STATION_ASSOC_FAIL_REASON \
2985 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2986#define STATION_MAX \
2987 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2988
2989static const struct nla_policy
2990hdd_get_station_policy[STATION_MAX + 1] = {
2991 [STATION_INFO] = {.type = NLA_FLAG},
2992 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2993};
2994
2995/**
2996 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2997 * @hdd_ctx: HDD context within host driver
2998 * @wdev: wireless device
2999 *
3000 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3001 * Validate cmd attributes and send the station info to upper layers.
3002 *
3003 * Return: Success(0) or reason code for failure
3004 */
3005static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3006 hdd_adapter_t *adapter)
3007{
3008 struct sk_buff *skb = NULL;
3009 uint32_t nl_buf_len;
3010 hdd_station_ctx_t *hdd_sta_ctx;
3011
3012 nl_buf_len = NLMSG_HDRLEN;
3013 nl_buf_len += sizeof(uint32_t);
3014 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3015
3016 if (!skb) {
3017 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3018 return -ENOMEM;
3019 }
3020
3021 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3022
3023 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3024 hdd_sta_ctx->conn_info.assoc_status_code)) {
3025 hdd_err("put fail");
3026 goto fail;
3027 }
3028 return cfg80211_vendor_cmd_reply(skb);
3029fail:
3030 if (skb)
3031 kfree_skb(skb);
3032 return -EINVAL;
3033}
3034
3035/**
3036 * hdd_map_auth_type() - transform auth type specific to
3037 * vendor command
3038 * @auth_type: csr auth type
3039 *
3040 * Return: Success(0) or reason code for failure
3041 */
3042static int hdd_convert_auth_type(uint32_t auth_type)
3043{
3044 uint32_t ret_val;
3045
3046 switch (auth_type) {
3047 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3048 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3049 break;
3050 case eCSR_AUTH_TYPE_SHARED_KEY:
3051 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3052 break;
3053 case eCSR_AUTH_TYPE_WPA:
3054 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3055 break;
3056 case eCSR_AUTH_TYPE_WPA_PSK:
3057 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3058 break;
3059 case eCSR_AUTH_TYPE_AUTOSWITCH:
3060 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3061 break;
3062 case eCSR_AUTH_TYPE_WPA_NONE:
3063 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3064 break;
3065 case eCSR_AUTH_TYPE_RSN:
3066 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3067 break;
3068 case eCSR_AUTH_TYPE_RSN_PSK:
3069 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3070 break;
3071 case eCSR_AUTH_TYPE_FT_RSN:
3072 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3073 break;
3074 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3075 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3076 break;
3077 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3078 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3079 break;
3080 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3081 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3082 break;
3083 case eCSR_AUTH_TYPE_CCKM_WPA:
3084 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3085 break;
3086 case eCSR_AUTH_TYPE_CCKM_RSN:
3087 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3088 break;
3089 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3090 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3091 break;
3092 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3093 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3094 break;
3095 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3096 case eCSR_AUTH_TYPE_FAILED:
3097 case eCSR_AUTH_TYPE_NONE:
3098 default:
3099 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3100 break;
3101 }
3102 return ret_val;
3103}
3104
3105/**
3106 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3107 * vendor command
3108 * @dot11mode: dot11mode
3109 *
3110 * Return: Success(0) or reason code for failure
3111 */
3112static int hdd_convert_dot11mode(uint32_t dot11mode)
3113{
3114 uint32_t ret_val;
3115
3116 switch (dot11mode) {
3117 case eCSR_CFG_DOT11_MODE_11A:
3118 ret_val = QCA_WLAN_802_11_MODE_11A;
3119 break;
3120 case eCSR_CFG_DOT11_MODE_11B:
3121 ret_val = QCA_WLAN_802_11_MODE_11B;
3122 break;
3123 case eCSR_CFG_DOT11_MODE_11G:
3124 ret_val = QCA_WLAN_802_11_MODE_11G;
3125 break;
3126 case eCSR_CFG_DOT11_MODE_11N:
3127 ret_val = QCA_WLAN_802_11_MODE_11N;
3128 break;
3129 case eCSR_CFG_DOT11_MODE_11AC:
3130 ret_val = QCA_WLAN_802_11_MODE_11AC;
3131 break;
3132 case eCSR_CFG_DOT11_MODE_AUTO:
3133 case eCSR_CFG_DOT11_MODE_ABG:
3134 default:
3135 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3136 }
3137 return ret_val;
3138}
3139
3140/**
3141 * hdd_add_tx_bitrate() - add tx bitrate attribute
3142 * @skb: pointer to sk buff
3143 * @hdd_sta_ctx: pointer to hdd station context
3144 * @idx: attribute index
3145 *
3146 * Return: Success(0) or reason code for failure
3147 */
3148static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3149 hdd_station_ctx_t *hdd_sta_ctx,
3150 int idx)
3151{
3152 struct nlattr *nla_attr;
3153 uint32_t bitrate, bitrate_compat;
3154
3155 nla_attr = nla_nest_start(skb, idx);
3156 if (!nla_attr)
3157 goto fail;
3158 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3159 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3160
3161 /* report 16-bit bitrate only if we can */
3162 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3163 if (bitrate > 0 &&
3164 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3165 hdd_err("put fail");
3166 goto fail;
3167 }
3168 if (bitrate_compat > 0 &&
3169 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3170 hdd_err("put fail");
3171 goto fail;
3172 }
3173 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3174 hdd_sta_ctx->conn_info.txrate.nss)) {
3175 hdd_err("put fail");
3176 goto fail;
3177 }
3178 nla_nest_end(skb, nla_attr);
3179 return 0;
3180fail:
3181 return -EINVAL;
3182}
3183
3184/**
3185 * hdd_add_sta_info() - add station info attribute
3186 * @skb: pointer to sk buff
3187 * @hdd_sta_ctx: pointer to hdd station context
3188 * @idx: attribute index
3189 *
3190 * Return: Success(0) or reason code for failure
3191 */
3192static int32_t hdd_add_sta_info(struct sk_buff *skb,
3193 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3194{
3195 struct nlattr *nla_attr;
3196
3197 nla_attr = nla_nest_start(skb, idx);
3198 if (!nla_attr)
3199 goto fail;
3200 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3201 (hdd_sta_ctx->conn_info.signal + 100))) {
3202 hdd_err("put fail");
3203 goto fail;
3204 }
3205 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3206 goto fail;
3207 nla_nest_end(skb, nla_attr);
3208 return 0;
3209fail:
3210 return -EINVAL;
3211}
3212
3213/**
3214 * hdd_add_survey_info() - add survey info attribute
3215 * @skb: pointer to sk buff
3216 * @hdd_sta_ctx: pointer to hdd station context
3217 * @idx: attribute index
3218 *
3219 * Return: Success(0) or reason code for failure
3220 */
3221static int32_t hdd_add_survey_info(struct sk_buff *skb,
3222 hdd_station_ctx_t *hdd_sta_ctx,
3223 int idx)
3224{
3225 struct nlattr *nla_attr;
3226
3227 nla_attr = nla_nest_start(skb, idx);
3228 if (!nla_attr)
3229 goto fail;
3230 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3231 hdd_sta_ctx->conn_info.freq) ||
3232 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3233 (hdd_sta_ctx->conn_info.noise + 100))) {
3234 hdd_err("put fail");
3235 goto fail;
3236 }
3237 nla_nest_end(skb, nla_attr);
3238 return 0;
3239fail:
3240 return -EINVAL;
3241}
3242
3243/**
3244 * hdd_add_link_standard_info() - add link info attribute
3245 * @skb: pointer to sk buff
3246 * @hdd_sta_ctx: pointer to hdd station context
3247 * @idx: attribute index
3248 *
3249 * Return: Success(0) or reason code for failure
3250 */
3251static int32_t
3252hdd_add_link_standard_info(struct sk_buff *skb,
3253 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3254{
3255 struct nlattr *nla_attr;
3256
3257 nla_attr = nla_nest_start(skb, idx);
3258 if (!nla_attr)
3259 goto fail;
3260 if (nla_put(skb,
3261 NL80211_ATTR_SSID,
3262 hdd_sta_ctx->conn_info.SSID.SSID.length,
3263 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3264 hdd_err("put fail");
3265 goto fail;
3266 }
3267 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3268 goto fail;
3269 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3270 goto fail;
3271 nla_nest_end(skb, nla_attr);
3272 return 0;
3273fail:
3274 return -EINVAL;
3275}
3276
3277/**
3278 * hdd_add_ap_standard_info() - add ap info attribute
3279 * @skb: pointer to sk buff
3280 * @hdd_sta_ctx: pointer to hdd station context
3281 * @idx: attribute index
3282 *
3283 * Return: Success(0) or reason code for failure
3284 */
3285static int32_t
3286hdd_add_ap_standard_info(struct sk_buff *skb,
3287 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3288{
3289 struct nlattr *nla_attr;
3290
3291 nla_attr = nla_nest_start(skb, idx);
3292 if (!nla_attr)
3293 goto fail;
3294 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3295 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3296 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3297 &hdd_sta_ctx->conn_info.vht_caps)) {
3298 hdd_err("put fail");
3299 goto fail;
3300 }
3301 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3302 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3303 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3304 &hdd_sta_ctx->conn_info.ht_caps)) {
3305 hdd_err("put fail");
3306 goto fail;
3307 }
3308 nla_nest_end(skb, nla_attr);
3309 return 0;
3310fail:
3311 return -EINVAL;
3312}
3313
3314/**
3315 * hdd_get_station_info() - send BSS information to supplicant
3316 * @hdd_ctx: pointer to hdd context
3317 * @adapter: pointer to adapter
3318 *
3319 * Return: 0 if success else error status
3320 */
3321static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3322 hdd_adapter_t *adapter)
3323{
3324 struct sk_buff *skb = NULL;
3325 uint8_t *tmp_hs20 = NULL;
3326 uint32_t nl_buf_len;
3327 hdd_station_ctx_t *hdd_sta_ctx;
3328
3329 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3330
3331 nl_buf_len = NLMSG_HDRLEN;
3332 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3333 sizeof(hdd_sta_ctx->conn_info.freq) +
3334 sizeof(hdd_sta_ctx->conn_info.noise) +
3335 sizeof(hdd_sta_ctx->conn_info.signal) +
3336 (sizeof(uint32_t) * 2) +
3337 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3338 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3339 sizeof(hdd_sta_ctx->conn_info.authType) +
3340 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3341 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3342 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3343 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3344 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3345 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3346 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3347 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3348 1);
3349 }
3350 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3351 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3352 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3353 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3354
3355
3356 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3357 if (!skb) {
3358 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3359 return -ENOMEM;
3360 }
3361
3362 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3363 LINK_INFO_STANDARD_NL80211_ATTR)) {
3364 hdd_err("put fail");
3365 goto fail;
3366 }
3367 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3368 AP_INFO_STANDARD_NL80211_ATTR)) {
3369 hdd_err("put fail");
3370 goto fail;
3371 }
3372 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3373 hdd_sta_ctx->conn_info.roam_count) ||
3374 nla_put_u32(skb, INFO_AKM,
3375 hdd_convert_auth_type(
3376 hdd_sta_ctx->conn_info.authType)) ||
3377 nla_put_u32(skb, WLAN802_11_MODE,
3378 hdd_convert_dot11mode(
3379 hdd_sta_ctx->conn_info.dot11Mode))) {
3380 hdd_err("put fail");
3381 goto fail;
3382 }
3383 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3384 if (nla_put(skb, HT_OPERATION,
3385 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3386 &hdd_sta_ctx->conn_info.ht_operation)) {
3387 hdd_err("put fail");
3388 goto fail;
3389 }
3390 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3391 if (nla_put(skb, VHT_OPERATION,
3392 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3393 &hdd_sta_ctx->conn_info.vht_operation)) {
3394 hdd_err("put fail");
3395 goto fail;
3396 }
3397 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3398 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3399 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3400 tmp_hs20 + 1)) {
3401 hdd_err("put fail");
3402 goto fail;
3403 }
3404
3405 return cfg80211_vendor_cmd_reply(skb);
3406fail:
3407 if (skb)
3408 kfree_skb(skb);
3409 return -EINVAL;
3410}
3411
3412/**
3413 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3414 * @wiphy: corestack handler
3415 * @wdev: wireless device
3416 * @data: data
3417 * @data_len: data length
3418 *
3419 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3420 * Validate cmd attributes and send the station info to upper layers.
3421 *
3422 * Return: Success(0) or reason code for failure
3423 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303424static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303425__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3426 struct wireless_dev *wdev,
3427 const void *data,
3428 int data_len)
3429{
3430 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3431 struct net_device *dev = wdev->netdev;
3432 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3433 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3434 int32_t status;
3435
3436 ENTER_DEV(dev);
3437 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3438 hdd_err("Command not allowed in FTM mode");
3439 status = -EPERM;
3440 goto out;
3441 }
3442
3443 status = wlan_hdd_validate_context(hdd_ctx);
3444 if (0 != status)
3445 goto out;
3446
3447
3448 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3449 data, data_len, NULL);
3450 if (status) {
3451 hdd_err("Invalid ATTR");
3452 goto out;
3453 }
3454
3455 /* Parse and fetch Command Type*/
3456 if (tb[STATION_INFO]) {
3457 status = hdd_get_station_info(hdd_ctx, adapter);
3458 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3459 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3460 } else {
3461 hdd_err("get station info cmd type failed");
3462 status = -EINVAL;
3463 goto out;
3464 }
3465 EXIT();
3466out:
3467 return status;
3468}
3469
3470/**
3471 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3472 * @wiphy: corestack handler
3473 * @wdev: wireless device
3474 * @data: data
3475 * @data_len: data length
3476 *
3477 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3478 * Validate cmd attributes and send the station info to upper layers.
3479 *
3480 * Return: Success(0) or reason code for failure
3481 */
3482static int32_t
3483hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3484 struct wireless_dev *wdev,
3485 const void *data,
3486 int data_len)
3487{
3488 int ret;
3489
3490 cds_ssr_protect(__func__);
3491 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3492 cds_ssr_unprotect(__func__);
3493
3494 return ret;
3495}
3496
3497/*
3498 * undef short names defined for get station command
3499 * used by __wlan_hdd_cfg80211_get_station_cmd()
3500 */
3501#undef STATION_INVALID
3502#undef STATION_INFO
3503#undef STATION_ASSOC_FAIL_REASON
3504#undef STATION_MAX
3505
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003506#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3507/**
3508 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3509 * @wiphy: pointer to wireless wiphy structure.
3510 * @wdev: pointer to wireless_dev structure.
3511 * @data: Pointer to the Key data
3512 * @data_len:Length of the data passed
3513 *
3514 * This is called when wlan driver needs to save the keys received via
3515 * vendor specific command.
3516 *
3517 * Return: Return the Success or Failure code.
3518 */
3519static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3520 struct wireless_dev *wdev,
3521 const void *data, int data_len)
3522{
3523 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3524 struct net_device *dev = wdev->netdev;
3525 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3526 hdd_context_t *hdd_ctx_ptr;
3527 int status;
3528
Jeff Johnson1f61b612016-02-12 16:28:33 -08003529 ENTER_DEV(dev);
3530
Anurag Chouhan6d760662016-02-20 16:05:43 +05303531 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003532 hdd_err("Command not allowed in FTM mode");
3533 return -EPERM;
3534 }
3535
3536 if ((data == NULL) || (data_len == 0) ||
3537 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003538 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003539 return -EINVAL;
3540 }
3541
3542 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3543 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003544 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003545 return -EINVAL;
3546 }
3547
3548 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303549 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003550 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3552 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003553 true,
3554 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303555 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3556 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003557 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3558 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3559 return 0;
3560}
3561
3562/**
3563 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3564 * @wiphy: pointer to wireless wiphy structure.
3565 * @wdev: pointer to wireless_dev structure.
3566 * @data: Pointer to the Key data
3567 * @data_len:Length of the data passed
3568 *
3569 * This is called when wlan driver needs to save the keys received via
3570 * vendor specific command.
3571 *
3572 * Return: Return the Success or Failure code.
3573 */
3574static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3575 struct wireless_dev *wdev,
3576 const void *data, int data_len)
3577{
3578 int ret;
3579
3580 cds_ssr_protect(__func__);
3581 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3582 cds_ssr_unprotect(__func__);
3583
3584 return ret;
3585}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003586#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003587
3588static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3589 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3590 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3591 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003592 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003593};
3594
3595/**
3596 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3597 * @wiphy: pointer to wireless wiphy structure.
3598 * @wdev: pointer to wireless_dev structure.
3599 * @data: Pointer to the data to be passed via vendor interface
3600 * @data_len:Length of the data to be passed
3601 *
3602 * This is called when wlan driver needs to send wifi driver related info
3603 * (driver/fw version) to the user space application upon request.
3604 *
3605 * Return: Return the Success or Failure code.
3606 */
3607static int
3608__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3609 struct wireless_dev *wdev,
3610 const void *data, int data_len)
3611{
3612 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3613 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003614 tSirVersionString driver_version;
3615 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003616 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003617 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003618 struct sk_buff *reply_skb;
3619 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003620
Jeff Johnson1f61b612016-02-12 16:28:33 -08003621 ENTER_DEV(wdev->netdev);
3622
Anurag Chouhan6d760662016-02-20 16:05:43 +05303623 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003624 hdd_err("Command not allowed in FTM mode");
3625 return -EPERM;
3626 }
3627
3628 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303629 if (status)
3630 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003631
3632 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3633 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003634 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003635 return -EINVAL;
3636 }
3637
3638 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003639 hdd_err("Rcvd req for Driver version");
3640 strlcpy(driver_version, QWLAN_VERSIONSTR,
3641 sizeof(driver_version));
3642 skb_len += strlen(driver_version) + 1;
3643 count++;
3644 }
3645
3646 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3647 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003648 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3649 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003650 snprintf(firmware_version, sizeof(firmware_version),
3651 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3652 skb_len += strlen(firmware_version) + 1;
3653 count++;
3654 }
3655
3656 if (count == 0) {
3657 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003658 return -EINVAL;
3659 }
3660
Ryan Hsu7ac88852016-04-28 10:20:34 -07003661 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3662 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3663
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003664 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003665 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003666 return -ENOMEM;
3667 }
3668
Ryan Hsu7ac88852016-04-28 10:20:34 -07003669 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3670 if (nla_put_string(reply_skb,
3671 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3672 driver_version))
3673 goto error_nla_fail;
3674 }
3675
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05303676 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003677 if (nla_put_string(reply_skb,
3678 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3679 firmware_version))
3680 goto error_nla_fail;
3681 }
3682
3683 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3684 if (nla_put_u32(reply_skb,
3685 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3686 hdd_ctx->radio_index))
3687 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003688 }
3689
3690 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003691
3692error_nla_fail:
3693 hdd_err("nla put fail");
3694 kfree_skb(reply_skb);
3695 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003696}
3697
3698/**
3699 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3700 * @wiphy: pointer to wireless wiphy structure.
3701 * @wdev: pointer to wireless_dev structure.
3702 * @data: Pointer to the data to be passed via vendor interface
3703 * @data_len:Length of the data to be passed
3704 *
3705 * This is called when wlan driver needs to send wifi driver related info
3706 * (driver/fw version) to the user space application upon request.
3707 *
3708 * Return: Return the Success or Failure code.
3709 */
3710static int
3711wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3712 struct wireless_dev *wdev,
3713 const void *data, int data_len)
3714{
3715 int ret;
3716
3717 cds_ssr_protect(__func__);
3718 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3719 cds_ssr_unprotect(__func__);
3720
3721 return ret;
3722}
3723
3724/**
3725 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3726 * @wiphy: pointer to wireless wiphy structure.
3727 * @wdev: pointer to wireless_dev structure.
3728 * @data: Pointer to the data to be passed via vendor interface
3729 * @data_len:Length of the data to be passed
3730 *
3731 * This is called by userspace to know the supported logger features
3732 *
3733 * Return: Return the Success or Failure code.
3734 */
3735static int
3736__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3737 struct wireless_dev *wdev,
3738 const void *data, int data_len)
3739{
3740 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3741 int status;
3742 uint32_t features;
3743 struct sk_buff *reply_skb = NULL;
3744
Jeff Johnson1f61b612016-02-12 16:28:33 -08003745 ENTER_DEV(wdev->netdev);
3746
Anurag Chouhan6d760662016-02-20 16:05:43 +05303747 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003748 hdd_err("Command not allowed in FTM mode");
3749 return -EPERM;
3750 }
3751
3752 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303753 if (status)
3754 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003755
3756 features = 0;
3757
3758 if (hdd_is_memdump_supported())
3759 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3760 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3761 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3762 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3763
3764 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3765 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3766 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003767 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003768 return -ENOMEM;
3769 }
3770
Jeff Johnson020db452016-06-29 14:37:26 -07003771 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003772 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3773 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003774 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003775 kfree_skb(reply_skb);
3776 return -EINVAL;
3777 }
3778
3779 return cfg80211_vendor_cmd_reply(reply_skb);
3780}
3781
3782/**
3783 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3784 * @wiphy: pointer to wireless wiphy structure.
3785 * @wdev: pointer to wireless_dev structure.
3786 * @data: Pointer to the data to be passed via vendor interface
3787 * @data_len:Length of the data to be passed
3788 *
3789 * This is called by userspace to know the supported logger features
3790 *
3791 * Return: Return the Success or Failure code.
3792 */
3793static int
3794wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3795 struct wireless_dev *wdev,
3796 const void *data, int data_len)
3797{
3798 int ret;
3799
3800 cds_ssr_protect(__func__);
3801 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3802 data, data_len);
3803 cds_ssr_unprotect(__func__);
3804
3805 return ret;
3806}
3807
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003808#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003809/**
3810 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05303811 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003812 * @bssid: pointer to bssid of roamed AP.
3813 * @req_rsn_ie: Pointer to request RSN IE
3814 * @req_rsn_len: Length of the request RSN IE
3815 * @rsp_rsn_ie: Pointer to response RSN IE
3816 * @rsp_rsn_len: Length of the response RSN IE
3817 * @roam_info_ptr: Pointer to the roaming related information
3818 *
3819 * This is called when wlan driver needs to send the roaming and
3820 * authorization information after roaming.
3821 *
3822 * The information that would be sent is the request RSN IE, response
3823 * RSN IE and BSSID of the newly roamed AP.
3824 *
3825 * If the Authorized status is authenticated, then additional parameters
3826 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3827 * supplicant.
3828 *
3829 * The supplicant upon receiving this event would ignore the legacy
3830 * cfg80211_roamed call and use the entire information from this event.
3831 * The cfg80211_roamed should still co-exist since the kernel will
3832 * make use of the parameters even if the supplicant ignores it.
3833 *
3834 * Return: Return the Success or Failure code.
3835 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05303836int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003837 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3838 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3839{
Prakash Dhavali989127d2016-11-29 14:56:44 +05303840 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003841 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003842 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003843 ENTER();
3844
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303845 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003846 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003848 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003849 !roam_info_ptr->roamSynchInProgress)
3850 return 0;
3851
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003852 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05303853 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003854 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3855 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3856 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003857 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003858 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3859 GFP_KERNEL);
3860
3861 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003862 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003863 return -EINVAL;
3864 }
3865
3866 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3867 ETH_ALEN, bssid) ||
3868 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3869 req_rsn_len, req_rsn_ie) ||
3870 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3871 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003872 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003873 goto nla_put_failure;
3874 }
Jeff Johnson020db452016-06-29 14:37:26 -07003875 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003876 if (roam_info_ptr->synchAuthStatus ==
3877 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003878 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003879 if (nla_put_u8(skb,
3880 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3881 hdd_err("nla put fail");
3882 goto nla_put_failure;
3883 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003884 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3885 /* if FT or CCKM connection: dont send replay counter */
3886 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3887 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3888 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3889 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3890 nla_put(skb,
3891 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3892 SIR_REPLAY_CTR_LEN,
3893 roam_info_ptr->replay_ctr)) {
3894 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003895 hdd_err("failed to send replay counter.");
3896 goto nla_put_failure;
3897 }
3898 if (nla_put(skb,
3899 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3900 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3901 nla_put(skb,
3902 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3903 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3904 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003905 goto nla_put_failure;
3906 }
3907 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003908 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3910 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003911 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003912 goto nla_put_failure;
3913 }
3914 }
3915
Jeff Johnson020db452016-06-29 14:37:26 -07003916 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003917 roam_info_ptr->subnet_change_status);
3918
3919 /*
3920 * Add subnet change status if subnet has changed
3921 * 0 = unchanged
3922 * 1 = changed
3923 * 2 = unknown
3924 */
3925 if (roam_info_ptr->subnet_change_status) {
3926 if (nla_put_u8(skb,
3927 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3928 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003929 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003930 goto nla_put_failure;
3931 }
3932 }
3933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003934 cfg80211_vendor_event(skb, GFP_KERNEL);
3935 return 0;
3936
3937nla_put_failure:
3938 kfree_skb(skb);
3939 return -EINVAL;
3940}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003941#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003942
3943static const struct nla_policy
3944wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3945
3946 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3947 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3948 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303949 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303950 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3951 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003952 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
3953 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
3954 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
3955 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
3956 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05303957 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003958};
3959
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003960/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303961 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3962 *
3963 * @adapter: Pointer to HDD adapter
3964 * @ie_data: Pointer to Scan IEs buffer
3965 * @ie_len: Length of Scan IEs
3966 *
3967 * Return: 0 on success; error number otherwise
3968 */
3969static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3970 uint8_t *ie_data, uint8_t ie_len)
3971{
3972 hdd_scaninfo_t *scan_info = NULL;
3973 scan_info = &adapter->scan_info;
3974
3975 if (scan_info->default_scan_ies) {
3976 qdf_mem_free(scan_info->default_scan_ies);
3977 scan_info->default_scan_ies = NULL;
3978 }
3979
3980 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3981 if (!scan_info->default_scan_ies)
3982 return -ENOMEM;
3983
3984 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3985 scan_info->default_scan_ies_len = ie_len;
3986 return 0;
3987}
3988
3989/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003990 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3991 * vendor command
3992 *
3993 * @wiphy: wiphy device pointer
3994 * @wdev: wireless device pointer
3995 * @data: Vendor command data buffer
3996 * @data_len: Buffer length
3997 *
3998 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3999 *
4000 * Return: Error code.
4001 */
4002static int
4003__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4004 struct wireless_dev *wdev,
4005 const void *data,
4006 int data_len)
4007{
4008 struct net_device *dev = wdev->netdev;
4009 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4010 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4011 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4012 int ret_val = 0;
4013 u32 modulated_dtim;
4014 u16 stats_avg_factor;
4015 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304016 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004017 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004018 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304019 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304020 int attr_len;
4021 int access_policy = 0;
4022 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4023 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304024 uint16_t scan_ie_len = 0;
4025 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304026 struct sir_set_tx_rx_aggregation_size request;
4027 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004028 uint8_t retry, delay;
4029 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304030 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304031
Jeff Johnson1f61b612016-02-12 16:28:33 -08004032 ENTER_DEV(dev);
4033
Anurag Chouhan6d760662016-02-20 16:05:43 +05304034 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004035 hdd_err("Command not allowed in FTM mode");
4036 return -EPERM;
4037 }
4038
4039 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304040 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004041 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042
4043 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4044 data, data_len,
4045 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004046 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004047 return -EINVAL;
4048 }
4049
Krunal Sonie3531942016-04-12 17:43:53 -07004050 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4051 ftm_capab = nla_get_u32(tb[
4052 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4053 hdd_ctx->config->fine_time_meas_cap =
4054 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4055 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304056 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004057 hdd_ctx->config->fine_time_meas_cap);
4058 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4059 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4060 hdd_ctx->config->fine_time_meas_cap);
4061 }
4062
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004063 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4064 modulated_dtim = nla_get_u32(
4065 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4066
4067 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4068 adapter->sessionId,
4069 modulated_dtim);
4070
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304071 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004072 ret_val = -EPERM;
4073 }
4074
Kapil Gupta6213c012016-09-02 19:39:09 +05304075 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4076 qpower = nla_get_u8(
4077 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4078 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4079 ret_val = -EINVAL;
4080 }
4081
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004082 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4083 stats_avg_factor = nla_get_u16(
4084 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4085 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4086 adapter->sessionId,
4087 stats_avg_factor);
4088
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304089 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004090 ret_val = -EPERM;
4091 }
4092
4093
4094 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4095 guard_time = nla_get_u32(
4096 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4097 status = sme_configure_guard_time(hdd_ctx->hHal,
4098 adapter->sessionId,
4099 guard_time);
4100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304101 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004102 ret_val = -EPERM;
4103 }
4104
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304105 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4106 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4107 attr_len = nla_len(
4108 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4109 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4110 hdd_info("Invalid value. attr_len %d",
4111 attr_len);
4112 return -EINVAL;
4113 }
4114
4115 nla_memcpy(&vendor_ie,
4116 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4117 attr_len);
4118 vendor_ie_present = true;
4119 hdd_info("Access policy vendor ie present.attr_len %d",
4120 attr_len);
4121 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4122 &vendor_ie[0], attr_len);
4123 }
4124
4125 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4126 access_policy = (int) nla_get_u32(
4127 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4128 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4129 (access_policy >
4130 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4131 hdd_info("Invalid value. access_policy %d",
4132 access_policy);
4133 return -EINVAL;
4134 }
4135 access_policy_present = true;
4136 hdd_info("Access policy present. access_policy %d",
4137 access_policy);
4138 }
4139
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004140 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4141 retry = nla_get_u8(tb[
4142 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4143 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4144 CFG_NON_AGG_RETRY_MAX : retry;
4145 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4146 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4147 retry, PDEV_CMD);
4148 }
4149
4150 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4151 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4152 retry = retry > CFG_AGG_RETRY_MAX ?
4153 CFG_AGG_RETRY_MAX : retry;
4154
4155 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4156 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4157 CFG_AGG_RETRY_MIN : retry;
4158 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4159 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4160 retry, PDEV_CMD);
4161 }
4162
4163 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4164 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4165 retry = retry > CFG_MGMT_RETRY_MAX ?
4166 CFG_MGMT_RETRY_MAX : retry;
4167 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4168 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4169 retry, PDEV_CMD);
4170 }
4171
4172 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4173 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4174 retry = retry > CFG_CTRL_RETRY_MAX ?
4175 CFG_CTRL_RETRY_MAX : retry;
4176 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4177 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4178 retry, PDEV_CMD);
4179 }
4180
4181 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4182 delay = nla_get_u8(tb[
4183 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4184 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4185 CFG_PROPAGATION_DELAY_MAX : delay;
4186 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4187 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4188 delay, PDEV_CMD);
4189 }
4190
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304191 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4192 tx_fail_count = nla_get_u32(
4193 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4194 if (tx_fail_count) {
4195 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4196 adapter->sessionId, tx_fail_count);
4197 if (QDF_STATUS_SUCCESS != status) {
4198 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4199 status);
4200 return -EINVAL;
4201 }
4202 }
4203 }
4204
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304205 if (vendor_ie_present && access_policy_present) {
4206 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4207 access_policy =
4208 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304209 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304210 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304211 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304212
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304213 hdd_info("calling sme_update_access_policy_vendor_ie");
4214 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4215 adapter->sessionId, &vendor_ie[0],
4216 access_policy);
4217 if (QDF_STATUS_SUCCESS != status) {
4218 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304219 return -EINVAL;
4220 }
4221 }
4222
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304223 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4224 set_value = nla_get_u8(
4225 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4226 hdd_info("set_value: %d", set_value);
4227 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4228 }
4229
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304230 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4231 scan_ie_len = nla_len(
4232 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4233 hdd_info("Received default scan IE of len %d session %d device mode %d",
4234 scan_ie_len, adapter->sessionId,
4235 adapter->device_mode);
4236 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4237 scan_ie = (uint8_t *) nla_data(tb
4238 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304239
4240 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4241 scan_ie_len))
4242 hdd_err("Failed to save default scan IEs");
4243
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304244 if (adapter->device_mode == QDF_STA_MODE) {
4245 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4246 adapter->sessionId, scan_ie,
4247 scan_ie_len);
4248 if (QDF_STATUS_SUCCESS != status)
4249 ret_val = -EPERM;
4250 }
4251 } else
4252 ret_val = -EPERM;
4253 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304254
4255 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4256 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4257 /* if one is specified, both must be specified */
4258 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4259 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4260 hdd_err("Both TX and RX MPDU Aggregation required");
4261 return -EINVAL;
4262 }
4263
4264 request.tx_aggregation_size = nla_get_u8(
4265 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4266 request.rx_aggregation_size = nla_get_u8(
4267 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4268 request.vdev_id = adapter->sessionId;
4269
4270 if (request.tx_aggregation_size >=
4271 CFG_TX_AGGREGATION_SIZE_MIN &&
4272 request.tx_aggregation_size <=
4273 CFG_TX_AGGREGATION_SIZE_MAX &&
4274 request.rx_aggregation_size >=
4275 CFG_RX_AGGREGATION_SIZE_MIN &&
4276 request.rx_aggregation_size <=
4277 CFG_RX_AGGREGATION_SIZE_MAX) {
4278 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4279 if (qdf_status != QDF_STATUS_SUCCESS) {
4280 hdd_err("failed to set aggr sizes err %d",
4281 qdf_status);
4282 ret_val = -EPERM;
4283 }
4284 } else {
4285 hdd_err("TX %d RX %d MPDU aggr size not in range",
4286 request.tx_aggregation_size,
4287 request.rx_aggregation_size);
4288 ret_val = -EINVAL;
4289 }
4290 }
4291
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304292 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4293 uint8_t ignore_assoc_disallowed;
4294
4295 ignore_assoc_disallowed
4296 = nla_get_u8(tb[
4297 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4298 hdd_info("Set ignore_assoc_disallowed value - %d",
4299 ignore_assoc_disallowed);
4300 if ((ignore_assoc_disallowed <
4301 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4302 (ignore_assoc_disallowed >
4303 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4304 return -EPERM;
4305
4306 sme_update_session_param(hdd_ctx->hHal,
4307 adapter->sessionId,
4308 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4309 ignore_assoc_disallowed);
4310 }
4311
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004312 return ret_val;
4313}
4314
4315/**
4316 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4317 * vendor command
4318 *
4319 * @wiphy: wiphy device pointer
4320 * @wdev: wireless device pointer
4321 * @data: Vendor command data buffer
4322 * @data_len: Buffer length
4323 *
4324 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4325 *
4326 * Return: EOK or other error codes.
4327 */
4328static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4329 struct wireless_dev *wdev,
4330 const void *data,
4331 int data_len)
4332{
4333 int ret;
4334
4335 cds_ssr_protect(__func__);
4336 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4337 data, data_len);
4338 cds_ssr_unprotect(__func__);
4339
4340 return ret;
4341}
4342
4343static const struct
4344nla_policy
4345qca_wlan_vendor_wifi_logger_start_policy
4346[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4347 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4348 = {.type = NLA_U32 },
4349 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4350 = {.type = NLA_U32 },
4351 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4352 = {.type = NLA_U32 },
4353};
4354
4355/**
4356 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4357 * or disable the collection of packet statistics from the firmware
4358 * @wiphy: WIPHY structure pointer
4359 * @wdev: Wireless device structure pointer
4360 * @data: Pointer to the data received
4361 * @data_len: Length of the data received
4362 *
4363 * This function enables or disables the collection of packet statistics from
4364 * the firmware
4365 *
4366 * Return: 0 on success and errno on failure
4367 */
4368static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4369 struct wireless_dev *wdev,
4370 const void *data,
4371 int data_len)
4372{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304373 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004374 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4375 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4376 struct sir_wifi_start_log start_log;
4377
Jeff Johnson1f61b612016-02-12 16:28:33 -08004378 ENTER_DEV(wdev->netdev);
4379
Anurag Chouhan6d760662016-02-20 16:05:43 +05304380 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004381 hdd_err("Command not allowed in FTM mode");
4382 return -EPERM;
4383 }
4384
4385 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304386 if (status)
4387 return status;
4388
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004389
4390 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4391 data, data_len,
4392 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004393 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004394 return -EINVAL;
4395 }
4396
4397 /* Parse and fetch ring id */
4398 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004399 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 return -EINVAL;
4401 }
4402 start_log.ring_id = nla_get_u32(
4403 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004404 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004405
4406 /* Parse and fetch verbose level */
4407 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004408 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004409 return -EINVAL;
4410 }
4411 start_log.verbose_level = nla_get_u32(
4412 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004413 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004414
4415 /* Parse and fetch flag */
4416 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004417 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004418 return -EINVAL;
4419 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304420 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004421 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304422 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004423
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304424 /* size is buff size which can be set using iwpriv command*/
4425 start_log.size = 0;
4426
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004427 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4428
4429 if (start_log.ring_id == RING_ID_WAKELOCK) {
4430 /* Start/stop wakelock events */
4431 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4432 cds_set_wakelock_logging(true);
4433 else
4434 cds_set_wakelock_logging(false);
4435 return 0;
4436 }
4437
4438 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304439 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004440 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004441 status);
4442 return -EINVAL;
4443 }
4444 return 0;
4445}
4446
4447/**
4448 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4449 * or disable the collection of packet statistics from the firmware
4450 * @wiphy: WIPHY structure pointer
4451 * @wdev: Wireless device structure pointer
4452 * @data: Pointer to the data received
4453 * @data_len: Length of the data received
4454 *
4455 * This function is used to enable or disable the collection of packet
4456 * statistics from the firmware
4457 *
4458 * Return: 0 on success and errno on failure
4459 */
4460static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4461 struct wireless_dev *wdev,
4462 const void *data,
4463 int data_len)
4464{
4465 int ret = 0;
4466
4467 cds_ssr_protect(__func__);
4468 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4469 wdev, data, data_len);
4470 cds_ssr_unprotect(__func__);
4471
4472 return ret;
4473}
4474
4475static const struct
4476nla_policy
4477qca_wlan_vendor_wifi_logger_get_ring_data_policy
4478[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4479 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4480 = {.type = NLA_U32 },
4481};
4482
4483/**
4484 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4485 * @wiphy: WIPHY structure pointer
4486 * @wdev: Wireless device structure pointer
4487 * @data: Pointer to the data received
4488 * @data_len: Length of the data received
4489 *
4490 * This function is used to flush or retrieve the per packet statistics from
4491 * the driver
4492 *
4493 * Return: 0 on success and errno on failure
4494 */
4495static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4496 struct wireless_dev *wdev,
4497 const void *data,
4498 int data_len)
4499{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304500 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004501 uint32_t ring_id;
4502 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4503 struct nlattr *tb
4504 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4505
Jeff Johnson1f61b612016-02-12 16:28:33 -08004506 ENTER_DEV(wdev->netdev);
4507
Anurag Chouhan6d760662016-02-20 16:05:43 +05304508 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004509 hdd_err("Command not allowed in FTM mode");
4510 return -EPERM;
4511 }
4512
4513 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304514 if (status)
4515 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004516
4517 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4518 data, data_len,
4519 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004520 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 return -EINVAL;
4522 }
4523
4524 /* Parse and fetch ring id */
4525 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004526 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004527 return -EINVAL;
4528 }
4529
4530 ring_id = nla_get_u32(
4531 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4532
4533 if (ring_id == RING_ID_PER_PACKET_STATS) {
4534 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004535 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304536 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4537 /*
4538 * As part of DRIVER ring ID, flush both driver and fw logs.
4539 * For other Ring ID's driver doesn't have any rings to flush
4540 */
4541 hdd_notice("Bug report triggered by framework");
4542
4543 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4544 WLAN_LOG_INDICATOR_FRAMEWORK,
4545 WLAN_LOG_REASON_CODE_UNUSED,
4546 true, false);
4547 if (QDF_STATUS_SUCCESS != status) {
4548 hdd_err("Failed to trigger bug report");
4549 return -EINVAL;
4550 }
4551 } else {
4552 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4553 WLAN_LOG_INDICATOR_FRAMEWORK,
4554 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004555 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004556 return 0;
4557}
4558
4559/**
4560 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4561 * @wiphy: WIPHY structure pointer
4562 * @wdev: Wireless device structure pointer
4563 * @data: Pointer to the data received
4564 * @data_len: Length of the data received
4565 *
4566 * This function is used to flush or retrieve the per packet statistics from
4567 * the driver
4568 *
4569 * Return: 0 on success and errno on failure
4570 */
4571static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4572 struct wireless_dev *wdev,
4573 const void *data,
4574 int data_len)
4575{
4576 int ret = 0;
4577
4578 cds_ssr_protect(__func__);
4579 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4580 wdev, data, data_len);
4581 cds_ssr_unprotect(__func__);
4582
4583 return ret;
4584}
4585
4586#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4587/**
4588 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4589 * @hdd_ctx: HDD context
4590 * @request_id: [input] request id
4591 * @pattern_id: [output] pattern id
4592 *
4593 * This function loops through request id to pattern id array
4594 * if the slot is available, store the request id and return pattern id
4595 * if entry exists, return the pattern id
4596 *
4597 * Return: 0 on success and errno on failure
4598 */
4599static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4600 uint32_t request_id,
4601 uint8_t *pattern_id)
4602{
4603 uint32_t i;
4604
4605 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4606 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4607 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4608 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4609 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4610 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4611 return 0;
4612 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4613 request_id) {
4614 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4615 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4616 return 0;
4617 }
4618 }
4619 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4620 return -EINVAL;
4621}
4622
4623/**
4624 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4625 * @hdd_ctx: HDD context
4626 * @request_id: [input] request id
4627 * @pattern_id: [output] pattern id
4628 *
4629 * This function loops through request id to pattern id array
4630 * reset request id to 0 (slot available again) and
4631 * return pattern id
4632 *
4633 * Return: 0 on success and errno on failure
4634 */
4635static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4636 uint32_t request_id,
4637 uint8_t *pattern_id)
4638{
4639 uint32_t i;
4640
4641 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4642 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4643 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4644 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4645 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4646 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4647 return 0;
4648 }
4649 }
4650 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4651 return -EINVAL;
4652}
4653
4654
4655/*
4656 * define short names for the global vendor params
4657 * used by __wlan_hdd_cfg80211_offloaded_packets()
4658 */
4659#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4660#define PARAM_REQUEST_ID \
4661 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4662#define PARAM_CONTROL \
4663 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4664#define PARAM_IP_PACKET \
4665 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4666#define PARAM_SRC_MAC_ADDR \
4667 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4668#define PARAM_DST_MAC_ADDR \
4669 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4670#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4671
4672/**
4673 * wlan_hdd_add_tx_ptrn() - add tx pattern
4674 * @adapter: adapter pointer
4675 * @hdd_ctx: hdd context
4676 * @tb: nl attributes
4677 *
4678 * This function reads the NL attributes and forms a AddTxPtrn message
4679 * posts it to SME.
4680 *
4681 */
4682static int
4683wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4684 struct nlattr **tb)
4685{
4686 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304687 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004688 uint32_t request_id, ret, len;
4689 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304690 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004691 uint16_t eth_type = htons(ETH_P_IP);
4692
4693 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004694 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004695 return -ENOTSUPP;
4696 }
4697
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304698 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004699 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004700 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701 return -ENOMEM;
4702 }
4703
4704 /* Parse and fetch request Id */
4705 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004706 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004707 goto fail;
4708 }
4709
4710 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4711 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004712 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004713 return -EINVAL;
4714 }
Jeff Johnson77848112016-06-29 14:52:06 -07004715 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004716
4717 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004718 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004719 goto fail;
4720 }
4721 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004722 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004723 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004724 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004725 goto fail;
4726 }
4727
4728 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004729 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004730 goto fail;
4731 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004732 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304733 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004734 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004735 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004736
Anurag Chouhanc5548422016-02-24 18:33:27 +05304737 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004738 &adapter->macAddressCurrent)) {
4739 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004740 goto fail;
4741 }
4742
4743 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004744 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004745 goto fail;
4746 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304747 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004748 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004749 MAC_ADDR_ARRAY(dst_addr.bytes));
4750
4751 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004752 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004753 goto fail;
4754 }
4755 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004756 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004757
4758 if (add_req->ucPtrnSize < 0 ||
4759 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4760 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004761 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762 add_req->ucPtrnSize);
4763 goto fail;
4764 }
4765
4766 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304767 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304768 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304769 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304770 QDF_MAC_ADDR_SIZE);
4771 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304772 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004773 len += 2;
4774
4775 /*
4776 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4777 * ------------------------------------------------------------
4778 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4779 * ------------------------------------------------------------
4780 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304781 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004782 nla_data(tb[PARAM_IP_PACKET]),
4783 add_req->ucPtrnSize);
4784 add_req->ucPtrnSize += len;
4785
4786 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4787 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004788 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004789 goto fail;
4790 }
4791 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004792 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004793
4794 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304795 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004796 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004797 goto fail;
4798 }
4799
4800 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304801 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004802 return 0;
4803
4804fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304805 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004806 return -EINVAL;
4807}
4808
4809/**
4810 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4811 * @adapter: adapter pointer
4812 * @hdd_ctx: hdd context
4813 * @tb: nl attributes
4814 *
4815 * This function reads the NL attributes and forms a DelTxPtrn message
4816 * posts it to SME.
4817 *
4818 */
4819static int
4820wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4821 struct nlattr **tb)
4822{
4823 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304824 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004825 uint32_t request_id, ret;
4826 uint8_t pattern_id = 0;
4827
4828 /* Parse and fetch request Id */
4829 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004830 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004831 return -EINVAL;
4832 }
4833 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4834 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004835 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004836 return -EINVAL;
4837 }
4838
4839 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4840 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004841 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004842 return -EINVAL;
4843 }
4844
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304845 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004846 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004847 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004848 return -ENOMEM;
4849 }
4850
Anurag Chouhanc5548422016-02-24 18:33:27 +05304851 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004852 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004853 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004854 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004855 request_id, del_req->ucPtrnId);
4856
4857 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304858 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004859 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860 goto fail;
4861 }
4862
4863 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304864 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004865 return 0;
4866
4867fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304868 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004869 return -EINVAL;
4870}
4871
4872
4873/**
4874 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4875 * @wiphy: Pointer to wireless phy
4876 * @wdev: Pointer to wireless device
4877 * @data: Pointer to data
4878 * @data_len: Data length
4879 *
4880 * Return: 0 on success, negative errno on failure
4881 */
4882static int
4883__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4884 struct wireless_dev *wdev,
4885 const void *data,
4886 int data_len)
4887{
4888 struct net_device *dev = wdev->netdev;
4889 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4890 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4891 struct nlattr *tb[PARAM_MAX + 1];
4892 uint8_t control;
4893 int ret;
4894 static const struct nla_policy policy[PARAM_MAX + 1] = {
4895 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4896 [PARAM_CONTROL] = { .type = NLA_U32 },
4897 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304898 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004899 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304900 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004901 [PARAM_PERIOD] = { .type = NLA_U32 },
4902 };
4903
Jeff Johnson1f61b612016-02-12 16:28:33 -08004904 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004905
Anurag Chouhan6d760662016-02-20 16:05:43 +05304906 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004907 hdd_err("Command not allowed in FTM mode");
4908 return -EPERM;
4909 }
4910
4911 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304912 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004913 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914
4915 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004916 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917 return -ENOTSUPP;
4918 }
4919
4920 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004921 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004922 return -EINVAL;
4923 }
4924
4925 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004926 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004927 return -EINVAL;
4928 }
4929 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004930 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004931
4932 if (control == WLAN_START_OFFLOADED_PACKETS)
4933 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4934 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4935 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4936 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004937 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004938 return -EINVAL;
4939 }
4940}
4941
4942/*
4943 * done with short names for the global vendor params
4944 * used by __wlan_hdd_cfg80211_offloaded_packets()
4945 */
4946#undef PARAM_MAX
4947#undef PARAM_REQUEST_ID
4948#undef PARAM_CONTROL
4949#undef PARAM_IP_PACKET
4950#undef PARAM_SRC_MAC_ADDR
4951#undef PARAM_DST_MAC_ADDR
4952#undef PARAM_PERIOD
4953
4954/**
4955 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4956 * @wiphy: wiphy structure pointer
4957 * @wdev: Wireless device structure pointer
4958 * @data: Pointer to the data received
4959 * @data_len: Length of @data
4960 *
4961 * Return: 0 on success; errno on failure
4962 */
4963static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4964 struct wireless_dev *wdev,
4965 const void *data,
4966 int data_len)
4967{
4968 int ret = 0;
4969
4970 cds_ssr_protect(__func__);
4971 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4972 wdev, data, data_len);
4973 cds_ssr_unprotect(__func__);
4974
4975 return ret;
4976}
4977#endif
4978
4979/*
4980 * define short names for the global vendor params
4981 * used by __wlan_hdd_cfg80211_monitor_rssi()
4982 */
4983#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4984#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4985#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4986#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4987#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4988
4989/**
4990 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4991 * @wiphy: Pointer to wireless phy
4992 * @wdev: Pointer to wireless device
4993 * @data: Pointer to data
4994 * @data_len: Data length
4995 *
4996 * Return: 0 on success, negative errno on failure
4997 */
4998static int
4999__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5000 struct wireless_dev *wdev,
5001 const void *data,
5002 int data_len)
5003{
5004 struct net_device *dev = wdev->netdev;
5005 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5006 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5007 struct nlattr *tb[PARAM_MAX + 1];
5008 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305009 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005010 int ret;
5011 uint32_t control;
5012 static const struct nla_policy policy[PARAM_MAX + 1] = {
5013 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5014 [PARAM_CONTROL] = { .type = NLA_U32 },
5015 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5016 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5017 };
5018
Jeff Johnson1f61b612016-02-12 16:28:33 -08005019 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005020
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305021 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5022 hdd_err("invalid session id: %d", adapter->sessionId);
5023 return -EINVAL;
5024 }
5025
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005026 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305027 if (ret)
5028 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005029
5030 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005031 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005032 return -ENOTSUPP;
5033 }
5034
5035 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005036 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005037 return -EINVAL;
5038 }
5039
5040 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005041 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005042 return -EINVAL;
5043 }
5044
5045 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005046 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005047 return -EINVAL;
5048 }
5049
5050 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5051 req.session_id = adapter->sessionId;
5052 control = nla_get_u32(tb[PARAM_CONTROL]);
5053
5054 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5055 req.control = true;
5056 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005057 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005058 return -EINVAL;
5059 }
5060
5061 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005062 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005063 return -EINVAL;
5064 }
5065
5066 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5067 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5068
5069 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005070 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005071 req.min_rssi, req.max_rssi);
5072 return -EINVAL;
5073 }
Jeff Johnson77848112016-06-29 14:52:06 -07005074 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005075 req.min_rssi, req.max_rssi);
5076
5077 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5078 req.control = false;
5079 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005080 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005081 return -EINVAL;
5082 }
Jeff Johnson77848112016-06-29 14:52:06 -07005083 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005084 req.request_id, req.session_id, req.control);
5085
5086 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305087 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005088 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005089 return -EINVAL;
5090 }
5091
5092 return 0;
5093}
5094
5095/*
5096 * done with short names for the global vendor params
5097 * used by __wlan_hdd_cfg80211_monitor_rssi()
5098 */
5099#undef PARAM_MAX
5100#undef PARAM_CONTROL
5101#undef PARAM_REQUEST_ID
5102#undef PARAM_MAX_RSSI
5103#undef PARAM_MIN_RSSI
5104
5105/**
5106 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5107 * @wiphy: wiphy structure pointer
5108 * @wdev: Wireless device structure pointer
5109 * @data: Pointer to the data received
5110 * @data_len: Length of @data
5111 *
5112 * Return: 0 on success; errno on failure
5113 */
5114static int
5115wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5116 const void *data, int data_len)
5117{
5118 int ret;
5119
5120 cds_ssr_protect(__func__);
5121 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5122 cds_ssr_unprotect(__func__);
5123
5124 return ret;
5125}
5126
5127/**
5128 * hdd_rssi_threshold_breached() - rssi breached NL event
5129 * @hddctx: HDD context
5130 * @data: rssi breached event data
5131 *
5132 * This function reads the rssi breached event %data and fill in the skb with
5133 * NL attributes and send up the NL event.
5134 *
5135 * Return: none
5136 */
5137void hdd_rssi_threshold_breached(void *hddctx,
5138 struct rssi_breach_event *data)
5139{
5140 hdd_context_t *hdd_ctx = hddctx;
5141 struct sk_buff *skb;
5142
5143 ENTER();
5144
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305145 if (wlan_hdd_validate_context(hdd_ctx))
5146 return;
5147 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005148 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149 return;
5150 }
5151
5152 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5153 NULL,
5154 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5155 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5156 GFP_KERNEL);
5157
5158 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005159 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005160 return;
5161 }
5162
Jeff Johnson77848112016-06-29 14:52:06 -07005163 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005164 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005165 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005166 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5167
5168 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5169 data->request_id) ||
5170 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5171 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5172 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5173 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005174 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005175 goto fail;
5176 }
5177
5178 cfg80211_vendor_event(skb, GFP_KERNEL);
5179 return;
5180
5181fail:
5182 kfree_skb(skb);
5183 return;
5184}
5185
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305186static const struct nla_policy
5187ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5188 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5189};
5190
5191/**
5192 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5193 * @wiphy: Pointer to wireless phy
5194 * @wdev: Pointer to wireless device
5195 * @data: Pointer to data
5196 * @data_len: Length of @data
5197 *
5198 * Return: 0 on success, negative errno on failure
5199 */
5200static int
5201__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5202 struct wireless_dev *wdev,
5203 const void *data, int data_len)
5204{
5205 int status;
5206 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5207 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005208 struct net_device *dev = wdev->netdev;
5209 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305210
5211 ENTER_DEV(wdev->netdev);
5212
5213 status = wlan_hdd_validate_context(pHddCtx);
5214 if (0 != status)
5215 return status;
5216 if (!pHddCtx->config->fhostNSOffload) {
5217 hdd_err("ND Offload not supported");
5218 return -EINVAL;
5219 }
5220
5221 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5222 (struct nlattr *)data,
5223 data_len, ns_offload_set_policy)) {
5224 hdd_err("nla_parse failed");
5225 return -EINVAL;
5226 }
5227
5228 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5229 hdd_err("ND Offload flag attribute not present");
5230 return -EINVAL;
5231 }
5232
5233 pHddCtx->ns_offload_enable =
5234 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5235
Dustin Brownd8279d22016-09-07 14:52:57 -07005236 /* update ns offload in case it is already enabled/disabled */
5237 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5238
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305239 return 0;
5240}
5241
5242/**
5243 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5244 * @wiphy: pointer to wireless wiphy structure.
5245 * @wdev: pointer to wireless_dev structure.
5246 * @data: Pointer to the data to be passed via vendor interface
5247 * @data_len:Length of the data to be passed
5248 *
5249 * Return: Return the Success or Failure code.
5250 */
5251static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5252 struct wireless_dev *wdev,
5253 const void *data, int data_len)
5254{
5255 int ret;
5256
5257 cds_ssr_protect(__func__);
5258 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5259 cds_ssr_unprotect(__func__);
5260
5261 return ret;
5262}
5263
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005264/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5265 * @wiphy: Pointer to wireless phy
5266 * @wdev: Pointer to wireless device
5267 * @data: Pointer to data
5268 * @data_len: Data length
5269 *
5270 * This function return the preferred frequency list generated by the policy
5271 * manager.
5272 *
5273 * Return: success or failure code
5274 */
5275static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5276 struct wireless_dev
5277 *wdev, const void *data,
5278 int data_len)
5279{
5280 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5281 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305282 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305283 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005284 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305285 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005286 enum cds_con_mode intf_mode;
5287 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5288 struct sk_buff *reply_skb;
5289
Jeff Johnson1f61b612016-02-12 16:28:33 -08005290 ENTER_DEV(wdev->netdev);
5291
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005292 ret = wlan_hdd_validate_context(hdd_ctx);
5293 if (ret)
5294 return -EINVAL;
5295
5296 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5297 data, data_len, NULL)) {
5298 hdd_err("Invalid ATTR");
5299 return -EINVAL;
5300 }
5301
5302 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5303 hdd_err("attr interface type failed");
5304 return -EINVAL;
5305 }
5306
5307 intf_mode = nla_get_u32(tb
5308 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5309
5310 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5311 hdd_err("Invalid interface type");
5312 return -EINVAL;
5313 }
5314
5315 hdd_debug("Userspace requested pref freq list");
5316
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305317 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5318 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305319 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005320 hdd_err("Get pcl failed");
5321 return -EINVAL;
5322 }
5323
5324 /* convert channel number to frequency */
5325 for (i = 0; i < pcl_len; i++) {
5326 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5327 freq_list[i] =
5328 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005329 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005330 else
5331 freq_list[i] =
5332 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005333 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005334 }
5335
5336 /* send the freq_list back to supplicant */
5337 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5338 sizeof(u32) *
5339 pcl_len +
5340 NLMSG_HDRLEN);
5341
5342 if (!reply_skb) {
5343 hdd_err("Allocate reply_skb failed");
5344 return -EINVAL;
5345 }
5346
5347 if (nla_put_u32(reply_skb,
5348 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5349 intf_mode) ||
5350 nla_put(reply_skb,
5351 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5352 sizeof(uint32_t) * pcl_len,
5353 freq_list)) {
5354 hdd_err("nla put fail");
5355 kfree_skb(reply_skb);
5356 return -EINVAL;
5357 }
5358
5359 return cfg80211_vendor_cmd_reply(reply_skb);
5360}
5361
5362/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5363 * @wiphy: Pointer to wireless phy
5364 * @wdev: Pointer to wireless device
5365 * @data: Pointer to data
5366 * @data_len: Data length
5367 *
5368 * This function return the preferred frequency list generated by the policy
5369 * manager.
5370 *
5371 * Return: success or failure code
5372 */
5373static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5374 struct wireless_dev
5375 *wdev, const void *data,
5376 int data_len)
5377{
5378 int ret = 0;
5379
5380 cds_ssr_protect(__func__);
5381 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5382 data, data_len);
5383 cds_ssr_unprotect(__func__);
5384
5385 return ret;
5386}
5387
5388/**
5389 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5390 * @wiphy: Pointer to wireless phy
5391 * @wdev: Pointer to wireless device
5392 * @data: Pointer to data
5393 * @data_len: Data length
5394 *
5395 * Return: 0 on success, negative errno on failure
5396 */
5397static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5398 struct wireless_dev *wdev,
5399 const void *data,
5400 int data_len)
5401{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305402 struct net_device *ndev = wdev->netdev;
5403 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005404 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5405 int ret = 0;
5406 enum cds_con_mode intf_mode;
5407 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5408 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005409
Jeff Johnson1f61b612016-02-12 16:28:33 -08005410 ENTER_DEV(ndev);
5411
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005412 ret = wlan_hdd_validate_context(hdd_ctx);
5413 if (ret)
5414 return ret;
5415
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5417 data, data_len, NULL)) {
5418 hdd_err("Invalid ATTR");
5419 return -EINVAL;
5420 }
5421
5422 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5423 hdd_err("attr interface type failed");
5424 return -EINVAL;
5425 }
5426
5427 intf_mode = nla_get_u32(tb
5428 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5429
5430 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5431 hdd_err("Invalid interface type");
5432 return -EINVAL;
5433 }
5434
5435 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5436 hdd_err("attr probable freq failed");
5437 return -EINVAL;
5438 }
5439
5440 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5441 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5442
5443 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005444 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005445 channel_hint, HW_MODE_20_MHZ)) {
5446 hdd_err("Set channel hint failed due to concurrency check");
5447 return -EINVAL;
5448 }
5449
Krunal Soni09e55032016-06-07 10:06:55 -07005450 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5451 hdd_warn("Remain On Channel Pending");
5452
Krunal Soni3091bcc2016-06-23 12:28:21 -07005453 ret = qdf_reset_connection_update();
5454 if (!QDF_IS_STATUS_SUCCESS(ret))
5455 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005456
Krunal Soni3091bcc2016-06-23 12:28:21 -07005457 ret = cds_current_connections_update(adapter->sessionId,
5458 channel_hint,
5459 SIR_UPDATE_REASON_SET_OPER_CHAN);
5460 if (QDF_STATUS_E_FAILURE == ret) {
5461 /* return in the failure case */
5462 hdd_err("ERROR: connections update failed!!");
5463 return -EINVAL;
5464 }
5465
5466 if (QDF_STATUS_SUCCESS == ret) {
5467 /*
5468 * Success is the only case for which we expect hw mode
5469 * change to take place, hence we need to wait.
5470 * For any other return value it should be a pass
5471 * through
5472 */
5473 ret = qdf_wait_for_connection_update();
5474 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5475 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005476 return -EINVAL;
5477 }
5478
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005479 }
5480
5481 return 0;
5482}
5483
5484/**
5485 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5486 * @wiphy: Pointer to wireless phy
5487 * @wdev: Pointer to wireless device
5488 * @data: Pointer to data
5489 * @data_len: Data length
5490 *
5491 * Return: 0 on success, negative errno on failure
5492 */
5493static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5494 struct wireless_dev *wdev,
5495 const void *data,
5496 int data_len)
5497{
5498 int ret = 0;
5499
5500 cds_ssr_protect(__func__);
5501 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5502 data, data_len);
5503 cds_ssr_unprotect(__func__);
5504
5505 return ret;
5506}
5507
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305508static const struct
5509nla_policy
5510qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5511 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5512};
5513
5514/**
5515 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5516 * @wiphy: WIPHY structure pointer
5517 * @wdev: Wireless device structure pointer
5518 * @data: Pointer to the data received
5519 * @data_len: Length of the data received
5520 *
5521 * This function is used to get link properties like nss, rate flags and
5522 * operating frequency for the active connection with the given peer.
5523 *
5524 * Return: 0 on success and errno on failure
5525 */
5526static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5527 struct wireless_dev *wdev,
5528 const void *data,
5529 int data_len)
5530{
5531 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5532 struct net_device *dev = wdev->netdev;
5533 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5534 hdd_station_ctx_t *hdd_sta_ctx;
5535 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305536 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305537 uint32_t sta_id;
5538 struct sk_buff *reply_skb;
5539 uint32_t rate_flags = 0;
5540 uint8_t nss;
5541 uint8_t final_rate_flags = 0;
5542 uint32_t freq;
5543
Jeff Johnson1f61b612016-02-12 16:28:33 -08005544 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305545
Anurag Chouhan6d760662016-02-20 16:05:43 +05305546 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305547 hdd_err("Command not allowed in FTM mode");
5548 return -EPERM;
5549 }
5550
5551 if (0 != wlan_hdd_validate_context(hdd_ctx))
5552 return -EINVAL;
5553
5554 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5555 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005556 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305557 return -EINVAL;
5558 }
5559
5560 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005561 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305562 adapter->device_mode);
5563 return -EINVAL;
5564 }
5565
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305566 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305567 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005568 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305569 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5570
Krunal Sonib4326f22016-03-10 13:05:51 -08005571 if (adapter->device_mode == QDF_STA_MODE ||
5572 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305573 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5574 if ((hdd_sta_ctx->conn_info.connState !=
5575 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305576 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305577 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005578 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305579 MAC_ADDR_ARRAY(peer_mac));
5580 return -EINVAL;
5581 }
5582
5583 nss = hdd_sta_ctx->conn_info.nss;
5584 freq = cds_chan_to_freq(
5585 hdd_sta_ctx->conn_info.operationChannel);
5586 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005587 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5588 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305589
5590 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5591 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305592 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305593 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305594 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305595 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305596 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305597 break;
5598 }
5599
5600 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005601 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305602 MAC_ADDR_ARRAY(peer_mac));
5603 return -EINVAL;
5604 }
5605
5606 nss = adapter->aStaInfo[sta_id].nss;
5607 freq = cds_chan_to_freq(
5608 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5609 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5610 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005611 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305612 MAC_ADDR_ARRAY(peer_mac));
5613 return -EINVAL;
5614 }
5615
5616 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5617 if (rate_flags & eHAL_TX_RATE_VHT80) {
5618 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005619#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305620 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005621#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305622 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5623 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005624#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305625 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005626#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305627 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5628 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5629 } else if (rate_flags &
5630 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5631 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005632#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305633 if (rate_flags & eHAL_TX_RATE_HT40)
5634 final_rate_flags |=
5635 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005636#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305637 }
5638
5639 if (rate_flags & eHAL_TX_RATE_SGI) {
5640 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5641 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5642 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5643 }
5644 }
5645
5646 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5647 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5648
5649 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005650 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305651 return -EINVAL;
5652 }
5653
5654 if (nla_put_u8(reply_skb,
5655 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5656 nss) ||
5657 nla_put_u8(reply_skb,
5658 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5659 final_rate_flags) ||
5660 nla_put_u32(reply_skb,
5661 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5662 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005663 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305664 kfree_skb(reply_skb);
5665 return -EINVAL;
5666 }
5667
5668 return cfg80211_vendor_cmd_reply(reply_skb);
5669}
5670
5671/**
5672 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5673 * properties.
5674 * @wiphy: WIPHY structure pointer
5675 * @wdev: Wireless device structure pointer
5676 * @data: Pointer to the data received
5677 * @data_len: Length of the data received
5678 *
5679 * This function is used to get link properties like nss, rate flags and
5680 * operating frequency for the active connection with the given peer.
5681 *
5682 * Return: 0 on success and errno on failure
5683 */
5684static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5685 struct wireless_dev *wdev,
5686 const void *data,
5687 int data_len)
5688{
5689 int ret = 0;
5690
5691 cds_ssr_protect(__func__);
5692 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5693 wdev, data, data_len);
5694 cds_ssr_unprotect(__func__);
5695
5696 return ret;
5697}
5698
Peng Xu278d0122015-09-24 16:34:17 -07005699static const struct
5700nla_policy
5701qca_wlan_vendor_ota_test_policy
5702[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5703 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5704};
5705
5706/**
5707 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5708 * @wiphy: Pointer to wireless phy
5709 * @wdev: Pointer to wireless device
5710 * @data: Pointer to data
5711 * @data_len: Data length
5712 *
5713 * Return: 0 on success, negative errno on failure
5714 */
5715static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5716 struct wireless_dev *wdev,
5717 const void *data,
5718 int data_len)
5719{
5720 struct net_device *dev = wdev->netdev;
5721 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5722 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5723 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5724 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5725 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305726 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005727 uint32_t current_roam_state;
5728
Jeff Johnson1f61b612016-02-12 16:28:33 -08005729 ENTER_DEV(dev);
5730
Anurag Chouhan6d760662016-02-20 16:05:43 +05305731 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005732 hdd_err("Command not allowed in FTM mode");
5733 return -EPERM;
5734 }
5735
5736 if (0 != wlan_hdd_validate_context(hdd_ctx))
5737 return -EINVAL;
5738
5739 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5740 data, data_len,
5741 qca_wlan_vendor_ota_test_policy)) {
5742 hdd_err("invalid attr");
5743 return -EINVAL;
5744 }
5745
5746 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5747 hdd_err("attr ota test failed");
5748 return -EINVAL;
5749 }
5750
5751 ota_enable = nla_get_u8(
5752 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5753
5754 hdd_info(" OTA test enable = %d", ota_enable);
5755 if (ota_enable != 1) {
5756 hdd_err("Invalid value, only enable test mode is supported!");
5757 return -EINVAL;
5758 }
5759
5760 current_roam_state =
5761 sme_get_current_roam_state(hal, adapter->sessionId);
5762 status = sme_stop_roaming(hal, adapter->sessionId,
5763 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305764 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005765 hdd_err("Enable/Disable roaming failed");
5766 return -EINVAL;
5767 }
5768
5769 status = sme_ps_enable_disable(hal, adapter->sessionId,
5770 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305771 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005772 hdd_err("Enable/Disable power save failed");
5773 /* restore previous roaming setting */
5774 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5775 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5776 status = sme_start_roaming(hal, adapter->sessionId,
5777 eCsrHddIssued);
5778 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5779 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5780 status = sme_stop_roaming(hal, adapter->sessionId,
5781 eCsrHddIssued);
5782
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305783 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005784 hdd_err("Restoring roaming state failed");
5785
5786 return -EINVAL;
5787 }
5788
5789
5790 return 0;
5791}
5792
5793/**
5794 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5795 * @wiphy: Pointer to wireless phy
5796 * @wdev: Pointer to wireless device
5797 * @data: Pointer to data
5798 * @data_len: Data length
5799 *
5800 * Return: 0 on success, negative errno on failure
5801 */
5802static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5803 struct wireless_dev *wdev,
5804 const void *data,
5805 int data_len)
5806{
5807 int ret = 0;
5808
5809 cds_ssr_protect(__func__);
5810 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5811 cds_ssr_unprotect(__func__);
5812
5813 return ret;
5814}
5815
Peng Xu4d67c8f2015-10-16 16:02:26 -07005816/**
5817 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5818 * @wiphy: Pointer to wireless phy
5819 * @wdev: Pointer to wireless device
5820 * @data: Pointer to data
5821 * @data_len: Data length
5822 *
5823 * Return: 0 on success, negative errno on failure
5824 */
5825static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5826 struct wireless_dev *wdev,
5827 const void *data,
5828 int data_len)
5829{
5830 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5831 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005832 hdd_adapter_t *adapter;
5833 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005834 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5835 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005836 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005837
Jeff Johnson1f61b612016-02-12 16:28:33 -08005838 ENTER_DEV(dev);
5839
Peng Xu4d67c8f2015-10-16 16:02:26 -07005840 ret = wlan_hdd_validate_context(hdd_ctx);
5841 if (ret)
5842 return ret;
5843
5844 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5845
5846 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5847 data, data_len, NULL)) {
5848 hdd_err("Invalid ATTR");
5849 return -EINVAL;
5850 }
5851
5852 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5853 hdd_err("attr tx power scale failed");
5854 return -EINVAL;
5855 }
5856
5857 scale_value = nla_get_u8(tb
5858 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5859
5860 if (scale_value > MAX_TXPOWER_SCALE) {
5861 hdd_err("Invalid tx power scale level");
5862 return -EINVAL;
5863 }
5864
Peng Xu62c8c432016-05-09 15:23:02 -07005865 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005866
Peng Xu62c8c432016-05-09 15:23:02 -07005867 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005868 hdd_err("Set tx power scale failed");
5869 return -EINVAL;
5870 }
5871
5872 return 0;
5873}
5874
5875/**
5876 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5877 * @wiphy: Pointer to wireless phy
5878 * @wdev: Pointer to wireless device
5879 * @data: Pointer to data
5880 * @data_len: Data length
5881 *
5882 * Return: 0 on success, negative errno on failure
5883 */
5884static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5885 struct wireless_dev *wdev,
5886 const void *data,
5887 int data_len)
5888{
Peng Xu62c8c432016-05-09 15:23:02 -07005889 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005890
5891 cds_ssr_protect(__func__);
5892 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5893 data, data_len);
5894 cds_ssr_unprotect(__func__);
5895
5896 return ret;
5897}
5898
5899/**
5900 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5901 * @wiphy: Pointer to wireless phy
5902 * @wdev: Pointer to wireless device
5903 * @data: Pointer to data
5904 * @data_len: Data length
5905 *
5906 * Return: 0 on success, negative errno on failure
5907 */
5908static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5909 struct wireless_dev *wdev,
5910 const void *data,
5911 int data_len)
5912{
5913 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5914 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005915 hdd_adapter_t *adapter;
5916 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005917 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5918 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005919 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005920
Jeff Johnson1f61b612016-02-12 16:28:33 -08005921 ENTER_DEV(dev);
5922
Peng Xu4d67c8f2015-10-16 16:02:26 -07005923 ret = wlan_hdd_validate_context(hdd_ctx);
5924 if (ret)
5925 return ret;
5926
5927 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5928
5929 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5930 data, data_len, NULL)) {
5931 hdd_err("Invalid ATTR");
5932 return -EINVAL;
5933 }
5934
5935 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5936 hdd_err("attr tx power decrease db value failed");
5937 return -EINVAL;
5938 }
5939
5940 scale_value = nla_get_u8(tb
5941 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5942
Peng Xu62c8c432016-05-09 15:23:02 -07005943 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5944 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005945
Peng Xu62c8c432016-05-09 15:23:02 -07005946 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005947 hdd_err("Set tx power decrease db failed");
5948 return -EINVAL;
5949 }
5950
5951 return 0;
5952}
5953
5954/**
5955 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5956 * @wiphy: Pointer to wireless phy
5957 * @wdev: Pointer to wireless device
5958 * @data: Pointer to data
5959 * @data_len: Data length
5960 *
5961 * Return: 0 on success, negative errno on failure
5962 */
5963static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5964 struct wireless_dev *wdev,
5965 const void *data,
5966 int data_len)
5967{
Peng Xu62c8c432016-05-09 15:23:02 -07005968 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005969
5970 cds_ssr_protect(__func__);
5971 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5972 data, data_len);
5973 cds_ssr_unprotect(__func__);
5974
5975 return ret;
5976}
Peng Xu8fdaa492016-06-22 10:20:47 -07005977
5978/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305979 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5980 * @wiphy: Pointer to wireless phy
5981 * @wdev: Pointer to wireless device
5982 * @data: Pointer to data
5983 * @data_len: Data length
5984 *
5985 * Processes the conditional channel switch request and invokes the helper
5986 * APIs to process the channel switch request.
5987 *
5988 * Return: 0 on success, negative errno on failure
5989 */
5990static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5991 struct wireless_dev *wdev,
5992 const void *data,
5993 int data_len)
5994{
5995 int ret;
5996 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5997 struct net_device *dev = wdev->netdev;
5998 hdd_adapter_t *adapter;
5999 struct nlattr
6000 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6001 uint32_t freq_len, i;
6002 uint32_t *freq;
6003 uint8_t chans[QDF_MAX_NUM_CHAN];
6004
6005 ENTER_DEV(dev);
6006
6007 ret = wlan_hdd_validate_context(hdd_ctx);
6008 if (ret)
6009 return ret;
6010
6011 if (!hdd_ctx->config->enableDFSMasterCap) {
6012 hdd_err("DFS master capability is not present in the driver");
6013 return -EINVAL;
6014 }
6015
6016 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6017 hdd_err("Command not allowed in FTM mode");
6018 return -EPERM;
6019 }
6020
6021 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6022 if (adapter->device_mode != QDF_SAP_MODE) {
6023 hdd_err("Invalid device mode %d", adapter->device_mode);
6024 return -EINVAL;
6025 }
6026
6027 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6028 data, data_len, NULL)) {
6029 hdd_err("Invalid ATTR");
6030 return -EINVAL;
6031 }
6032
6033 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6034 hdd_err("Frequency list is missing");
6035 return -EINVAL;
6036 }
6037
6038 freq_len = nla_len(
6039 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6040 sizeof(uint32_t);
6041
6042 if (freq_len > QDF_MAX_NUM_CHAN) {
6043 hdd_err("insufficient space to hold channels");
6044 return -ENOMEM;
6045 }
6046
6047 hdd_debug("freq_len=%d", freq_len);
6048
6049 freq = nla_data(
6050 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6051
6052
6053 for (i = 0; i < freq_len; i++) {
6054 if (freq[i] == 0)
6055 chans[i] = 0;
6056 else
6057 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6058
6059 hdd_debug("freq[%d]=%d", i, freq[i]);
6060 }
6061
6062 /*
6063 * The input frequency list from user space is designed to be a
6064 * priority based frequency list. This is only to accommodate any
6065 * future request. But, current requirement is only to perform CAC
6066 * on a single channel. So, the first entry from the list is picked.
6067 *
6068 * If channel is zero, any channel in the available outdoor regulatory
6069 * domain will be selected.
6070 */
6071 ret = wlan_hdd_request_pre_cac(chans[0]);
6072 if (ret) {
6073 hdd_err("pre cac request failed with reason:%d", ret);
6074 return ret;
6075 }
6076
6077 return 0;
6078}
6079
6080/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006081 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6082 * @wiphy: Pointer to wireless phy
6083 * @wdev: Pointer to wireless device
6084 * @data: Pointer to data
6085 * @data_len: Data length
6086 *
6087 * This function is to process the p2p listen offload start vendor
6088 * command. It parses the input parameters and invoke WMA API to
6089 * send the command to firmware.
6090 *
6091 * Return: 0 on success, negative errno on failure
6092 */
6093static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6094 struct wireless_dev *wdev,
6095 const void *data,
6096 int data_len)
6097{
6098 int ret;
6099 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6100 struct net_device *dev = wdev->netdev;
6101 hdd_adapter_t *adapter;
6102 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6103 struct sir_p2p_lo_start params;
6104 QDF_STATUS status;
6105
6106 ENTER_DEV(dev);
6107
6108 ret = wlan_hdd_validate_context(hdd_ctx);
6109 if (ret)
6110 return ret;
6111
6112 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6113 hdd_err("Command not allowed in FTM mode");
6114 return -EPERM;
6115 }
6116
6117 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6118 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6119 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6120 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6121 hdd_err("Invalid device mode %d", adapter->device_mode);
6122 return -EINVAL;
6123 }
6124
6125 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6126 data, data_len, NULL)) {
6127 hdd_err("Invalid ATTR");
6128 return -EINVAL;
6129 }
6130
6131 memset(&params, 0, sizeof(params));
6132
6133 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6134 params.ctl_flags = 1; /* set to default value */
6135 else
6136 params.ctl_flags = nla_get_u32(tb
6137 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6138
6139 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6140 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6141 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6142 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6143 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6144 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6145 hdd_err("Attribute parsing failed");
6146 return -EINVAL;
6147 }
6148
6149 params.vdev_id = adapter->sessionId;
6150 params.freq = nla_get_u32(tb
6151 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6152 if ((params.freq != 2412) && (params.freq != 2437) &&
6153 (params.freq != 2462)) {
6154 hdd_err("Invalid listening channel: %d", params.freq);
6155 return -EINVAL;
6156 }
6157
6158 params.period = nla_get_u32(tb
6159 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6160 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6161 hdd_err("Invalid period: %d", params.period);
6162 return -EINVAL;
6163 }
6164
6165 params.interval = nla_get_u32(tb
6166 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6167 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6168 hdd_err("Invalid interval: %d", params.interval);
6169 return -EINVAL;
6170 }
6171
6172 params.count = nla_get_u32(tb
6173 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006174 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006175 hdd_err("Invalid count: %d", params.count);
6176 return -EINVAL;
6177 }
6178
6179 params.device_types = nla_data(tb
6180 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6181 if (params.device_types == NULL) {
6182 hdd_err("Invalid device types");
6183 return -EINVAL;
6184 }
6185
6186 params.dev_types_len = nla_len(tb
6187 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6188 if (params.dev_types_len < 8) {
6189 hdd_err("Invalid device type length: %d", params.dev_types_len);
6190 return -EINVAL;
6191 }
6192
6193 params.probe_resp_tmplt = nla_data(tb
6194 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6195 if (params.probe_resp_tmplt == NULL) {
6196 hdd_err("Invalid probe response template");
6197 return -EINVAL;
6198 }
6199
6200 params.probe_resp_len = nla_len(tb
6201 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6202 if (params.probe_resp_len == 0) {
6203 hdd_err("Invalid probe resp template length: %d",
6204 params.probe_resp_len);
6205 return -EINVAL;
6206 }
6207
6208 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6209 params.freq, params.period, params.interval, params.count);
6210
6211 status = wma_p2p_lo_start(&params);
6212
6213 if (!QDF_IS_STATUS_SUCCESS(status)) {
6214 hdd_err("P2P LO start failed");
6215 return -EINVAL;
6216 }
6217
6218 return 0;
6219}
6220
6221
6222/**
6223 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6224 * @wiphy: Pointer to wireless phy
6225 * @wdev: Pointer to wireless device
6226 * @data: Pointer to data
6227 * @data_len: Data length
6228 *
6229 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6230 * to process p2p listen offload start vendor command.
6231 *
6232 * Return: 0 on success, negative errno on failure
6233 */
6234static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6235 struct wireless_dev *wdev,
6236 const void *data,
6237 int data_len)
6238{
6239 int ret = 0;
6240
6241 cds_ssr_protect(__func__);
6242 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6243 data, data_len);
6244 cds_ssr_unprotect(__func__);
6245
6246 return ret;
6247}
6248
6249/**
6250 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6251 * @wiphy: Pointer to wireless phy
6252 * @wdev: Pointer to wireless device
6253 * @data: Pointer to data
6254 * @data_len: Data length
6255 *
6256 * This function is to process the p2p listen offload stop vendor
6257 * command. It invokes WMA API to send command to firmware.
6258 *
6259 * Return: 0 on success, negative errno on failure
6260 */
6261static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6262 struct wireless_dev *wdev,
6263 const void *data,
6264 int data_len)
6265{
6266 QDF_STATUS status;
6267 hdd_adapter_t *adapter;
6268 struct net_device *dev = wdev->netdev;
6269
6270 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6271 hdd_err("Command not allowed in FTM mode");
6272 return -EPERM;
6273 }
6274
6275 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6276 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6277 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6278 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6279 hdd_err("Invalid device mode");
6280 return -EINVAL;
6281 }
6282
6283 status = wma_p2p_lo_stop(adapter->sessionId);
6284
6285 if (!QDF_IS_STATUS_SUCCESS(status)) {
6286 hdd_err("P2P LO stop failed");
6287 return -EINVAL;
6288 }
6289
6290 return 0;
6291}
6292
6293/**
6294 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6295 * @wiphy: Pointer to wireless phy
6296 * @wdev: Pointer to wireless device
6297 * @data: Pointer to data
6298 * @data_len: Data length
6299 *
6300 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6301 * to process p2p listen offload stop vendor command.
6302 *
6303 * Return: 0 on success, negative errno on failure
6304 */
6305static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6306 struct wireless_dev *wdev,
6307 const void *data,
6308 int data_len)
6309{
6310 int ret = 0;
6311
6312 cds_ssr_protect(__func__);
6313 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6314 data, data_len);
6315 cds_ssr_unprotect(__func__);
6316
6317 return ret;
6318}
6319
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306320/**
6321 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6322 * @wiphy: Pointer to wireless phy
6323 * @wdev: Pointer to wireless device
6324 * @data: Pointer to data
6325 * @data_len: Data length
6326 *
6327 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6328 * to process the conditional channel switch request.
6329 *
6330 * Return: 0 on success, negative errno on failure
6331 */
6332static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6333 struct wireless_dev *wdev,
6334 const void *data,
6335 int data_len)
6336{
6337 int ret;
6338
6339 cds_ssr_protect(__func__);
6340 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6341 data, data_len);
6342 cds_ssr_unprotect(__func__);
6343
6344 return ret;
6345}
6346
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306347/*
6348 * define short names for the global vendor params
6349 * used by __wlan_hdd_cfg80211_bpf_offload()
6350 */
6351#define BPF_INVALID \
6352 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6353#define BPF_SET_RESET \
6354 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6355#define BPF_VERSION \
6356 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6357#define BPF_FILTER_ID \
6358 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6359#define BPF_PACKET_SIZE \
6360 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6361#define BPF_CURRENT_OFFSET \
6362 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6363#define BPF_PROGRAM \
6364 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6365#define BPF_MAX \
6366 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006367
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306368static const struct nla_policy
6369wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6370 [BPF_SET_RESET] = {.type = NLA_U32},
6371 [BPF_VERSION] = {.type = NLA_U32},
6372 [BPF_FILTER_ID] = {.type = NLA_U32},
6373 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6374 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6375 [BPF_PROGRAM] = {.type = NLA_U8},
6376};
6377
6378/**
6379 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6380 * @hdd_context: hdd_context
6381 * @bpf_get_offload: struct for get offload
6382 *
6383 * This function receives the response/data from the lower layer and
6384 * checks to see if the thread is still waiting then post the results to
6385 * upper layer, if the request has timed out then ignore.
6386 *
6387 * Return: None
6388 */
6389void hdd_get_bpf_offload_cb(void *hdd_context,
6390 struct sir_bpf_get_offload *data)
6391{
6392 hdd_context_t *hdd_ctx = hdd_context;
6393 struct hdd_bpf_context *context;
6394
6395 ENTER();
6396
6397 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006398 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306399 data);
6400 return;
6401 }
6402
6403 spin_lock(&hdd_context_lock);
6404
6405 context = &bpf_context;
6406 /* The caller presumably timed out so there is nothing we can do */
6407 if (context->magic != BPF_CONTEXT_MAGIC) {
6408 spin_unlock(&hdd_context_lock);
6409 return;
6410 }
6411
6412 /* context is valid so caller is still waiting */
6413 /* paranoia: invalidate the magic */
6414 context->magic = 0;
6415
6416 context->capability_response = *data;
6417 complete(&context->completion);
6418
6419 spin_unlock(&hdd_context_lock);
6420
6421 return;
6422}
6423
6424/**
6425 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6426 * @hdd_context: hdd_context
6427 * @bpf_get_offload: struct for get offload
6428 *
6429 * Return: 0 on success, error number otherwise.
6430 */
6431static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6432 struct sir_bpf_get_offload *bpf_get_offload)
6433{
6434 struct sk_buff *skb;
6435 uint32_t nl_buf_len;
6436
6437 ENTER();
6438
6439 nl_buf_len = NLMSG_HDRLEN;
6440 nl_buf_len +=
6441 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6442 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6443
6444 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6445 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006446 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306447 return -ENOMEM;
6448 }
6449
Jeff Johnson77848112016-06-29 14:52:06 -07006450 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306451 bpf_get_offload->bpf_version,
6452 bpf_get_offload->max_bytes_for_bpf_inst);
6453
6454 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6455 bpf_get_offload->max_bytes_for_bpf_inst) ||
6456 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006457 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306458 goto nla_put_failure;
6459 }
6460
6461 cfg80211_vendor_cmd_reply(skb);
6462 EXIT();
6463 return 0;
6464
6465nla_put_failure:
6466 kfree_skb(skb);
6467 return -EINVAL;
6468}
6469
6470/**
6471 * hdd_get_bpf_offload - Get BPF offload Capabilities
6472 * @hdd_ctx: Hdd context
6473 *
6474 * Return: 0 on success, errno on failure
6475 */
6476static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6477{
6478 unsigned long rc;
Houston Hoffman59c097f2016-11-09 15:50:25 -08006479 static struct hdd_bpf_context *context;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306480 QDF_STATUS status;
6481 int ret;
6482
6483 ENTER();
6484
6485 spin_lock(&hdd_context_lock);
6486 context = &bpf_context;
6487 context->magic = BPF_CONTEXT_MAGIC;
6488 INIT_COMPLETION(context->completion);
6489 spin_unlock(&hdd_context_lock);
6490
6491 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6492 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006493 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306494 return -EINVAL;
6495 }
6496 /* request was sent -- wait for the response */
6497 rc = wait_for_completion_timeout(&context->completion,
6498 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6499 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006500 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306501 spin_lock(&hdd_context_lock);
6502 context->magic = 0;
6503 spin_unlock(&hdd_context_lock);
6504
6505 return -ETIMEDOUT;
6506 }
6507 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6508 &bpf_context.capability_response);
6509 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006510 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306511
6512 EXIT();
6513 return ret;
6514}
6515
6516/**
6517 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6518 * @hdd_ctx: Hdd context
6519 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306520 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306521 *
6522 * Return: 0 on success; errno on failure
6523 */
6524static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6525 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306526 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306527{
6528 struct sir_bpf_set_offload *bpf_set_offload;
6529 QDF_STATUS status;
6530 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306531 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306532
6533 ENTER();
6534
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306535 if (adapter->device_mode == QDF_STA_MODE ||
6536 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6537 if (!hdd_conn_is_connected(
6538 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6539 hdd_err("Not in Connected state!");
6540 return -ENOTSUPP;
6541 }
6542 }
6543
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306544 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6545 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006546 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306547 return -ENOMEM;
6548 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306549
6550 /* Parse and fetch bpf packet size */
6551 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006552 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306553 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306554 goto fail;
6555 }
6556 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6557
6558 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006559 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306560 goto post_sme;
6561 }
6562
6563 /* Parse and fetch bpf program */
6564 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006565 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306566 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306567 goto fail;
6568 }
6569
6570 prog_len = nla_len(tb[BPF_PROGRAM]);
6571 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306572
6573 if (bpf_set_offload->program == NULL) {
6574 hdd_err("qdf_mem_malloc failed for bpf offload program");
6575 ret = -ENOMEM;
6576 goto fail;
6577 }
6578
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306579 bpf_set_offload->current_length = prog_len;
6580 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306581 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306582
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306583 hdd_info("BPF set instructions");
6584 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6585 bpf_set_offload->program, prog_len);
6586
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306587 /* Parse and fetch filter Id */
6588 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006589 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306590 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306591 goto fail;
6592 }
6593 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6594
6595 /* Parse and fetch current offset */
6596 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006597 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306598 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306599 goto fail;
6600 }
6601 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6602
6603post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006604 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 +05306605 bpf_set_offload->session_id,
6606 bpf_set_offload->version,
6607 bpf_set_offload->filter_id,
6608 bpf_set_offload->total_length,
6609 bpf_set_offload->current_length,
6610 bpf_set_offload->current_offset);
6611
6612 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6613 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006614 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306615 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306616 goto fail;
6617 }
6618 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306619
6620fail:
6621 if (bpf_set_offload->current_length)
6622 qdf_mem_free(bpf_set_offload->program);
6623 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306624 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306625}
6626
6627/**
6628 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6629 * @wiphy: wiphy structure pointer
6630 * @wdev: Wireless device structure pointer
6631 * @data: Pointer to the data received
6632 * @data_len: Length of @data
6633 *
6634 * Return: 0 on success; errno on failure
6635 */
6636static int
6637__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6638 struct wireless_dev *wdev,
6639 const void *data, int data_len)
6640{
6641 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6642 struct net_device *dev = wdev->netdev;
6643 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6644 struct nlattr *tb[BPF_MAX + 1];
6645 int ret_val, packet_filter_subcmd;
6646
6647 ENTER();
6648
6649 ret_val = wlan_hdd_validate_context(hdd_ctx);
6650 if (ret_val)
6651 return ret_val;
6652
6653 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006654 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306655 return -EINVAL;
6656 }
6657
6658 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006659 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306660 return -ENOTSUPP;
6661 }
6662
6663 if (nla_parse(tb, BPF_MAX, data, data_len,
6664 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006665 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306666 return -EINVAL;
6667 }
6668
6669 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006670 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306671 return -EINVAL;
6672 }
6673
6674 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6675
6676 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6677 return hdd_get_bpf_offload(hdd_ctx);
6678 else
6679 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306680 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306681}
6682
6683/**
6684 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6685 * @wiphy: wiphy structure pointer
6686 * @wdev: Wireless device structure pointer
6687 * @data: Pointer to the data received
6688 * @data_len: Length of @data
6689 *
6690 * Return: 0 on success; errno on failure
6691 */
6692
6693static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6694 struct wireless_dev *wdev,
6695 const void *data, int data_len)
6696{
6697 int ret;
6698
6699 cds_ssr_protect(__func__);
6700 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6701 cds_ssr_unprotect(__func__);
6702
6703 return ret;
6704}
6705
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306706/**
6707 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6708 * @pre_cac_adapter: AP adapter used for pre cac
6709 * @status: Status (true or false)
6710 * @handle: Global handle
6711 *
6712 * Sets the status of pre cac i.e., whether the pre cac is active or not
6713 *
6714 * Return: Zero on success, non-zero on failure
6715 */
6716static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6717 bool status, tHalHandle handle)
6718{
6719 QDF_STATUS ret;
6720
6721 ret = wlan_sap_set_pre_cac_status(
6722 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6723 if (QDF_IS_STATUS_ERROR(ret))
6724 return -EINVAL;
6725
6726 return 0;
6727}
6728
6729/**
6730 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6731 * @ap_adapter: AP adapter
6732 * @chan_before_pre_cac: Channel
6733 *
6734 * Saves the channel which the AP was beaconing on before moving to the pre
6735 * cac channel. If radar is detected on the pre cac channel, this saved
6736 * channel will be used for AP operations.
6737 *
6738 * Return: Zero on success, non-zero on failure
6739 */
6740static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6741 uint8_t chan_before_pre_cac)
6742{
6743 QDF_STATUS ret;
6744
6745 ret = wlan_sap_set_chan_before_pre_cac(
6746 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6747 if (QDF_IS_STATUS_ERROR(ret))
6748 return -EINVAL;
6749
6750 return 0;
6751}
6752
6753/**
6754 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6755 * @ap_adapter: AP adapter
6756 * @nol: Non-occupancy list
6757 * @nol_len: Length of NOL
6758 *
6759 * Get the NOL for SAP
6760 *
6761 * Return: Zero on success, non-zero on failure
6762 */
6763static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6764 uint32_t *nol_len)
6765{
6766 QDF_STATUS ret;
6767
6768 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6769 nol, nol_len);
6770 if (QDF_IS_STATUS_ERROR(ret))
6771 return -EINVAL;
6772
6773 return 0;
6774}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306775
6776/**
6777 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6778 * @hdd_ctx: HDD context
6779 * @ap_adapter: AP adapter
6780 * @channel: Channel requested by userspace
6781 * @pre_cac_chan: Pointer to the pre CAC channel
6782 *
6783 * Validates the channel provided by userspace. If user provided channel 0,
6784 * a valid outdoor channel must be selected from the regulatory channel.
6785 *
6786 * Return: Zero on success and non zero value on error
6787 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006788static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6789 hdd_adapter_t *ap_adapter,
6790 uint8_t channel,
6791 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306792{
6793 uint32_t i, j;
6794 QDF_STATUS status;
6795 int ret;
6796 uint8_t nol[QDF_MAX_NUM_CHAN];
6797 uint32_t nol_len = 0, weight_len = 0;
6798 bool found;
6799 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6800 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6801 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6802
6803 if (0 == channel) {
6804 /* Channel is not obtained from PCL because PCL may not have
6805 * the entire channel list. For example: if SAP is up on
6806 * channel 6 and PCL is queried for the next SAP interface,
6807 * if SCC is preferred, the PCL will contain only the channel
6808 * 6. But, we are in need of a DFS channel. So, going with the
6809 * first channel from the valid channel list.
6810 */
6811 status = cds_get_valid_chans(channel_list, &len);
6812 if (QDF_IS_STATUS_ERROR(status)) {
6813 hdd_err("Failed to get channel list");
6814 return -EINVAL;
6815 }
6816 cds_update_with_safe_channel_list(channel_list, &len,
6817 pcl_weights, weight_len);
6818 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6819 for (i = 0; i < len; i++) {
6820 found = false;
6821 for (j = 0; j < nol_len; j++) {
6822 if (channel_list[i] == nol[j]) {
6823 found = true;
6824 break;
6825 }
6826 }
6827 if (found)
6828 continue;
6829 if (CDS_IS_DFS_CH(channel_list[i])) {
6830 *pre_cac_chan = channel_list[i];
6831 break;
6832 }
6833 }
6834 if (*pre_cac_chan == 0) {
6835 hdd_err("unable to find outdoor channel");
6836 return -EINVAL;
6837 }
6838 } else {
6839 /* Only when driver selects a channel, check is done for
6840 * unnsafe and NOL channels. When user provides a fixed channel
6841 * the user is expected to take care of this.
6842 */
6843 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6844 !CDS_IS_DFS_CH(channel)) {
6845 hdd_err("Invalid channel for pre cac:%d", channel);
6846 return -EINVAL;
6847 } else {
6848 *pre_cac_chan = channel;
6849 }
6850 }
6851 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6852 return 0;
6853}
6854
6855/**
6856 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6857 * @channel: Channel option provided by userspace
6858 *
6859 * Sets the driver to the required hardware mode and start an adapater for
6860 * pre CAC which will mimic an AP.
6861 *
6862 * Return: Zero on success, non-zero value on error
6863 */
6864int wlan_hdd_request_pre_cac(uint8_t channel)
6865{
Krunal Sonib37bb352016-12-20 14:12:21 -08006866 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306867 hdd_context_t *hdd_ctx;
6868 int ret;
6869 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6870 hdd_ap_ctx_t *hdd_ap_ctx;
6871 QDF_STATUS status;
6872 struct wiphy *wiphy;
6873 struct net_device *dev;
6874 struct cfg80211_chan_def chandef;
6875 enum nl80211_channel_type channel_type;
6876 uint32_t freq;
6877 struct ieee80211_channel *chan;
6878 tHalHandle handle;
6879 bool val;
6880
6881 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6882 if (0 != wlan_hdd_validate_context(hdd_ctx))
6883 return -EINVAL;
6884
6885 if (cds_get_connection_count() > 1) {
6886 hdd_err("pre cac not allowed in concurrency");
6887 return -EINVAL;
6888 }
6889
6890 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6891 if (!ap_adapter) {
6892 hdd_err("unable to get SAP adapter");
6893 return -EINVAL;
6894 }
6895
6896 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6897 if (!handle) {
6898 hdd_err("Invalid handle");
6899 return -EINVAL;
6900 }
6901
6902 val = wlan_sap_is_pre_cac_active(handle);
6903 if (val) {
6904 hdd_err("pre cac is already in progress");
6905 return -EINVAL;
6906 }
6907
6908 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6909 if (!hdd_ap_ctx) {
6910 hdd_err("SAP context is NULL");
6911 return -EINVAL;
6912 }
6913
6914 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6915 hdd_err("SAP is already on DFS channel:%d",
6916 hdd_ap_ctx->operatingChannel);
6917 return -EINVAL;
6918 }
6919
6920 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6921 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6922 hdd_ap_ctx->operatingChannel);
6923 return -EINVAL;
6924 }
6925
Krunal Sonib37bb352016-12-20 14:12:21 -08006926 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6927 if (!mac_addr) {
6928 hdd_err("can't add virtual intf: Not getting valid mac addr");
6929 return -EINVAL;
6930 }
6931
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306932 hdd_info("channel:%d", channel);
6933
6934 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6935 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08006936 if (ret != 0) {
6937 hdd_err("can't validate pre-cac channel");
6938 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306939 }
6940
6941 hdd_debug("starting pre cac SAP adapter");
6942
6943 /* Starting a SAP adapter:
6944 * Instead of opening an adapter, we could just do a SME open session
6945 * for AP type. But, start BSS would still need an adapter.
6946 * So, this option is not taken.
6947 *
6948 * hdd open adapter is going to register this precac interface with
6949 * user space. This interface though exposed to user space will be in
6950 * DOWN state. Consideration was done to avoid this registration to the
6951 * user space. But, as part of SAP operations multiple events are sent
6952 * to user space. Some of these events received from unregistered
6953 * interface was causing crashes. So, retaining the registration.
6954 *
6955 * So, this interface would remain registered and will remain in DOWN
6956 * state for the CAC duration. We will add notes in the feature
6957 * announcement to not use this temporary interface for any activity
6958 * from user space.
6959 */
6960 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08006961 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306962 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306963 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08006964 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306965 }
6966
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306967 /*
6968 * This interface is internally created by the driver. So, no interface
6969 * up comes for this interface from user space and hence starting
6970 * the adapter internally.
6971 */
6972 if (hdd_start_adapter(pre_cac_adapter)) {
6973 hdd_err("error starting the pre cac adapter");
6974 goto close_pre_cac_adapter;
6975 }
6976
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306977 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6978
6979 wiphy = hdd_ctx->wiphy;
6980 dev = pre_cac_adapter->dev;
6981
6982 /* Since this is only a dummy interface lets us use the IEs from the
6983 * other active SAP interface. In regular scenarios, these IEs would
6984 * come from the user space entity
6985 */
6986 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6987 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6988 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6989 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306990 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306991 }
6992 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6993 ap_adapter->sessionCtx.ap.beacon,
6994 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6995 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6996 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6997 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6998 ap_adapter->sessionCtx.ap.sapConfig.authType;
6999
7000 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7001 * to operate on the same bandwidth as that of the 2.4GHz operations.
7002 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7003 */
7004 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7005 case CH_WIDTH_20MHZ:
7006 channel_type = NL80211_CHAN_HT20;
7007 break;
7008 case CH_WIDTH_40MHZ:
7009 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7010 ap_adapter->sessionCtx.ap.sapConfig.channel)
7011 channel_type = NL80211_CHAN_HT40PLUS;
7012 else
7013 channel_type = NL80211_CHAN_HT40MINUS;
7014 break;
7015 default:
7016 channel_type = NL80211_CHAN_NO_HT;
7017 break;
7018 }
7019
7020 freq = cds_chan_to_freq(pre_cac_chan);
7021 chan = __ieee80211_get_channel(wiphy, freq);
7022 if (!chan) {
7023 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307024 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307025 }
7026
7027 cfg80211_chandef_create(&chandef, chan, channel_type);
7028
7029 hdd_debug("orig width:%d channel_type:%d freq:%d",
7030 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7031 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007032 /*
7033 * Doing update after opening and starting pre-cac adapter will make
7034 * sure that driver won't do hardware mode change if there are any
7035 * initial hick-ups or issues in pre-cac adapter's configuration.
7036 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7037 * connection update should result in DBS mode
7038 */
7039 status = cds_update_and_wait_for_connection_update(
7040 ap_adapter->sessionId,
7041 pre_cac_chan,
7042 SIR_UPDATE_REASON_PRE_CAC);
7043 if (QDF_IS_STATUS_ERROR(status)) {
7044 hdd_err("error in moving to DBS mode");
7045 goto stop_close_pre_cac_adapter;
7046 }
7047
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307048
7049 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7050 if (0 != ret) {
7051 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307052 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307053 }
7054
7055 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7056 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007057 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307058 if (QDF_IS_STATUS_ERROR(status)) {
7059 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307060 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307061 }
7062
7063 /*
7064 * The pre cac status is set here. But, it would not be reset explicitly
7065 * anywhere, since after the pre cac success/failure, the pre cac
7066 * adapter itself would be removed.
7067 */
7068 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7069 if (0 != ret) {
7070 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307071 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307072 }
7073
7074 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7075 hdd_ap_ctx->operatingChannel);
7076 if (0 != ret) {
7077 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307078 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307079 }
7080
7081 ap_adapter->pre_cac_chan = pre_cac_chan;
7082
7083 return 0;
7084
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307085stop_close_pre_cac_adapter:
7086 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307087 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7088 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307089close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307090 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007091release_intf_addr_and_return_failure:
7092 /*
7093 * Release the interface address as the adapter
7094 * failed to start, if you don't release then next
7095 * adapter which is trying to come wouldn't get valid
7096 * mac address. Remember we have limited pool of mac addresses
7097 */
7098 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307099 return -EINVAL;
7100}
7101
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307102/**
7103 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7104 *
7105 * Return: None
7106 */
7107void hdd_init_bpf_completion(void)
7108{
7109 init_completion(&bpf_context.completion);
7110}
7111
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307112static const struct nla_policy
7113wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7114 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7115};
7116
Agrawal Ashish65634612016-08-18 13:24:32 +05307117static const struct nla_policy
7118wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7119 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7120 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7121};
7122
7123/**
7124 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7125 * @wiphy: Pointer to wireless phy
7126 * @wdev: Pointer to wireless device
7127 * @data: Pointer to data
7128 * @data_len: Length of @data
7129 *
7130 * This function parses the incoming NL vendor command data attributes and
7131 * updates the SAP context about channel_hint and DFS mode.
7132 * If channel_hint is set, SAP will choose that channel
7133 * as operating channel.
7134 *
7135 * If DFS mode is enabled, driver will include DFS channels
7136 * in ACS else driver will skip DFS channels.
7137 *
7138 * Return: 0 on success, negative errno on failure
7139 */
7140static int
7141__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7142 struct wireless_dev *wdev,
7143 const void *data, int data_len)
7144{
7145 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7146 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7147 int ret;
7148 struct acs_dfs_policy *acs_policy;
7149 int mode = DFS_MODE_NONE;
7150 int channel_hint = 0;
7151
7152 ENTER_DEV(wdev->netdev);
7153
7154 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7155 hdd_err("Command not allowed in FTM mode");
7156 return -EINVAL;
7157 }
7158
7159 ret = wlan_hdd_validate_context(hdd_ctx);
7160 if (0 != ret)
7161 return ret;
7162
7163 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7164 data, data_len,
7165 wlan_hdd_set_acs_dfs_config_policy)) {
7166 hdd_err("invalid attr");
7167 return -EINVAL;
7168 }
7169
7170 acs_policy = &hdd_ctx->acs_policy;
7171 /*
7172 * SCM sends this attribute to restrict SAP from choosing
7173 * DFS channels from ACS.
7174 */
7175 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7176 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7177
7178 if (!IS_DFS_MODE_VALID(mode)) {
7179 hdd_err("attr acs dfs mode is not valid");
7180 return -EINVAL;
7181 }
7182 acs_policy->acs_dfs_mode = mode;
7183
7184 /*
7185 * SCM sends this attribute to provide an active channel,
7186 * to skip redundant ACS between drivers, and save driver start up time
7187 */
7188 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7189 channel_hint = nla_get_u8(
7190 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7191
7192 if (!IS_CHANNEL_VALID(channel_hint)) {
7193 hdd_err("acs channel is not valid");
7194 return -EINVAL;
7195 }
7196 acs_policy->acs_channel = channel_hint;
7197
7198 return 0;
7199}
7200
7201/**
7202 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7203 * @wiphy: wiphy structure pointer
7204 * @wdev: Wireless device structure pointer
7205 * @data: Pointer to the data received
7206 * @data_len: Length of @data
7207 *
7208 * This function parses the incoming NL vendor command data attributes and
7209 * updates the SAP context about channel_hint and DFS mode.
7210 *
7211 * Return: 0 on success; errno on failure
7212 */
7213static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7214 struct wireless_dev *wdev,
7215 const void *data, int data_len)
7216{
7217 int ret;
7218
7219 cds_ssr_protect(__func__);
7220 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7221 cds_ssr_unprotect(__func__);
7222
7223 return ret;
7224}
7225
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307226/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307227 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7228 * @mode : cfg80211 dfs mode
7229 *
7230 * Return: return csr sta roam dfs mode else return NONE
7231 */
7232static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7233 enum dfs_mode mode)
7234{
7235 switch (mode) {
7236 case DFS_MODE_ENABLE:
7237 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7238 break;
7239 case DFS_MODE_DISABLE:
7240 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7241 break;
7242 case DFS_MODE_DEPRIORITIZE:
7243 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7244 break;
7245 default:
7246 hdd_err("STA Roam policy dfs mode is NONE");
7247 return CSR_STA_ROAM_POLICY_NONE;
7248 }
7249}
7250
7251static const struct nla_policy
7252wlan_hdd_set_sta_roam_config_policy[
7253QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7254 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7255 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7256};
7257
7258/**
7259 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7260 * for station connection or roaming.
7261 * @wiphy: Pointer to wireless phy
7262 * @wdev: Pointer to wireless device
7263 * @data: Pointer to data
7264 * @data_len: Length of @data
7265 *
7266 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7267 * channels needs to be skipped in scanning or not.
7268 * If dfs_mode is disabled, driver will not scan DFS channels.
7269 * If skip_unsafe_channels is set, driver will skip unsafe channels
7270 * in Scanning.
7271 *
7272 * Return: 0 on success, negative errno on failure
7273 */
7274static int
7275__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7276 struct wireless_dev *wdev,
7277 const void *data, int data_len)
7278{
7279 struct net_device *dev = wdev->netdev;
7280 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7281 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7282 struct nlattr *tb[
7283 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7284 int ret;
7285 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7286 enum dfs_mode mode = DFS_MODE_NONE;
7287 bool skip_unsafe_channels = false;
7288 QDF_STATUS status;
7289
7290 ENTER_DEV(dev);
7291
7292 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7293 hdd_err("Command not allowed in FTM mode");
7294 return -EINVAL;
7295 }
7296
7297 ret = wlan_hdd_validate_context(hdd_ctx);
7298 if (0 != ret)
7299 return ret;
7300 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7301 data, data_len,
7302 wlan_hdd_set_sta_roam_config_policy)) {
7303 hdd_err("invalid attr");
7304 return -EINVAL;
7305 }
7306 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7307 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7308 if (!IS_DFS_MODE_VALID(mode)) {
7309 hdd_err("attr sta roam dfs mode policy is not valid");
7310 return -EINVAL;
7311 }
7312
7313 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7314
7315 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7316 skip_unsafe_channels = nla_get_u8(
7317 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7318
7319 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7320 skip_unsafe_channels, adapter->sessionId);
7321
7322 if (!QDF_IS_STATUS_SUCCESS(status)) {
7323 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7324 return -EINVAL;
7325 }
7326 return 0;
7327}
7328
7329/**
7330 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7331 * connection and roaming for station.
7332 * @wiphy: wiphy structure pointer
7333 * @wdev: Wireless device structure pointer
7334 * @data: Pointer to the data received
7335 * @data_len: Length of @data
7336 *
7337 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7338 * channels needs to be skipped in scanning or not.
7339 * If dfs_mode is disabled, driver will not scan DFS channels.
7340 * If skip_unsafe_channels is set, driver will skip unsafe channels
7341 * in Scanning.
7342 * Return: 0 on success; errno on failure
7343 */
7344static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7345 struct wireless_dev *wdev,
7346 const void *data, int data_len)
7347{
7348 int ret;
7349
7350 cds_ssr_protect(__func__);
7351 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7352 cds_ssr_unprotect(__func__);
7353
7354 return ret;
7355}
7356
Agrawal Ashish467dde42016-09-08 18:44:22 +05307357#ifdef FEATURE_WLAN_CH_AVOID
7358/**
7359 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7360 * is on unsafe channel.
7361 * @wiphy: wiphy structure pointer
7362 * @wdev: Wireless device structure pointer
7363 * @data: Pointer to the data received
7364 * @data_len: Length of @data
7365 *
7366 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7367 * on any of unsafe channels.
7368 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7369 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7370 *
7371 * Return: 0 on success; errno on failure
7372 */
7373static int
7374__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7375 struct wireless_dev *wdev,
7376 const void *data, int data_len)
7377{
7378 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7379 int ret;
7380 uint16_t unsafe_channel_count;
7381 int unsafe_channel_index;
7382 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7383
7384 ENTER_DEV(wdev->netdev);
7385
7386 if (!qdf_ctx) {
7387 cds_err("qdf_ctx is NULL");
7388 return -EINVAL;
7389 }
7390
7391 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7392 hdd_err("Command not allowed in FTM mode");
7393 return -EINVAL;
7394 }
7395
7396 ret = wlan_hdd_validate_context(hdd_ctx);
7397 if (0 != ret)
7398 return ret;
7399 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7400 &(hdd_ctx->unsafe_channel_count),
7401 sizeof(hdd_ctx->unsafe_channel_list));
7402
7403 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7404 (uint16_t)NUM_CHANNELS);
7405 for (unsafe_channel_index = 0;
7406 unsafe_channel_index < unsafe_channel_count;
7407 unsafe_channel_index++) {
7408 hdd_info("Channel %d is not safe",
7409 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7410 }
7411 hdd_unsafe_channel_restart_sap(hdd_ctx);
7412 return 0;
7413}
7414
7415/**
7416 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7417 * is on unsafe channel.
7418 * @wiphy: wiphy structure pointer
7419 * @wdev: Wireless device structure pointer
7420 * @data: Pointer to the data received
7421 * @data_len: Length of @data
7422 *
7423 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7424 * on any of unsafe channels.
7425 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7426 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7427 *
7428 * Return: 0 on success; errno on failure
7429 */
7430static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7431 struct wireless_dev *wdev,
7432 const void *data, int data_len)
7433{
7434 int ret;
7435
7436 cds_ssr_protect(__func__);
7437 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7438 cds_ssr_unprotect(__func__);
7439
7440 return ret;
7441}
7442
7443#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307444/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307445 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7446 * SAP is on unsafe channel.
7447 * @wiphy: wiphy structure pointer
7448 * @wdev: Wireless device structure pointer
7449 * @data: Pointer to the data received
7450 * @data_len: Length of @data
7451 *
7452 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7453 * driver.
7454 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7455 * will initiate restart of sap.
7456 *
7457 * Return: 0 on success; errno on failure
7458 */
7459static int
7460__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7461 struct wireless_dev *wdev,
7462 const void *data, int data_len)
7463{
7464 struct net_device *ndev = wdev->netdev;
7465 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7466 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7467 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7468 uint8_t config_channel = 0;
7469 hdd_ap_ctx_t *ap_ctx;
7470 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307471 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307472
7473 ENTER();
7474
7475 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007476 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307477 return -EINVAL;
7478 }
7479
7480 ret = wlan_hdd_validate_context(hdd_ctx);
7481 if (0 != ret)
7482 return -EINVAL;
7483
7484 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7485 data, data_len,
7486 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007487 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307488 return -EINVAL;
7489 }
7490
7491 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7492 if (!test_bit(SOFTAP_BSS_STARTED,
7493 &hostapd_adapter->event_flags)) {
7494 hdd_err("SAP is not started yet. Restart sap will be invalid");
7495 return -EINVAL;
7496 }
7497
7498 config_channel =
7499 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7500
7501 if (!((IS_24G_CH(config_channel)) ||
7502 (IS_5G_CH(config_channel)))) {
7503 hdd_err("Channel %d is not valid to restart SAP",
7504 config_channel);
7505 return -ENOTSUPP;
7506 }
7507
7508 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7509 ap_ctx->sapConfig.channel = config_channel;
7510 ap_ctx->sapConfig.ch_params.ch_width =
7511 ap_ctx->sapConfig.ch_width_orig;
7512
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007513 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307514 ap_ctx->sapConfig.sec_ch,
7515 &ap_ctx->sapConfig.ch_params);
7516
7517 cds_restart_sap(hostapd_adapter);
7518 }
7519
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307520 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7521 uint32_t freq_len, i;
7522 uint32_t *freq;
7523 uint8_t chans[QDF_MAX_NUM_CHAN];
7524
7525 hdd_debug("setting mandatory freq/chan list");
7526
7527 freq_len = nla_len(
7528 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7529 sizeof(uint32_t);
7530
7531 if (freq_len > QDF_MAX_NUM_CHAN) {
7532 hdd_err("insufficient space to hold channels");
7533 return -ENOMEM;
7534 }
7535
7536 freq = nla_data(
7537 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7538
7539 hdd_debug("freq_len=%d", freq_len);
7540
7541 for (i = 0; i < freq_len; i++) {
7542 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7543 hdd_debug("freq[%d]=%d", i, freq[i]);
7544 }
7545
7546 status = cds_set_sap_mandatory_channels(chans, freq_len);
7547 if (QDF_IS_STATUS_ERROR(status))
7548 return -EINVAL;
7549 }
7550
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307551 return 0;
7552}
7553
7554/**
7555 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7556 * @wiphy: wiphy structure pointer
7557 * @wdev: Wireless device structure pointer
7558 * @data: Pointer to the data received
7559 * @data_len: Length of @data
7560 *
7561 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7562 * driver.
7563 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7564 * will initiate restart of sap.
7565 *
7566 * Return: 0 on success; errno on failure
7567 */
7568static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7569 struct wireless_dev *wdev,
7570 const void *data, int data_len)
7571{
7572 int ret;
7573
7574 cds_ssr_protect(__func__);
7575 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7576 wdev, data, data_len);
7577 cds_ssr_unprotect(__func__);
7578
7579 return ret;
7580}
7581
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307582#undef BPF_INVALID
7583#undef BPF_SET_RESET
7584#undef BPF_VERSION
7585#undef BPF_ID
7586#undef BPF_PACKET_SIZE
7587#undef BPF_CURRENT_OFFSET
7588#undef BPF_PROGRAM
7589#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307590
7591/**
7592 * define short names for the global vendor params
7593 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7594 */
7595#define PARAM_TOTAL_CMD_EVENT_WAKE \
7596 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7597#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7598 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7599#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7600 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7601#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7602 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7603#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7604 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7605#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7606 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7607#define PARAM_TOTAL_RX_DATA_WAKE \
7608 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7609#define PARAM_RX_UNICAST_CNT \
7610 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7611#define PARAM_RX_MULTICAST_CNT \
7612 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7613#define PARAM_RX_BROADCAST_CNT \
7614 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7615#define PARAM_ICMP_PKT \
7616 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7617#define PARAM_ICMP6_PKT \
7618 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7619#define PARAM_ICMP6_RA \
7620 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7621#define PARAM_ICMP6_NA \
7622 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7623#define PARAM_ICMP6_NS \
7624 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7625#define PARAM_ICMP4_RX_MULTICAST_CNT \
7626 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7627#define PARAM_ICMP6_RX_MULTICAST_CNT \
7628 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7629#define PARAM_OTHER_RX_MULTICAST_CNT \
7630 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307631#define PARAM_RSSI_BREACH_CNT \
7632 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
7633#define PARAM_LOW_RSSI_CNT \
7634 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
7635#define PARAM_GSCAN_CNT \
7636 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
7637#define PARAM_PNO_COMPLETE_CNT \
7638 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
7639#define PARAM_PNO_MATCH_CNT \
7640 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
7641
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307642
7643
7644/**
7645 * hdd_send_wakelock_stats() - API to send wakelock stats
7646 * @ctx: context to be passed to callback
7647 * @data: data passed to callback
7648 *
7649 * This function is used to send wake lock stats to HAL layer
7650 *
7651 * Return: 0 on success, error number otherwise.
7652 */
7653static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7654 const struct sir_wake_lock_stats *data)
7655{
7656 struct sk_buff *skb;
7657 uint32_t nl_buf_len;
7658 uint32_t total_rx_data_wake, rx_multicast_cnt;
7659 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307660 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307661
7662 ENTER();
7663
7664 nl_buf_len = NLMSG_HDRLEN;
7665 nl_buf_len +=
7666 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7667 (NLMSG_HDRLEN + sizeof(uint32_t));
7668
7669 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7670
7671 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007672 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307673 return -ENOMEM;
7674 }
7675
Jeff Johnson64943bd2016-08-23 13:14:06 -07007676 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307677 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007678 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307679 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007680 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307681 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007682 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307683 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007684 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307685 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007686 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307687 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007688 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307689 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007690 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7691 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307692 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307693 hdd_info("wow_rssi_breach_wake_up_count %d",
7694 data->wow_rssi_breach_wake_up_count);
7695 hdd_info("wow_low_rssi_wake_up_count %d",
7696 data->wow_low_rssi_wake_up_count);
7697 hdd_info("wow_gscan_wake_up_count %d",
7698 data->wow_gscan_wake_up_count);
7699 hdd_info("wow_pno_complete_wake_up_count %d",
7700 data->wow_pno_complete_wake_up_count);
7701 hdd_info("wow_pno_match_wake_up_count %d",
7702 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307703
7704 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307705 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307706
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307707 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307708 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307709
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307710 rx_multicast_cnt =
7711 data->wow_ipv4_mcast_wake_up_count +
7712 ipv6_rx_multicast_addr_cnt;
7713
7714 total_rx_data_wake =
7715 data->wow_ucast_wake_up_count +
7716 data->wow_bcast_wake_up_count +
7717 rx_multicast_cnt;
7718
7719 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7720 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7721 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7722 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7723 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7724 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7725 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7726 total_rx_data_wake) ||
7727 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7728 data->wow_ucast_wake_up_count) ||
7729 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7730 rx_multicast_cnt) ||
7731 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7732 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307733 nla_put_u32(skb, PARAM_ICMP_PKT,
7734 data->wow_icmpv4_count) ||
7735 nla_put_u32(skb, PARAM_ICMP6_PKT,
7736 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307737 nla_put_u32(skb, PARAM_ICMP6_RA,
7738 data->wow_ipv6_mcast_ra_stats) ||
7739 nla_put_u32(skb, PARAM_ICMP6_NA,
7740 data->wow_ipv6_mcast_na_stats) ||
7741 nla_put_u32(skb, PARAM_ICMP6_NS,
7742 data->wow_ipv6_mcast_ns_stats) ||
7743 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7744 data->wow_ipv4_mcast_wake_up_count) ||
7745 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7746 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307747 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
7748 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
7749 data->wow_rssi_breach_wake_up_count) ||
7750 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
7751 data->wow_low_rssi_wake_up_count) ||
7752 nla_put_u32(skb, PARAM_GSCAN_CNT,
7753 data->wow_gscan_wake_up_count) ||
7754 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
7755 data->wow_pno_complete_wake_up_count) ||
7756 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
7757 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007758 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307759 goto nla_put_failure;
7760 }
7761
7762 cfg80211_vendor_cmd_reply(skb);
7763
7764 EXIT();
7765 return 0;
7766
7767nla_put_failure:
7768 kfree_skb(skb);
7769 return -EINVAL;
7770}
7771
7772/**
7773 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7774 * @wiphy: wiphy pointer
7775 * @wdev: pointer to struct wireless_dev
7776 * @data: pointer to incoming NL vendor data
7777 * @data_len: length of @data
7778 *
7779 * This function parses the incoming NL vendor command data attributes and
7780 * invokes the SME Api and blocks on a completion variable.
7781 * WMA copies required data and invokes callback
7782 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7783 *
7784 * Return: 0 on success; error number otherwise.
7785 */
7786static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7787 struct wireless_dev *wdev,
7788 const void *data,
7789 int data_len)
7790{
7791 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7792 int status, ret;
7793 struct sir_wake_lock_stats wake_lock_stats;
7794 QDF_STATUS qdf_status;
7795
7796 ENTER();
7797
7798 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007799 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307800 return -EINVAL;
7801 }
7802
7803 status = wlan_hdd_validate_context(hdd_ctx);
7804 if (0 != status)
7805 return -EINVAL;
7806
7807 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7808 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007809 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307810 return -EINVAL;
7811 }
7812
7813 ret = hdd_send_wakelock_stats(hdd_ctx,
7814 &wake_lock_stats);
7815 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007816 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307817
7818 EXIT();
7819 return ret;
7820}
7821
7822/**
7823 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7824 * @wiphy: wiphy pointer
7825 * @wdev: pointer to struct wireless_dev
7826 * @data: pointer to incoming NL vendor data
7827 * @data_len: length of @data
7828 *
7829 * This function parses the incoming NL vendor command data attributes and
7830 * invokes the SME Api and blocks on a completion variable.
7831 * WMA copies required data and invokes callback
7832 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7833 *
7834 * Return: 0 on success; error number otherwise.
7835 */
7836static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7837 struct wireless_dev *wdev,
7838 const void *data, int data_len)
7839{
7840 int ret;
7841
7842 cds_ssr_protect(__func__);
7843 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7844 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007845 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307846
7847 return ret;
7848}
7849
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307850/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307851 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7852 * @wiphy: wiphy structure pointer
7853 * @wdev: Wireless device structure pointer
7854 * @data: Pointer to the data received
7855 * @data_len: Length of @data
7856 *
7857 * This function reads wmi max bus size and fill in the skb with
7858 * NL attributes and send up the NL event.
7859 * Return: 0 on success; errno on failure
7860 */
7861static int
7862__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7863 struct wireless_dev *wdev,
7864 const void *data, int data_len)
7865{
7866 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7867 int ret_val;
7868 struct sk_buff *skb;
7869 uint32_t nl_buf_len;
7870
7871 ENTER();
7872
7873 ret_val = wlan_hdd_validate_context(hdd_ctx);
7874 if (ret_val)
7875 return ret_val;
7876
7877 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7878 hdd_err("Command not allowed in FTM mode");
7879 return -EINVAL;
7880 }
7881
7882 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7883
7884 nl_buf_len = NLMSG_HDRLEN;
7885 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7886
7887 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7888 if (!skb) {
7889 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7890 return -ENOMEM;
7891 }
7892
7893 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7894 hdd_ctx->wmi_max_len)) {
7895 hdd_err("nla put failure");
7896 goto nla_put_failure;
7897 }
7898
7899 cfg80211_vendor_cmd_reply(skb);
7900
7901 EXIT();
7902
7903 return 0;
7904
7905nla_put_failure:
7906 kfree_skb(skb);
7907 return -EINVAL;
7908}
7909
7910/**
7911 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7912 * @wiphy: wiphy structure pointer
7913 * @wdev: Wireless device structure pointer
7914 * @data: Pointer to the data received
7915 * @data_len: Length of @data
7916 *
7917 * Return: 0 on success; errno on failure
7918 */
7919static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7920 struct wireless_dev *wdev,
7921 const void *data, int data_len)
7922{
7923 int ret;
7924
7925 cds_ssr_protect(__func__);
7926 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7927 cds_ssr_unprotect(__func__);
7928
7929 return ret;
7930}
7931
7932/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307933 *__wlan_hdd_cfg80211_setband() - set band
7934 * @wiphy: Pointer to wireless phy
7935 * @wdev: Pointer to wireless device
7936 * @data: Pointer to data
7937 * @data_len: Length of @data
7938 *
7939 * Return: 0 on success, negative errno on failure
7940 */
7941static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7942 struct wireless_dev *wdev,
7943 const void *data, int data_len)
7944{
7945 struct net_device *dev = wdev->netdev;
7946 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7947 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7948 int ret;
7949 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7950 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7951
7952 ENTER();
7953
7954 ret = wlan_hdd_validate_context(hdd_ctx);
7955 if (ret)
7956 return ret;
7957
7958 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7959 hdd_err(FL("Invalid ATTR"));
7960 return -EINVAL;
7961 }
7962
7963 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7964 hdd_err(FL("attr SETBAND_VALUE failed"));
7965 return -EINVAL;
7966 }
7967
7968 ret = hdd_set_band(dev,
7969 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7970
7971 EXIT();
7972 return ret;
7973}
7974
7975/**
7976 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7977 * @wiphy: wiphy structure pointer
7978 * @wdev: Wireless device structure pointer
7979 * @data: Pointer to the data received
7980 * @data_len: Length of @data
7981 *
7982 * Return: 0 on success; errno on failure
7983 */
7984static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7985 struct wireless_dev *wdev,
7986 const void *data, int data_len)
7987{
7988 int ret;
7989
7990 cds_ssr_protect(__func__);
7991 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7992 cds_ssr_unprotect(__func__);
7993
7994 return ret;
7995}
7996
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08007997/**
7998 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
7999 * @nl80211_value: Vendor command attribute value
8000 * @wmi_value: Pointer to return converted WMI return value
8001 *
8002 * Convert NL80211 vendor command value for SAR limit set to WMI value
8003 * Return: 0 on success, -1 on invalid value
8004 */
8005static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8006 u32 *wmi_value)
8007{
8008 int ret = 0;
8009
8010 switch (nl80211_value) {
8011 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8012 *wmi_value = WMI_SAR_FEATURE_OFF;
8013 break;
8014 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8015 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8016 break;
8017 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8018 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8019 break;
8020 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8021 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8022 break;
8023 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8024 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8025 break;
8026 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8027 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8028 break;
8029 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8030 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8031 break;
8032 default:
8033 ret = -1;
8034 }
8035 return ret;
8036}
8037
8038/**
8039 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8040 * @nl80211_value: Vendor command attribute value
8041 * @wmi_value: Pointer to return converted WMI return value
8042 *
8043 * Convert NL80211 vendor command value for SAR BAND to WMI value
8044 * Return: 0 on success, -1 on invalid value
8045 */
8046static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8047{
8048 int ret = 0;
8049
8050 switch (nl80211_value) {
8051 case NL80211_BAND_2GHZ:
8052 *wmi_value = WMI_SAR_2G_ID;
8053 break;
8054 case NL80211_BAND_5GHZ:
8055 *wmi_value = WMI_SAR_5G_ID;
8056 break;
8057 default:
8058 ret = -1;
8059 }
8060 return ret;
8061}
8062
8063/**
8064 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8065 * @nl80211_value: Vendor command attribute value
8066 * @wmi_value: Pointer to return converted WMI return value
8067 *
8068 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8069 * Return: 0 on success, -1 on invalid value
8070 */
8071static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8072 u32 *wmi_value)
8073{
8074 int ret = 0;
8075
8076 switch (nl80211_value) {
8077 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8078 *wmi_value = WMI_SAR_MOD_CCK;
8079 break;
8080 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8081 *wmi_value = WMI_SAR_MOD_OFDM;
8082 break;
8083 default:
8084 ret = -1;
8085 }
8086 return ret;
8087}
8088
8089
8090/**
8091 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
8092 * @wiphy: Pointer to wireless phy
8093 * @wdev: Pointer to wireless device
8094 * @data: Pointer to data
8095 * @data_len: Length of @data
8096 *
8097 * This function is used to setup Specific Absorption Rate limit specs.
8098 *
8099 * Return: 0 on success, negative errno on failure
8100 */
8101static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
8102 struct wireless_dev *wdev,
8103 const void *data, int data_len)
8104{
8105 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8106 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8107 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8108 *sar_spec_list;
8109 struct sar_limit_cmd_params sar_limit_cmd = {0};
8110 int ret = -EINVAL, i = 0, rem = 0;
8111
8112 ENTER();
8113
8114 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8115 hdd_err("Command not allowed in FTM mode");
8116 return -EPERM;
8117 }
8118
8119 if (wlan_hdd_validate_context(hdd_ctx))
8120 return -EINVAL;
8121
8122 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
8123 data, data_len, NULL)) {
8124 hdd_err("Invalid SAR attributes");
8125 return -EINVAL;
8126 }
8127
8128 /* Vendor command manadates all SAR Specs in single call */
8129 sar_limit_cmd.commit_limits = 1;
8130 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
8131 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
8132 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
8133 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
8134 &sar_limit_cmd.sar_enable) < 0) {
8135 hdd_err("Invalid SAR Enable attr");
8136 goto fail;
8137 }
8138 }
8139 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
8140
8141 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
8142 sar_limit_cmd.num_limit_rows = nla_get_u32(
8143 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
8144 hdd_info("attr sar num_limit_rows %d",
8145 sar_limit_cmd.num_limit_rows);
8146 }
8147 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
8148 hdd_err("SAR Spec list exceed supported size");
8149 goto fail;
8150 }
8151 if (sar_limit_cmd.num_limit_rows == 0)
8152 goto send_sar_limits;
8153 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
8154 struct sar_limit_cmd_row) *
8155 sar_limit_cmd.num_limit_rows);
8156 if (!sar_limit_cmd.sar_limit_row_list) {
8157 ret = -ENOMEM;
8158 goto fail;
8159 }
8160 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
8161 hdd_err("Invalid SAR SPECs list");
8162 goto fail;
8163 }
8164
8165 nla_for_each_nested(sar_spec_list,
8166 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
8167 if (i == sar_limit_cmd.num_limit_rows) {
8168 hdd_warn("SAR Cmd has excess SPECs in list");
8169 break;
8170 }
8171
8172 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
8173 nla_data(sar_spec_list), nla_len(sar_spec_list),
8174 NULL)) {
8175 hdd_err("nla_parse failed for SAR Spec list");
8176 goto fail;
8177 }
8178 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
8179 if (sar_spec[
8180 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
8181 sar_limit_cmd.sar_limit_row_list[i].limit_value =
8182 nla_get_u32(sar_spec[
8183 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
8184 } else {
8185 hdd_err("SAR Spec does not have power limit value");
8186 goto fail;
8187 }
8188
8189 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
8190 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
8191 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
8192 &sar_limit_cmd.sar_limit_row_list[i].band_id)
8193 < 0) {
8194 hdd_err("Invalid SAR Band attr");
8195 goto fail;
8196 }
8197 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8198 WMI_SAR_BAND_ID_VALID_MASK;
8199 }
8200 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
8201 sar_limit_cmd.sar_limit_row_list[i].chain_id =
8202 nla_get_u32(sar_spec[
8203 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
8204 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8205 WMI_SAR_CHAIN_ID_VALID_MASK;
8206 }
8207 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
8208 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
8209 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
8210 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
8211 < 0) {
8212 hdd_err("Invalid SAR Modulation attr");
8213 goto fail;
8214 }
8215 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8216 WMI_SAR_MOD_ID_VALID_MASK;
8217 }
8218 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
8219 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
8220 sar_limit_cmd.sar_limit_row_list[i].chain_id,
8221 sar_limit_cmd.sar_limit_row_list[i].mod_id,
8222 sar_limit_cmd.sar_limit_row_list[i].limit_value,
8223 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
8224 i++;
8225 }
8226
8227 if (i < sar_limit_cmd.num_limit_rows) {
8228 hdd_warn("SAR Cmd has less SPECs in list");
8229 sar_limit_cmd.num_limit_rows = i;
8230 }
8231
8232send_sar_limits:
8233 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
8234 QDF_STATUS_SUCCESS)
8235 ret = 0;
8236fail:
8237 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
8238 return ret;
8239}
8240
8241/**
8242 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
8243 * @wiphy: Pointer to wireless phy
8244 * @wdev: Pointer to wireless device
8245 * @data: Pointer to data
8246 * @data_len: Length of @data
8247 *
8248 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
8249 *
8250 * Return: 0 on success, negative errno on failure
8251 */
8252static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
8253 struct wireless_dev *wdev,
8254 const void *data,
8255 int data_len)
8256{
8257 int ret;
8258
8259 cds_ssr_protect(__func__);
8260 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
8261 data_len);
8262 cds_ssr_unprotect(__func__);
8263
8264 return ret;
8265}
8266
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308267static const struct
8268nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
8269 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
8270 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
8271 .len = QDF_MAC_ADDR_SIZE},
8272};
8273
8274/**
8275 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8276 * @wiphy: Pointer to wireless phy
8277 * @wdev: Pointer to wireless device
8278 * @data: Pointer to data
8279 * @data_len: Length of @data
8280 *
8281 * This function is used to enable/disable roaming using vendor commands
8282 *
8283 * Return: 0 on success, negative errno on failure
8284 */
8285static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8286 struct wireless_dev *wdev,
8287 const void *data, int data_len)
8288{
8289 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8290 struct net_device *dev = wdev->netdev;
8291 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8292 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8293 uint32_t is_fast_roam_enabled;
8294 int ret;
8295
8296 ENTER_DEV(dev);
8297
8298 ret = wlan_hdd_validate_context(hdd_ctx);
8299 if (0 != ret)
8300 return ret;
8301
8302 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8303 hdd_err("Command not allowed in FTM mode");
8304 return -EINVAL;
8305 }
8306
8307 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
8308 qca_wlan_vendor_attr);
8309 if (ret) {
8310 hdd_err("Invalid ATTR");
8311 return -EINVAL;
8312 }
8313
8314 /* Parse and fetch Enable flag */
8315 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
8316 hdd_err("attr enable failed");
8317 return -EINVAL;
8318 }
8319
8320 is_fast_roam_enabled = nla_get_u32(
8321 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008322 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
8323 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308324
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008325 if (!adapter->fast_roaming_allowed) {
8326 hdd_err("fast roaming not allowed on %s interface",
8327 adapter->dev->name);
8328 return -EINVAL;
8329 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308330 /* Update roaming */
8331 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008332 (is_fast_roam_enabled &&
8333 adapter->fast_roaming_allowed));
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308334 if (ret)
8335 hdd_err("sme_config_fast_roaming failed");
8336 EXIT();
8337 return ret;
8338}
8339
8340/**
8341 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8342 * @wiphy: Pointer to wireless phy
8343 * @wdev: Pointer to wireless device
8344 * @data: Pointer to data
8345 * @data_len: Length of @data
8346 *
8347 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
8348 *
8349 * Return: 0 on success, negative errno on failure
8350 */
8351static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8352 struct wireless_dev *wdev,
8353 const void *data, int data_len)
8354{
8355 int ret;
8356
8357 cds_ssr_protect(__func__);
8358 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
8359 cds_ssr_unprotect(__func__);
8360
8361 return ret;
8362}
8363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008364const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
8365 {
8366 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8367 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
8368 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05308369 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008370 .doit = is_driver_dfs_capable
8371 },
8372
8373#ifdef WLAN_FEATURE_NAN
8374 {
8375 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8376 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
8377 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8378 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8379 .doit = wlan_hdd_cfg80211_nan_request
8380 },
8381#endif
8382
8383#ifdef WLAN_FEATURE_STATS_EXT
8384 {
8385 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8386 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
8387 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8388 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8389 .doit = wlan_hdd_cfg80211_stats_ext_request
8390 },
8391#endif
8392#ifdef FEATURE_WLAN_EXTSCAN
8393 {
8394 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8395 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
8396 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8397 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8398 .doit = wlan_hdd_cfg80211_extscan_start
8399 },
8400 {
8401 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8402 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
8403 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8404 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8405 .doit = wlan_hdd_cfg80211_extscan_stop
8406 },
8407 {
8408 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8409 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8410 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8411 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8412 },
8413 {
8414 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8415 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8416 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8417 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8418 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8419 },
8420 {
8421 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8422 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8423 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8424 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8425 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8426 },
8427 {
8428 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8429 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8430 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8431 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8432 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8433 },
8434 {
8435 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8436 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8437 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8438 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8439 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8440 },
8441 {
8442 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8443 .info.subcmd =
8444 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8445 .flags =
8446 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8447 WIPHY_VENDOR_CMD_NEED_RUNNING,
8448 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8449 },
8450 {
8451 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8452 .info.subcmd =
8453 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8454 .flags =
8455 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8456 WIPHY_VENDOR_CMD_NEED_RUNNING,
8457 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8458 },
8459 {
8460 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8461 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8462 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8463 WIPHY_VENDOR_CMD_NEED_NETDEV |
8464 WIPHY_VENDOR_CMD_NEED_RUNNING,
8465 .doit = wlan_hdd_cfg80211_set_epno_list
8466 },
8467#endif /* FEATURE_WLAN_EXTSCAN */
8468
8469#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8470 {
8471 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8472 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8473 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8474 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8475 .doit = wlan_hdd_cfg80211_ll_stats_clear
8476 },
8477
8478 {
8479 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8480 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8481 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8482 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8483 .doit = wlan_hdd_cfg80211_ll_stats_set
8484 },
8485
8486 {
8487 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8488 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8489 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8490 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8491 .doit = wlan_hdd_cfg80211_ll_stats_get
8492 },
8493#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8494#ifdef FEATURE_WLAN_TDLS
8495 {
8496 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8497 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8498 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8499 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8500 .doit = wlan_hdd_cfg80211_exttdls_enable
8501 },
8502 {
8503 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8504 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8505 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8506 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8507 .doit = wlan_hdd_cfg80211_exttdls_disable
8508 },
8509 {
8510 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8511 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8512 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8513 .doit = wlan_hdd_cfg80211_exttdls_get_status
8514 },
8515#endif
8516 {
8517 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8518 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8519 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8520 .doit = wlan_hdd_cfg80211_get_supported_features
8521 },
8522 {
8523 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8524 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8525 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8526 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8527 },
8528 {
8529 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8530 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8531 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308532 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008533 },
8534 {
8535 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8536 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8537 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8538 WIPHY_VENDOR_CMD_NEED_NETDEV,
8539 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8540 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008541 {
8542 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8543 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8544 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8545 WIPHY_VENDOR_CMD_NEED_NETDEV,
8546 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8547 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008548 {
8549 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308550 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8551 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8552 WIPHY_VENDOR_CMD_NEED_NETDEV |
8553 WIPHY_VENDOR_CMD_NEED_RUNNING,
8554 .doit = hdd_cfg80211_get_station_cmd
8555 },
8556 {
8557 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008558 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8559 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8560 WIPHY_VENDOR_CMD_NEED_NETDEV |
8561 WIPHY_VENDOR_CMD_NEED_RUNNING,
8562 .doit = wlan_hdd_cfg80211_do_acs
8563 },
8564
8565 {
8566 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8567 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8568 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8569 WIPHY_VENDOR_CMD_NEED_NETDEV,
8570 .doit = wlan_hdd_cfg80211_get_features
8571 },
8572#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8573 {
8574 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8575 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8576 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8577 WIPHY_VENDOR_CMD_NEED_NETDEV |
8578 WIPHY_VENDOR_CMD_NEED_RUNNING,
8579 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8580 },
8581#endif
8582#ifdef FEATURE_WLAN_EXTSCAN
8583 {
8584 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8585 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8586 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8587 WIPHY_VENDOR_CMD_NEED_NETDEV |
8588 WIPHY_VENDOR_CMD_NEED_RUNNING,
8589 .doit = wlan_hdd_cfg80211_set_passpoint_list
8590 },
8591 {
8592 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8593 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8594 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8595 WIPHY_VENDOR_CMD_NEED_NETDEV |
8596 WIPHY_VENDOR_CMD_NEED_RUNNING,
8597 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8598 },
8599 {
8600 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8601 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8602 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8603 WIPHY_VENDOR_CMD_NEED_NETDEV |
8604 WIPHY_VENDOR_CMD_NEED_RUNNING,
8605 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8606 },
8607 {
8608 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8609 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8610 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8611 WIPHY_VENDOR_CMD_NEED_NETDEV |
8612 WIPHY_VENDOR_CMD_NEED_RUNNING,
8613 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8614 },
8615#endif /* FEATURE_WLAN_EXTSCAN */
8616 {
8617 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8618 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8619 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8620 WIPHY_VENDOR_CMD_NEED_NETDEV,
8621 .doit = wlan_hdd_cfg80211_get_wifi_info
8622 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008623#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008624 {
8625 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8626 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8627 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8628 WIPHY_VENDOR_CMD_NEED_NETDEV |
8629 WIPHY_VENDOR_CMD_NEED_RUNNING,
8630 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8631 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008632#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008633 {
8634 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8635 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8636 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8637 WIPHY_VENDOR_CMD_NEED_NETDEV,
8638 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8639 },
8640 {
8641 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8642 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8643 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8644 WIPHY_VENDOR_CMD_NEED_NETDEV,
8645 .doit = wlan_hdd_cfg80211_wifi_logger_start
8646 },
8647 {
8648 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8649 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8650 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8651 WIPHY_VENDOR_CMD_NEED_NETDEV,
8652 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8653 },
8654 {
8655 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8656 .info.subcmd =
8657 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8658 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8659 WIPHY_VENDOR_CMD_NEED_NETDEV |
8660 WIPHY_VENDOR_CMD_NEED_RUNNING,
8661 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8662 },
8663 {
8664 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8665 .info.subcmd =
8666 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8667 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8668 WIPHY_VENDOR_CMD_NEED_NETDEV |
8669 WIPHY_VENDOR_CMD_NEED_RUNNING,
8670 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8671 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008672#ifdef WLAN_FEATURE_TSF
8673 {
8674 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8675 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8676 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8677 WIPHY_VENDOR_CMD_NEED_NETDEV |
8678 WIPHY_VENDOR_CMD_NEED_RUNNING,
8679 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8680 },
8681#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008682#ifdef FEATURE_WLAN_TDLS
8683 {
8684 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8685 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8686 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8687 WIPHY_VENDOR_CMD_NEED_NETDEV |
8688 WIPHY_VENDOR_CMD_NEED_RUNNING,
8689 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8690 },
8691#endif
8692#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8693 {
8694 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8695 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8696 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8697 WIPHY_VENDOR_CMD_NEED_NETDEV |
8698 WIPHY_VENDOR_CMD_NEED_RUNNING,
8699 .doit = wlan_hdd_cfg80211_offloaded_packets
8700 },
8701#endif
8702 {
8703 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8704 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8705 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8706 WIPHY_VENDOR_CMD_NEED_NETDEV |
8707 WIPHY_VENDOR_CMD_NEED_RUNNING,
8708 .doit = wlan_hdd_cfg80211_monitor_rssi
8709 },
8710 {
8711 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308712 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8713 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8714 WIPHY_VENDOR_CMD_NEED_NETDEV |
8715 WIPHY_VENDOR_CMD_NEED_RUNNING,
8716 .doit = wlan_hdd_cfg80211_set_ns_offload
8717 },
8718 {
8719 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008720 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8721 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8722 WIPHY_VENDOR_CMD_NEED_NETDEV |
8723 WIPHY_VENDOR_CMD_NEED_RUNNING,
8724 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8725 },
8726#ifdef WLAN_FEATURE_MEMDUMP
8727 {
8728 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8729 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8730 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8731 WIPHY_VENDOR_CMD_NEED_NETDEV |
8732 WIPHY_VENDOR_CMD_NEED_RUNNING,
8733 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8734 },
8735#endif /* WLAN_FEATURE_MEMDUMP */
8736 {
8737 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8738 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8739 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8740 WIPHY_VENDOR_CMD_NEED_NETDEV |
8741 WIPHY_VENDOR_CMD_NEED_RUNNING,
8742 .doit = wlan_hdd_cfg80211_vendor_scan
8743 },
8744
8745 /* OCB commands */
8746 {
8747 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8748 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8749 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8750 WIPHY_VENDOR_CMD_NEED_NETDEV |
8751 WIPHY_VENDOR_CMD_NEED_RUNNING,
8752 .doit = wlan_hdd_cfg80211_ocb_set_config
8753 },
8754 {
8755 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8756 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8757 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8758 WIPHY_VENDOR_CMD_NEED_NETDEV |
8759 WIPHY_VENDOR_CMD_NEED_RUNNING,
8760 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8761 },
8762 {
8763 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8764 .info.subcmd =
8765 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8766 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8767 WIPHY_VENDOR_CMD_NEED_NETDEV |
8768 WIPHY_VENDOR_CMD_NEED_RUNNING,
8769 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8770 },
8771 {
8772 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8773 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8774 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8775 WIPHY_VENDOR_CMD_NEED_NETDEV |
8776 WIPHY_VENDOR_CMD_NEED_RUNNING,
8777 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8778 },
8779 {
8780 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8781 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8782 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8783 WIPHY_VENDOR_CMD_NEED_NETDEV |
8784 WIPHY_VENDOR_CMD_NEED_RUNNING,
8785 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8786 },
8787 {
8788 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8789 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8790 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8791 WIPHY_VENDOR_CMD_NEED_NETDEV |
8792 WIPHY_VENDOR_CMD_NEED_RUNNING,
8793 .doit = wlan_hdd_cfg80211_dcc_get_stats
8794 },
8795 {
8796 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8797 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8798 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8799 WIPHY_VENDOR_CMD_NEED_NETDEV |
8800 WIPHY_VENDOR_CMD_NEED_RUNNING,
8801 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8802 },
8803 {
8804 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8805 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8806 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8807 WIPHY_VENDOR_CMD_NEED_NETDEV |
8808 WIPHY_VENDOR_CMD_NEED_RUNNING,
8809 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8810 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308811 {
8812 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8813 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8814 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8815 WIPHY_VENDOR_CMD_NEED_NETDEV |
8816 WIPHY_VENDOR_CMD_NEED_RUNNING,
8817 .doit = wlan_hdd_cfg80211_get_link_properties
8818 },
Peng Xu278d0122015-09-24 16:34:17 -07008819 {
Peng Xud2220962016-07-11 17:59:17 -07008820 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008821 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8822 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8823 WIPHY_VENDOR_CMD_NEED_NETDEV |
8824 WIPHY_VENDOR_CMD_NEED_RUNNING,
8825 .doit = wlan_hdd_cfg80211_set_ota_test
8826 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008827#ifdef FEATURE_LFR_SUBNET_DETECTION
8828 {
8829 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8830 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8831 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8832 WIPHY_VENDOR_CMD_NEED_NETDEV |
8833 WIPHY_VENDOR_CMD_NEED_RUNNING,
8834 .doit = wlan_hdd_cfg80211_set_gateway_params
8835 },
8836#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008837 {
Peng Xud2220962016-07-11 17:59:17 -07008838 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008839 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8840 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8841 WIPHY_VENDOR_CMD_NEED_NETDEV |
8842 WIPHY_VENDOR_CMD_NEED_RUNNING,
8843 .doit = wlan_hdd_cfg80211_txpower_scale
8844 },
8845 {
8846 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8847 .info.subcmd =
8848 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8849 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8850 WIPHY_VENDOR_CMD_NEED_NETDEV |
8851 WIPHY_VENDOR_CMD_NEED_RUNNING,
8852 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8853 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308854 {
8855 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8856 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8857 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8858 WIPHY_VENDOR_CMD_NEED_NETDEV |
8859 WIPHY_VENDOR_CMD_NEED_RUNNING,
8860 .doit = wlan_hdd_cfg80211_bpf_offload
8861 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308862 {
8863 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308864 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8865 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8866 WIPHY_VENDOR_CMD_NEED_NETDEV |
8867 WIPHY_VENDOR_CMD_NEED_RUNNING,
8868 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8869 },
8870 {
8871 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308872 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8873 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8874 WIPHY_VENDOR_CMD_NEED_NETDEV |
8875 WIPHY_VENDOR_CMD_NEED_RUNNING,
8876 .doit = wlan_hdd_cfg80211_sta_roam_policy
8877 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308878#ifdef FEATURE_WLAN_CH_AVOID
8879 {
8880 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8881 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8882 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8883 WIPHY_VENDOR_CMD_NEED_NETDEV |
8884 WIPHY_VENDOR_CMD_NEED_RUNNING,
8885 .doit = wlan_hdd_cfg80211_avoid_freq
8886 },
8887#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308888 {
8889 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308890 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8891 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8892 WIPHY_VENDOR_CMD_NEED_NETDEV |
8893 WIPHY_VENDOR_CMD_NEED_RUNNING,
8894 .doit = wlan_hdd_cfg80211_sap_configuration_set
8895 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008896 {
Peng Xu4225c152016-07-14 21:18:14 -07008897 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008898 .info.subcmd =
8899 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8900 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8901 WIPHY_VENDOR_CMD_NEED_NETDEV |
8902 WIPHY_VENDOR_CMD_NEED_RUNNING,
8903 .doit = wlan_hdd_cfg80211_p2p_lo_start
8904 },
8905 {
8906 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8907 .info.subcmd =
8908 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8909 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8910 WIPHY_VENDOR_CMD_NEED_NETDEV |
8911 WIPHY_VENDOR_CMD_NEED_RUNNING,
8912 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8913 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308914 {
8915 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8916 .info.subcmd =
8917 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8918 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8919 WIPHY_VENDOR_CMD_NEED_NETDEV |
8920 WIPHY_VENDOR_CMD_NEED_RUNNING,
8921 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8922 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008923#ifdef WLAN_FEATURE_NAN_DATAPATH
8924 {
8925 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8926 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8927 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8928 WIPHY_VENDOR_CMD_NEED_NETDEV |
8929 WIPHY_VENDOR_CMD_NEED_RUNNING,
8930 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8931 },
8932#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308933 {
8934 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8935 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8936 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8937 WIPHY_VENDOR_CMD_NEED_NETDEV |
8938 WIPHY_VENDOR_CMD_NEED_RUNNING,
8939 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8940 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308941 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308942 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8943 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8944 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8945 WIPHY_VENDOR_CMD_NEED_NETDEV |
8946 WIPHY_VENDOR_CMD_NEED_RUNNING,
8947 .doit = wlan_hdd_cfg80211_get_bus_size
8948 },
8949 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308950 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8951 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8952 WIPHY_VENDOR_CMD_NEED_NETDEV |
8953 WIPHY_VENDOR_CMD_NEED_RUNNING,
8954 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308955 },
8956 {
8957 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8958 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8959 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8960 WIPHY_VENDOR_CMD_NEED_NETDEV |
8961 WIPHY_VENDOR_CMD_NEED_RUNNING,
8962 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308963 },
8964#ifdef WLAN_FEATURE_DISA
8965 {
8966 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8967 .info.subcmd =
8968 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8969 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8970 WIPHY_VENDOR_CMD_NEED_NETDEV |
8971 WIPHY_VENDOR_CMD_NEED_RUNNING,
8972 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8973 },
8974#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07008975#ifdef FEATURE_WLAN_TDLS
8976 {
8977 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8978 .info.subcmd =
8979 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
8980 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8981 WIPHY_VENDOR_CMD_NEED_NETDEV |
8982 WIPHY_VENDOR_CMD_NEED_RUNNING,
8983 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008984 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -07008985#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008986 {
8987 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8988 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
8989 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8990 WIPHY_VENDOR_CMD_NEED_RUNNING,
8991 .doit = wlan_hdd_cfg80211_set_sar_power_limits
8992 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008993#ifdef WLAN_UMAC_CONVERGENCE
8994 COMMON_VENDOR_COMMANDS
8995#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008996};
8997
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05308998#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
8999 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
9000 defined(FEATURE_WLAN_SCAN_PNO)
9001/**
9002 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
9003 * @wiphy: pointer to wiphy
9004 * @config: pointer to config
9005 *
9006 * Return: None
9007 */
9008static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
9009 struct hdd_config *config)
9010{
9011 if (config->configPNOScanSupport) {
9012 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9013 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
9014 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
9015 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
9016 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
9017 if (config->max_sched_scan_plan_interval)
9018 wiphy->max_sched_scan_plan_interval =
9019 config->max_sched_scan_plan_interval;
9020 if (config->max_sched_scan_plan_iterations)
9021 wiphy->max_sched_scan_plan_iterations =
9022 config->max_sched_scan_plan_iterations;
9023 }
9024}
9025#else
9026static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
9027 struct hdd_config *config)
9028{
9029}
9030#endif
9031
9032
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009033/**
9034 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
9035 * @priv_size: Size of the hdd context.
9036 *
9037 * Allocate wiphy context and hdd context.
9038 *
9039 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009040 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009041hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009042{
9043 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009044 hdd_context_t *hdd_ctx;
9045
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009046 ENTER();
9047
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009048 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
9049
9050 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009051 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009052 return NULL;
9053 }
9054
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009055 hdd_ctx = wiphy_priv(wiphy);
9056
9057 hdd_ctx->wiphy = wiphy;
9058
9059 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009060}
9061
9062/*
9063 * FUNCTION: wlan_hdd_cfg80211_update_band
9064 * This function is called from the supplicant through a
9065 * private ioctl to change the band value
9066 */
9067int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
9068{
9069 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07009070 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009071
9072 ENTER();
9073
Dustin Browna30892e2016-10-12 17:28:36 -07009074 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009075
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009076 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009077 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009078
9079 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
9080 struct ieee80211_supported_band *band = wiphy->bands[i];
9081
9082 channelEnabledState =
9083 cds_get_channel_state(band->channels[j].
9084 hw_value);
9085
Dustin Browna30892e2016-10-12 17:28:36 -07009086 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009087 /* 5G only */
9088#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
9089 /* Enable Social channels for P2P */
9090 if (WLAN_HDD_IS_SOCIAL_CHANNEL
9091 (band->channels[j].center_freq)
9092 && CHANNEL_STATE_ENABLE ==
9093 channelEnabledState)
9094 band->channels[j].flags &=
9095 ~IEEE80211_CHAN_DISABLED;
9096 else
9097#endif
9098 band->channels[j].flags |=
9099 IEEE80211_CHAN_DISABLED;
9100 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07009101 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009102 eCSR_BAND_24 == eBand) {
9103 /* 2G only */
9104 band->channels[j].flags |=
9105 IEEE80211_CHAN_DISABLED;
9106 continue;
9107 }
9108
Amar Singhal6842e8f2016-02-23 16:30:32 -08009109 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009110 band->channels[j].flags &=
9111 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009112 }
9113 }
9114 return 0;
9115}
9116
9117/*
9118 * FUNCTION: wlan_hdd_cfg80211_init
9119 * This function is called by hdd_wlan_startup()
9120 * during initialization.
9121 * This function is used to initialize and register wiphy structure.
9122 */
9123int wlan_hdd_cfg80211_init(struct device *dev,
9124 struct wiphy *wiphy, struct hdd_config *pCfg)
9125{
9126 int i, j;
9127 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9128
9129 ENTER();
9130
9131 /* Now bind the underlying wlan device with wiphy */
9132 set_wiphy_dev(wiphy, dev);
9133
9134 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
9135
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009136#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
9137 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07009138 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009139#else
9140 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07009141 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009142#endif
9143
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009144 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
9145 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
9146 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
9147#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
9148 | WIPHY_FLAG_4ADDR_STATION
9149#endif
9150 | WIPHY_FLAG_OFFCHAN_TX;
9151
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009152#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9153 wiphy->wowlan = &wowlan_support_cfg80211_init;
9154#else
9155 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
9156 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
9157 wiphy->wowlan.pattern_min_len = 1;
9158 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
9159#endif
9160
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07009161 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009162#ifdef FEATURE_WLAN_ESE
9163 || pCfg->isEseIniFeatureEnabled
9164#endif
9165 ) {
9166 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
9167 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009168#ifdef FEATURE_WLAN_TDLS
9169 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
9170 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
9171#endif
9172
9173 wiphy->features |= NL80211_FEATURE_HT_IBSS;
9174
Naveen Rawatc77e6e72016-08-05 15:19:03 -07009175#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
9176 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
9177#endif
9178
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05309179 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009180
9181#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05309182 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009183#endif
9184
9185 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
9186 driver can still register regulatory callback and
9187 it will get regulatory settings in wiphy->band[], but
9188 driver need to determine what to do with both
9189 regulatory settings */
9190
9191 wiphy->reg_notifier = hdd_reg_notifier;
9192
9193#if defined QCA_WIFI_FTM
9194}
9195#endif
9196
9197 wiphy->max_scan_ssids = MAX_SCAN_SSID;
9198
9199 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
9200
9201 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
9202
Arun Khandavallifae92942016-08-01 13:31:08 +05309203 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
9204 | BIT(NL80211_IFTYPE_ADHOC)
9205 | BIT(NL80211_IFTYPE_P2P_CLIENT)
9206 | BIT(NL80211_IFTYPE_P2P_GO)
9207 | BIT(NL80211_IFTYPE_AP)
9208 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009209
Arun Khandavallifae92942016-08-01 13:31:08 +05309210 if (pCfg->advertiseConcurrentOperation) {
9211 if (pCfg->enableMCC) {
9212 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07009213
Arun Khandavallifae92942016-08-01 13:31:08 +05309214 for (i = 0;
9215 i < ARRAY_SIZE(wlan_hdd_iface_combination);
9216 i++) {
9217 if (!pCfg->allowMCCGODiffBI)
9218 wlan_hdd_iface_combination[i].
9219 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009220 }
9221 }
9222 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05309223 ARRAY_SIZE(wlan_hdd_iface_combination);
9224 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009225 }
9226
9227 /* Before registering we need to update the ht capabilitied based
9228 * on ini values*/
9229 if (!pCfg->ShortGI20MhzEnable) {
9230 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
9231 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009232 }
9233
9234 if (!pCfg->ShortGI40MhzEnable) {
9235 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
9236 }
9237
9238 if (!pCfg->nChannelBondingMode5GHz) {
9239 wlan_hdd_band_5_ghz.ht_cap.cap &=
9240 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
9241 }
9242
Abhishek Singhf512bf32016-05-04 16:47:46 +05309243 /*
9244 * In case of static linked driver at the time of driver unload,
9245 * module exit doesn't happens. Module cleanup helps in cleaning
9246 * of static memory.
9247 * If driver load happens statically, at the time of driver unload,
9248 * wiphy flags don't get reset because of static memory.
9249 * It's better not to store channel in static memory.
9250 */
Dustin Browna30892e2016-10-12 17:28:36 -07009251 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
9252 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05309253 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07009254 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309255 hdd_err("Not enough memory to allocate channels");
9256 return -ENOMEM;
9257 }
Dustin Browna30892e2016-10-12 17:28:36 -07009258 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05309259 &hdd_channels_2_4_ghz[0],
9260 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05309261 if ((hdd_is_5g_supported(pHddCtx)) &&
9262 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
9263 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
9264 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
9265 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -07009266 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
9267 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05309268 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07009269 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309270 hdd_err("Not enough memory to allocate channels");
9271 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -07009272 bands[NL80211_BAND_2GHZ]->channels);
9273 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +05309274 return -ENOMEM;
9275 }
Dustin Browna30892e2016-10-12 17:28:36 -07009276 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05309277 &hdd_channels_5_ghz[0],
9278 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009279 }
9280
Dustin Browna30892e2016-10-12 17:28:36 -07009281 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009282
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009283 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009284 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009285
9286 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
9287 struct ieee80211_supported_band *band = wiphy->bands[i];
9288
Dustin Browna30892e2016-10-12 17:28:36 -07009289 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009290 eCSR_BAND_5G == pCfg->nBandCapability) {
9291 /* 5G only */
9292#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
9293 /* Enable social channels for P2P */
9294 if (WLAN_HDD_IS_SOCIAL_CHANNEL
9295 (band->channels[j].center_freq))
9296 band->channels[j].flags &=
9297 ~IEEE80211_CHAN_DISABLED;
9298 else
9299#endif
9300 band->channels[j].flags |=
9301 IEEE80211_CHAN_DISABLED;
9302 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07009303 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009304 eCSR_BAND_24 == pCfg->nBandCapability) {
9305 /* 2G only */
9306 band->channels[j].flags |=
9307 IEEE80211_CHAN_DISABLED;
9308 continue;
9309 }
9310 }
9311 }
9312 /*Initialise the supported cipher suite details */
9313 wiphy->cipher_suites = hdd_cipher_suites;
9314 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
9315
9316 /*signal strength in mBm (100*dBm) */
9317 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
9318 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
9319
Anurag Chouhan6d760662016-02-20 16:05:43 +05309320 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009321 wiphy->n_vendor_commands =
9322 ARRAY_SIZE(hdd_wiphy_vendor_commands);
9323 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
9324
9325 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
9326 wiphy->n_vendor_events =
9327 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
9328 }
9329
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009330 if (pCfg->enableDFSMasterCap) {
9331 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
9332 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009333
9334 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
9335
9336#ifdef QCA_HT_2040_COEX
9337 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
9338#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +05309339 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05309340 hdd_add_channel_switch_support(&wiphy->flags);
9341
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009342 EXIT();
9343 return 0;
9344}
9345
Abhishek Singhf512bf32016-05-04 16:47:46 +05309346/**
Yingying Tang80e15f32016-09-27 18:23:01 +08009347 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
9348 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +05309349 *
9350 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309351 * memory allocated in wlan_hdd_cfg80211_init also
9352 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05309353 *
9354 * Return: void
9355 */
9356void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
9357{
9358 int i;
9359
Dustin Browna30892e2016-10-12 17:28:36 -07009360 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309361 if (NULL != wiphy->bands[i] &&
9362 (NULL != wiphy->bands[i]->channels)) {
9363 qdf_mem_free(wiphy->bands[i]->channels);
9364 wiphy->bands[i]->channels = NULL;
9365 }
9366 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309367 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05309368}
9369
Yingying Tang80e15f32016-09-27 18:23:01 +08009370/**
9371 * wlan_hdd_update_band_cap() - update capabilities for supported bands
9372 * @hdd_ctx: HDD context
9373 *
9374 * this function will update capabilities for supported bands
9375 *
9376 * Return: void
9377 */
9378static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
9379{
9380 uint32_t val32;
9381 uint16_t val16;
9382 tSirMacHTCapabilityInfo *ht_cap_info;
9383 QDF_STATUS status;
9384
9385 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
9386 if (QDF_STATUS_SUCCESS != status) {
9387 hdd_err("could not get HT capability info");
9388 val32 = 0;
9389 }
9390 val16 = (uint16_t)val32;
9391 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
9392
9393 if (ht_cap_info->txSTBC == true) {
9394 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
9395 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
9396 IEEE80211_HT_CAP_TX_STBC;
9397 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
9398 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
9399 IEEE80211_HT_CAP_TX_STBC;
9400 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009401
9402 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
9403 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
9404 vht_cap.vht_supported = 0;
9405 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
9406 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
9407 vht_cap.vht_supported = 0;
9408 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
9409 }
Yingying Tang80e15f32016-09-27 18:23:01 +08009410}
9411
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009412/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309413 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009414 * initialization. In wlan_hdd_cfg80211_init, only the
9415 * default values will be initialized. The final initialization
9416 * of all required members can be done here.
9417 */
Yingying Tang80e15f32016-09-27 18:23:01 +08009418void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009419{
Yingying Tang80e15f32016-09-27 18:23:01 +08009420 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
9421
9422 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009423}
9424
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009425/**
9426 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
9427 * @cfg: hdd cfg
9428 *
9429 * this function update 11n mode in hdd cfg
9430 *
9431 * Return: void
9432 */
9433void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
9434{
9435 if (sme_is_feature_supported_by_fw(DOT11AC)) {
9436 hdd_notice("support 11ac");
9437 } else {
9438 hdd_notice("not support 11ac");
9439 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
9440 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
9441 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
9442 cfg->sap_p2p_11ac_override = 0;
9443 }
9444 }
9445}
9446
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009447/* In this function we are registering wiphy. */
9448int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
9449{
9450 ENTER();
9451 /* Register our wiphy dev with cfg80211 */
9452 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009453 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009454 return -EIO;
9455 }
9456
9457 EXIT();
9458 return 0;
9459}
9460
9461/*
9462 HDD function to update wiphy capability based on target offload status.
9463
9464 wlan_hdd_cfg80211_init() does initialization of all wiphy related
9465 capability even before downloading firmware to the target. In discrete
9466 case, host will get know certain offload capability (say sched_scan
9467 caps) only after downloading firmware to the target and target boots up.
9468 This function is used to override setting done in wlan_hdd_cfg80211_init()
9469 based on target capability.
9470 */
9471void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
9472{
9473#ifdef FEATURE_WLAN_SCAN_PNO
9474 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9475 struct hdd_config *pCfg = pHddCtx->config;
9476
9477 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
9478 * control comes here. Here just we need to clear it if firmware doesn't
9479 * have PNO support. */
9480 if (!pCfg->PnoOffload) {
9481 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9482 wiphy->max_sched_scan_ssids = 0;
9483 wiphy->max_match_sets = 0;
9484 wiphy->max_sched_scan_ie_len = 0;
9485 }
9486#endif
9487}
9488
9489/* This function registers for all frame which supplicant is interested in */
9490void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
9491{
9492 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9493 /* Register for all P2P action, public action etc frames */
9494 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9495
9496 ENTER();
9497
Abhishek Singh7996eb72015-12-30 17:24:02 +05309498 /* Register frame indication call back */
9499 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
9500
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05309501 /* Register for p2p ack indication */
9502 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
9503
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009504 /* Right now we are registering these frame when driver is getting
9505 initialized. Once we will move to 2.6.37 kernel, in which we have
9506 frame register ops, we will move this code as a part of that */
9507 /* GAS Initial Request */
9508 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9509 (uint8_t *) GAS_INITIAL_REQ,
9510 GAS_INITIAL_REQ_SIZE);
9511
9512 /* GAS Initial Response */
9513 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9514 (uint8_t *) GAS_INITIAL_RSP,
9515 GAS_INITIAL_RSP_SIZE);
9516
9517 /* GAS Comeback Request */
9518 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9519 (uint8_t *) GAS_COMEBACK_REQ,
9520 GAS_COMEBACK_REQ_SIZE);
9521
9522 /* GAS Comeback Response */
9523 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9524 (uint8_t *) GAS_COMEBACK_RSP,
9525 GAS_COMEBACK_RSP_SIZE);
9526
9527 /* P2P Public Action */
9528 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9529 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9530 P2P_PUBLIC_ACTION_FRAME_SIZE);
9531
9532 /* P2P Action */
9533 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9534 (uint8_t *) P2P_ACTION_FRAME,
9535 P2P_ACTION_FRAME_SIZE);
9536
9537 /* WNM BSS Transition Request frame */
9538 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9539 (uint8_t *) WNM_BSS_ACTION_FRAME,
9540 WNM_BSS_ACTION_FRAME_SIZE);
9541
9542 /* WNM-Notification */
9543 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9544 (uint8_t *) WNM_NOTIFICATION_FRAME,
9545 WNM_NOTIFICATION_FRAME_SIZE);
9546}
9547
9548void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9549{
9550 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9551 /* Register for all P2P action, public action etc frames */
9552 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9553
9554 ENTER();
9555
9556 /* Right now we are registering these frame when driver is getting
9557 initialized. Once we will move to 2.6.37 kernel, in which we have
9558 frame register ops, we will move this code as a part of that */
9559 /* GAS Initial Request */
9560
9561 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9562 (uint8_t *) GAS_INITIAL_REQ,
9563 GAS_INITIAL_REQ_SIZE);
9564
9565 /* GAS Initial Response */
9566 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9567 (uint8_t *) GAS_INITIAL_RSP,
9568 GAS_INITIAL_RSP_SIZE);
9569
9570 /* GAS Comeback Request */
9571 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9572 (uint8_t *) GAS_COMEBACK_REQ,
9573 GAS_COMEBACK_REQ_SIZE);
9574
9575 /* GAS Comeback Response */
9576 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9577 (uint8_t *) GAS_COMEBACK_RSP,
9578 GAS_COMEBACK_RSP_SIZE);
9579
9580 /* P2P Public Action */
9581 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9582 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9583 P2P_PUBLIC_ACTION_FRAME_SIZE);
9584
9585 /* P2P Action */
9586 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9587 (uint8_t *) P2P_ACTION_FRAME,
9588 P2P_ACTION_FRAME_SIZE);
9589
9590 /* WNM-Notification */
9591 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9592 (uint8_t *) WNM_NOTIFICATION_FRAME,
9593 WNM_NOTIFICATION_FRAME_SIZE);
9594}
9595
9596#ifdef FEATURE_WLAN_WAPI
9597void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9598 const uint8_t *mac_addr, const uint8_t *key,
9599 int key_Len)
9600{
9601 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9602 tCsrRoamSetKey setKey;
9603 bool isConnected = true;
9604 int status = 0;
9605 uint32_t roamId = 0xFF;
9606 uint8_t *pKeyPtr = NULL;
9607 int n = 0;
9608
Jeff Johnson46b40792016-06-29 14:03:14 -07009609 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009610 hdd_device_mode_to_string(pAdapter->device_mode),
9611 pAdapter->device_mode);
9612
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309613 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009614 setKey.keyId = key_index; /* Store Key ID */
9615 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9616 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9617 setKey.paeRole = 0; /* the PAE role */
9618 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309619 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009620 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309621 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009622 }
9623 setKey.keyLength = key_Len;
9624 pKeyPtr = setKey.Key;
9625 memcpy(pKeyPtr, key, key_Len);
9626
Jeff Johnson46b40792016-06-29 14:03:14 -07009627 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009628 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009629 hdd_notice("WAPI KEY Data[%d]:%02x ",
9630 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009631
9632 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9633 if (isConnected) {
9634 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9635 pAdapter->sessionId, &setKey, &roamId);
9636 }
9637 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009638 hdd_err("sme_roam_set_key returned ERROR status= %d",
9639 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009640 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9641 }
9642}
9643#endif /* FEATURE_WLAN_WAPI */
9644
9645uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9646 uint8_t eid)
9647{
9648 int left = length;
9649 uint8_t *ptr = (uint8_t *)ies_ptr;
9650 uint8_t elem_id, elem_len;
9651
9652 while (left >= 2) {
9653 elem_id = ptr[0];
9654 elem_len = ptr[1];
9655 left -= 2;
9656 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009657 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009658 eid, elem_len, left);
9659 return NULL;
9660 }
9661 if (elem_id == eid) {
9662 return ptr;
9663 }
9664
9665 left -= elem_len;
9666 ptr += (elem_len + 2);
9667 }
9668 return NULL;
9669}
9670
9671/*
9672 * FUNCTION: wlan_hdd_validate_operation_channel
9673 * called by wlan_hdd_cfg80211_start_bss() and
9674 * wlan_hdd_set_channel()
9675 * This function validates whether given channel is part of valid
9676 * channel list.
9677 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309678QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009679 int channel)
9680{
9681
9682 uint32_t num_ch = 0;
9683 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9684 u32 indx = 0;
9685 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9686 uint8_t fValidChannel = false, count = 0;
9687 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9688
9689 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9690
9691 if (hdd_pConfig_ini->sapAllowAllChannel) {
9692 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009693 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009694 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009695 fValidChannel = true;
9696 break;
9697 }
9698 }
9699 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009700 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309701 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009702 }
9703 } else {
9704 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9705 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009706 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309707 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009708 }
9709 for (indx = 0; indx < num_ch; indx++) {
9710 if (channel == valid_ch[indx]) {
9711 break;
9712 }
9713 }
9714
9715 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009716 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309717 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009718 }
9719 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309720 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009721
9722}
9723
9724#ifdef DHCP_SERVER_OFFLOAD
9725static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9726{
9727 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9728 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9729 uint8_t numEntries = 0;
9730 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9731 uint8_t num;
9732 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309733 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009734 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009735 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009736 return;
9737 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009738 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9739 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9740 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9741 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9742 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9743 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009744 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009745 goto end;
9746 }
9747 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009748 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009749 goto end;
9750 }
9751 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009752 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009753 goto end;
9754 }
9755 for (num = 0; num < numEntries; num++) {
9756 temp = srv_ip[num];
9757 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9758 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309759 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009760 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009761 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009762 goto end;
9763 }
Jeff Johnson77848112016-06-29 14:52:06 -07009764 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009765end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309766 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009767 return;
9768}
9769#endif /* DHCP_SERVER_OFFLOAD */
9770
9771static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9772 struct net_device *dev,
9773 struct bss_parameters *params)
9774{
9775 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9776 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9777 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309778 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009779
9780 ENTER();
9781
Anurag Chouhan6d760662016-02-20 16:05:43 +05309782 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009783 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009784 return -EINVAL;
9785 }
9786
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309787 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9788 hdd_err("invalid session id: %d", pAdapter->sessionId);
9789 return -EINVAL;
9790 }
9791
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309792 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009793 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9794 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009795 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009796 hdd_device_mode_to_string(pAdapter->device_mode),
9797 pAdapter->device_mode, params->ap_isolate);
9798
9799 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9800 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309801 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009802 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009803
Krunal Sonib4326f22016-03-10 13:05:51 -08009804 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9805 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009806 return -EOPNOTSUPP;
9807 }
9808
9809 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9810 * want to update this parameter */
9811 if (-1 != params->ap_isolate) {
9812 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9813 !!params->ap_isolate;
9814
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309815 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009816 pAdapter->sessionId,
9817 pAdapter->sessionCtx.
9818 ap.
9819 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309820 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009821 ret = -EINVAL;
9822 }
9823 }
9824
9825 EXIT();
9826 return ret;
9827}
9828
Krunal Soni8c37e322016-02-03 16:08:37 -08009829/**
9830 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9831 * @ndev: pointer to net device provided by supplicant
9832 * @type: type of the interface, upper layer wanted to change
9833 *
9834 * Upper layer provides the new interface mode that needs to be changed
9835 * for given net device
9836 *
9837 * Return: success or failure in terms of integer value
9838 */
9839static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009840 enum nl80211_iftype type)
9841{
Krunal Soni8c37e322016-02-03 16:08:37 -08009842 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9843 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9844 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009845 hdd_wext_state_t *wext;
9846 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309847 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009848
9849 ENTER();
9850
Krunal Soni8c37e322016-02-03 16:08:37 -08009851 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009852 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009853 return 0;
9854 }
9855
9856 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009857 hdd_stop_adapter(hdd_ctx, adapter, true);
9858 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009859 wdev->iftype = type;
9860 /*Check for sub-string p2p to confirm its a p2p interface */
9861 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009862 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009863 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009864 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009865 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009866 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009867 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009868 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009869 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009870 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009871 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009872 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9873 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009874 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9875 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009876 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009877 adapter->scan_info.scanAddIE.length;
9878 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309879 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009880 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9881 wext->roamProfile.phyMode =
9882 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9883 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009884 EXIT();
9885 return status;
9886}
9887
9888static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9889 struct net_device *dev,
9890 struct bss_parameters *params)
9891{
9892 int ret;
9893
9894 cds_ssr_protect(__func__);
9895 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9896 cds_ssr_unprotect(__func__);
9897
9898 return ret;
9899}
9900
9901/* FUNCTION: wlan_hdd_change_country_code_cd
9902 * to wait for contry code completion
9903 */
9904void *wlan_hdd_change_country_code_cb(void *pAdapter)
9905{
9906 hdd_adapter_t *call_back_pAdapter = pAdapter;
9907 complete(&call_back_pAdapter->change_country_code);
9908 return NULL;
9909}
9910
Rajeev Kumar98edb772016-01-19 12:42:19 -08009911/**
9912 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9913 * @wiphy: Pointer to the wiphy structure
9914 * @ndev: Pointer to the net device
9915 * @type: Interface type
9916 * @flags: Flags for change interface
9917 * @params: Pointer to change interface parameters
9918 *
9919 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009920 */
9921static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9922 struct net_device *ndev,
9923 enum nl80211_iftype type,
9924 u32 *flags,
9925 struct vif_params *params)
9926{
9927 struct wireless_dev *wdev;
9928 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9929 hdd_context_t *pHddCtx;
9930 tCsrRoamProfile *pRoamProfile = NULL;
9931 eCsrRoamBssType LastBSSType;
9932 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309933 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009934 int status;
9935
9936 ENTER();
9937
Anurag Chouhan6d760662016-02-20 16:05:43 +05309938 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009939 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009940 return -EINVAL;
9941 }
9942
9943 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9944 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309945 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009946 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009947
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309948 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009949 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9950 pAdapter->sessionId, type));
9951
Jeff Johnson77848112016-06-29 14:52:06 -07009952 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009953 pAdapter->device_mode, type);
9954
Arun Khandavallifae92942016-08-01 13:31:08 +05309955 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9956 if (status) {
9957 hdd_err("Failed to start modules");
9958 return -EINVAL;
9959 }
9960
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009961 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009962 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9963 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009964 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009965 return -EINVAL;
9966 }
9967
9968 pConfig = pHddCtx->config;
9969 wdev = ndev->ieee80211_ptr;
9970
9971 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009972 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009973
9974 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9975
Krunal Sonib4326f22016-03-10 13:05:51 -08009976 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9977 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9978 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9979 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009980 hdd_wext_state_t *pWextState =
9981 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9982
9983 pRoamProfile = &pWextState->roamProfile;
9984 LastBSSType = pRoamProfile->BSSType;
9985
9986 switch (type) {
9987 case NL80211_IFTYPE_STATION:
9988 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009989 case NL80211_IFTYPE_ADHOC:
9990 if (type == NL80211_IFTYPE_ADHOC) {
9991 wlan_hdd_tdls_exit(pAdapter);
9992 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009993 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009994 }
9995 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9996 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309997 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009998 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309999 if (hdd_start_adapter(pAdapter)) {
10000 hdd_err("Failed to start adapter :%d",
10001 pAdapter->device_mode);
10002 return -EINVAL;
10003 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010004 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010005 case NL80211_IFTYPE_AP:
10006 case NL80211_IFTYPE_P2P_GO:
10007 {
Jeff Johnson77848112016-06-29 14:52:06 -070010008 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010009 (type ==
10010 NL80211_IFTYPE_AP) ? "SoftAP" :
10011 "P2pGo");
10012
10013 /* Cancel any remain on channel for GO mode */
10014 if (NL80211_IFTYPE_P2P_GO == type) {
10015 wlan_hdd_cancel_existing_remain_on_channel
10016 (pAdapter);
10017 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010018
Arun Khandavallifae92942016-08-01 13:31:08 +053010019 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010020 /* De-init the adapter */
10021 hdd_deinit_adapter(pHddCtx, pAdapter, true);
10022 memset(&pAdapter->sessionCtx, 0,
10023 sizeof(pAdapter->sessionCtx));
10024 pAdapter->device_mode =
10025 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080010026 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
10027 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010028
10029 /*
10030 * Fw will take care incase of concurrency
10031 */
10032
Krunal Sonib4326f22016-03-10 13:05:51 -080010033 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010034 && (pConfig->apRandomBssidEnabled)) {
10035 /* To meet Android requirements create a randomized
10036 MAC address of the form 02:1A:11:Fx:xx:xx */
10037 get_random_bytes(&ndev->dev_addr[3], 3);
10038 ndev->dev_addr[0] = 0x02;
10039 ndev->dev_addr[1] = 0x1A;
10040 ndev->dev_addr[2] = 0x11;
10041 ndev->dev_addr[3] |= 0xF0;
10042 memcpy(pAdapter->macAddressCurrent.
10043 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053010044 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010045 pr_info("wlan: Generated HotSpot BSSID "
10046 MAC_ADDRESS_STR "\n",
10047 MAC_ADDR_ARRAY(ndev->dev_addr));
10048 }
10049
10050 hdd_set_ap_ops(pAdapter->dev);
10051
Arun Khandavallifae92942016-08-01 13:31:08 +053010052 if (hdd_start_adapter(pAdapter)) {
10053 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010054 return -EINVAL;
10055 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010056 /* Interface type changed update in wiphy structure */
10057 if (wdev) {
10058 wdev->iftype = type;
10059 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070010060 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010061 return -EINVAL;
10062 }
10063 goto done;
10064 }
10065
10066 default:
Jeff Johnson77848112016-06-29 14:52:06 -070010067 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010068 type);
10069 return -EOPNOTSUPP;
10070 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010071 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10072 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010073 switch (type) {
10074 case NL80211_IFTYPE_STATION:
10075 case NL80211_IFTYPE_P2P_CLIENT:
10076 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080010077 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
10078 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010079 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010080 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010081 if (hdd_start_adapter(pAdapter)) {
10082 hdd_err("Failed to start adapter :%d",
10083 pAdapter->device_mode);
10084 return -EINVAL;
10085 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010086 goto done;
10087
10088 case NL80211_IFTYPE_AP:
10089 case NL80211_IFTYPE_P2P_GO:
10090 wdev->iftype = type;
10091 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010092 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010093 goto done;
10094
10095 default:
Jeff Johnson77848112016-06-29 14:52:06 -070010096 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010097 type);
10098 return -EOPNOTSUPP;
10099 }
10100 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070010101 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010102 pAdapter->device_mode);
10103 return -EOPNOTSUPP;
10104 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010105done:
10106 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010107 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010108
Jeff Johnson2ae6f712016-09-23 15:08:48 -070010109 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010110
10111 EXIT();
10112 return 0;
10113}
10114
Rajeev Kumar98edb772016-01-19 12:42:19 -080010115/**
10116 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10117 * @wiphy: Pointer to the wiphy structure
10118 * @ndev: Pointer to the net device
10119 * @type: Interface type
10120 * @flags: Flags for change interface
10121 * @params: Pointer to change interface parameters
10122 *
10123 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010124 */
10125static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
10126 struct net_device *ndev,
10127 enum nl80211_iftype type,
10128 u32 *flags,
10129 struct vif_params *params)
10130{
10131 int ret;
10132
10133 cds_ssr_protect(__func__);
10134 ret =
10135 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
10136 cds_ssr_unprotect(__func__);
10137
10138 return ret;
10139}
10140
10141#ifdef FEATURE_WLAN_TDLS
10142static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
10143 int index, uint8_t match)
10144{
10145 int i;
10146 for (i = 0; i < index; i++) {
10147 if (arr[i] == match)
10148 return true;
10149 }
10150 return false;
10151}
10152#endif
10153
10154/**
10155 * __wlan_hdd_change_station() - change station
10156 * @wiphy: Pointer to the wiphy structure
10157 * @dev: Pointer to the net device.
10158 * @mac: bssid
10159 * @params: Pointer to station parameters
10160 *
10161 * Return: 0 for success, error number on failure.
10162 */
10163#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10164static int __wlan_hdd_change_station(struct wiphy *wiphy,
10165 struct net_device *dev,
10166 const uint8_t *mac,
10167 struct station_parameters *params)
10168#else
10169static int __wlan_hdd_change_station(struct wiphy *wiphy,
10170 struct net_device *dev,
10171 uint8_t *mac,
10172 struct station_parameters *params)
10173#endif
10174{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010175 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010176 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10177 hdd_context_t *pHddCtx;
10178 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053010179 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010180#ifdef FEATURE_WLAN_TDLS
10181 tCsrStaParams StaParams = { 0 };
10182 uint8_t isBufSta = 0;
10183 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053010184 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010185#endif
10186 int ret;
10187
10188 ENTER();
10189
Anurag Chouhan6d760662016-02-20 16:05:43 +053010190 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010191 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010192 return -EINVAL;
10193 }
10194
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010195 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010196 TRACE_CODE_HDD_CHANGE_STATION,
10197 pAdapter->sessionId, params->listen_interval));
10198
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010199 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10200 hdd_err("invalid session id: %d", pAdapter->sessionId);
10201 return -EINVAL;
10202 }
10203
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010204 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10205 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010206 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010207 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010208
10209 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10210
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010211 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010212
Krunal Sonib4326f22016-03-10 13:05:51 -080010213 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10214 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010215 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
10216 status =
10217 hdd_softap_change_sta_state(pAdapter,
10218 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080010219 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010220
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010221 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010222 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010223 return -EINVAL;
10224 }
10225 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010226 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10227 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010228#ifdef FEATURE_WLAN_TDLS
10229 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070010230
10231 if (cds_is_sub_20_mhz_enabled()) {
10232 hdd_err("TDLS not allowed with sub 20 MHz");
10233 return -EINVAL;
10234 }
10235
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010236 StaParams.capability = params->capability;
10237 StaParams.uapsd_queues = params->uapsd_queues;
10238 StaParams.max_sp = params->max_sp;
10239
10240 /* Convert (first channel , number of channels) tuple to
10241 * the total list of channels. This goes with the assumption
10242 * that if the first channel is < 14, then the next channels
10243 * are an incremental of 1 else an incremental of 4 till the number
10244 * of channels.
10245 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010246 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010247 if (0 != params->supported_channels_len) {
10248 int i = 0, j = 0, k = 0, no_of_channels = 0;
10249 int num_unique_channels;
10250 int next;
10251 for (i = 0;
10252 i < params->supported_channels_len
10253 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
10254 int wifi_chan_index;
10255 if (!wlan_hdd_is_duplicate_channel
10256 (StaParams.supported_channels, j,
10257 params->supported_channels[i])) {
10258 StaParams.
10259 supported_channels[j] =
10260 params->
10261 supported_channels[i];
10262 } else {
10263 continue;
10264 }
10265 wifi_chan_index =
10266 ((StaParams.supported_channels[j] <=
10267 HDD_CHANNEL_14) ? 1 : 4);
10268 no_of_channels =
10269 params->supported_channels[i + 1];
10270
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010271 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 -080010272 StaParams.
10273 supported_channels[j],
10274 wifi_chan_index,
10275 no_of_channels);
10276 for (k = 1; k <= no_of_channels &&
10277 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
10278 k++) {
10279 next =
10280 StaParams.
10281 supported_channels[j] +
10282 wifi_chan_index;
10283 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
10284 StaParams.
10285 supported_channels[j
10286 +
10287 1]
10288 = next;
10289 } else {
10290 continue;
10291 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010292 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010293 j + 1,
10294 StaParams.
10295 supported_channels[j +
10296 1]);
10297 j += 1;
10298 }
10299 }
10300 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010301 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010302 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010303 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010304 StaParams.
10305 supported_channels[i]);
10306 }
10307 if (MAX_CHANNEL < num_unique_channels)
10308 num_unique_channels = MAX_CHANNEL;
10309 StaParams.supported_channels_len =
10310 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010311 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010312 StaParams.supported_channels_len);
10313 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010314 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010315 params->supported_oper_classes,
10316 params->supported_oper_classes_len);
10317 StaParams.supported_oper_classes_len =
10318 params->supported_oper_classes_len;
10319
10320 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010321 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010322 params->ext_capab,
10323 sizeof(StaParams.extn_capability));
10324
10325 if (NULL != params->ht_capa) {
10326 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010327 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010328 sizeof(tSirHTCap));
10329 }
10330
10331 StaParams.supported_rates_len =
10332 params->supported_rates_len;
10333
10334 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
10335 * The supported_rates array , for all the structures propogating till Add Sta
10336 * to the firmware has to be modified , if the supplicant (ieee80211) is
10337 * modified to send more rates.
10338 */
10339
10340 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
10341 */
10342 if (StaParams.supported_rates_len >
10343 SIR_MAC_MAX_SUPP_RATES)
10344 StaParams.supported_rates_len =
10345 SIR_MAC_MAX_SUPP_RATES;
10346
10347 if (0 != StaParams.supported_rates_len) {
10348 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010349 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010350 params->supported_rates,
10351 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010352 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010353 StaParams.supported_rates_len);
10354 for (i = 0; i < StaParams.supported_rates_len;
10355 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010356 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010357 StaParams.supported_rates[i]);
10358 }
10359
10360 if (NULL != params->vht_capa) {
10361 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010362 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010363 params->vht_capa,
10364 sizeof(tSirVHTCap));
10365 }
10366
10367 if (0 != params->ext_capab_len) {
10368 /*Define A Macro : TODO Sunil */
10369 if ((1 << 4) & StaParams.extn_capability[3]) {
10370 isBufSta = 1;
10371 }
10372 /* TDLS Channel Switching Support */
10373 if ((1 << 6) & StaParams.extn_capability[3]) {
10374 isOffChannelSupported = 1;
10375 }
10376 }
10377
Nitesh Shah99934ac2016-09-05 15:54:08 +053010378 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053010379 (params->ht_capa || params->vht_capa ||
10380 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053010381 is_qos_wmm_sta = true;
10382
10383 hdd_notice("%s: TDLS Peer is QOS capable"
10384 " is_qos_wmm_sta= %d HTcapPresent = %d",
10385 __func__, is_qos_wmm_sta,
10386 StaParams.htcap_present);
10387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010388 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053010389 &StaParams,
10390 isBufSta,
10391 isOffChannelSupported,
10392 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010393 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010394 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010395 return -EINVAL;
10396 }
10397
10398 status =
10399 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
10400 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010401 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010402 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010403 return -EINVAL;
10404 }
10405 }
10406#endif
10407 }
10408 EXIT();
10409 return ret;
10410}
10411
10412/**
10413 * wlan_hdd_change_station() - cfg80211 change station handler function
10414 * @wiphy: Pointer to the wiphy structure
10415 * @dev: Pointer to the net device.
10416 * @mac: bssid
10417 * @params: Pointer to station parameters
10418 *
10419 * This is the cfg80211 change station handler function which invokes
10420 * the internal function @__wlan_hdd_change_station with
10421 * SSR protection.
10422 *
10423 * Return: 0 for success, error number on failure.
10424 */
10425#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
10426static int wlan_hdd_change_station(struct wiphy *wiphy,
10427 struct net_device *dev,
10428 const u8 *mac,
10429 struct station_parameters *params)
10430#else
10431static int wlan_hdd_change_station(struct wiphy *wiphy,
10432 struct net_device *dev,
10433 u8 *mac,
10434 struct station_parameters *params)
10435#endif
10436{
10437 int ret;
10438
10439 cds_ssr_protect(__func__);
10440 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
10441 cds_ssr_unprotect(__func__);
10442
10443 return ret;
10444}
10445
10446/*
10447 * FUNCTION: __wlan_hdd_cfg80211_add_key
10448 * This function is used to initialize the key information
10449 */
10450static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10451 struct net_device *ndev,
10452 u8 key_index, bool pairwise,
10453 const u8 *mac_addr,
10454 struct key_params *params)
10455{
10456 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10457 tCsrRoamSetKey setKey;
10458 int status;
10459 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010460 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010461 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010462 hdd_context_t *pHddCtx;
10463 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10464
10465 ENTER();
10466
Anurag Chouhan6d760662016-02-20 16:05:43 +053010467 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010468 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010469 return -EINVAL;
10470 }
10471
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010472 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10473 hdd_err("invalid session id: %d", pAdapter->sessionId);
10474 return -EINVAL;
10475 }
10476
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010477 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010478 TRACE_CODE_HDD_CFG80211_ADD_KEY,
10479 pAdapter->sessionId, params->key_len));
10480 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10481 status = wlan_hdd_validate_context(pHddCtx);
10482
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010483 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010484 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010485
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010486 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010487 hdd_device_mode_to_string(pAdapter->device_mode),
10488 pAdapter->device_mode);
10489
10490 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010491 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010492
10493 return -EINVAL;
10494 }
10495
10496 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010497 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010498
10499 return -EINVAL;
10500 }
10501
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010502 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010503
10504 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010505 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010506 setKey.keyId = key_index;
10507 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010508 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010509
10510 switch (params->cipher) {
10511 case WLAN_CIPHER_SUITE_WEP40:
10512 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10513 break;
10514
10515 case WLAN_CIPHER_SUITE_WEP104:
10516 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
10517 break;
10518
10519 case WLAN_CIPHER_SUITE_TKIP:
10520 {
10521 u8 *pKey = &setKey.Key[0];
10522 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
10523
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010524 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010525
10526 /*Supplicant sends the 32bytes key in this order
10527
10528 |--------------|----------|----------|
10529 | Tk1 |TX-MIC | RX Mic |
10530 |||--------------|----------|----------|
10531 <---16bytes---><--8bytes--><--8bytes-->
10532
10533 */
10534 /*Sme expects the 32 bytes key to be in the below order
10535
10536 |--------------|----------|----------|
10537 | Tk1 |RX-MIC | TX Mic |
10538 |||--------------|----------|----------|
10539 <---16bytes---><--8bytes--><--8bytes-->
10540 */
10541 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010542 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010543
10544 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010545 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010546
10547 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010548 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010549
10550 break;
10551 }
10552
10553 case WLAN_CIPHER_SUITE_CCMP:
10554 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10555 break;
10556
10557#ifdef FEATURE_WLAN_WAPI
10558 case WLAN_CIPHER_SUITE_SMS4:
10559 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010560 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010561 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10562 mac_addr, params->key,
10563 params->key_len);
10564 return 0;
10565 }
10566#endif
10567
10568#ifdef FEATURE_WLAN_ESE
10569 case WLAN_CIPHER_SUITE_KRK:
10570 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10571 break;
10572#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10573 case WLAN_CIPHER_SUITE_BTK:
10574 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10575 break;
10576#endif
10577#endif
10578
10579#ifdef WLAN_FEATURE_11W
10580 case WLAN_CIPHER_SUITE_AES_CMAC:
10581 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10582 break;
10583#endif
10584
10585 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010586 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010587 return -EOPNOTSUPP;
10588 }
10589
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010590 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010591
10592 if (!pairwise) {
10593 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010594 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010595 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010596 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010597 } else {
10598 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010599 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010600 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010601 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010602 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010603 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010604 /* if a key is already installed, block all subsequent ones */
10605 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010606 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010607 return 0;
10608 }
10609
10610 setKey.keyDirection = eSIR_TX_RX;
10611 /*Set the group key */
10612 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10613 pAdapter->sessionId, &setKey, &roamId);
10614
10615 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010616 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010617 return -EINVAL;
10618 }
10619 /*Save the keys here and call sme_roam_set_key for setting
10620 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010621 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010622 &setKey, sizeof(tCsrRoamSetKey));
10623
10624 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10625 return status;
10626 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010627 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10628 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010629 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10630 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010631 status = wlansap_set_key_sta(
10632 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010633 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010634 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010635 __LINE__, status);
10636 }
10637 }
10638
10639 /* Save the key in ap ctx for use on START_BASS and restart */
10640 if (pairwise ||
10641 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10642 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010643 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010644 sizeof(tCsrRoamSetKey));
10645 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010646 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010647 sizeof(tCsrRoamSetKey));
10648
Krunal Sonib4326f22016-03-10 13:05:51 -080010649 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10650 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010651 hdd_wext_state_t *pWextState =
10652 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10653 hdd_station_ctx_t *pHddStaCtx =
10654 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10655
10656 if (!pairwise) {
10657 /* set group key */
10658 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010659 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010660 __func__, __LINE__);
10661 hdd_perform_roam_set_key_complete(pAdapter);
10662 }
10663 }
10664
10665 pWextState->roamProfile.Keys.KeyLength[key_index] =
10666 (u8) params->key_len;
10667
10668 pWextState->roamProfile.Keys.defaultIndex = key_index;
10669
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010670 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010671 KeyMaterial[key_index][0], params->key,
10672 params->key_len);
10673
10674 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10675
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010676 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010677 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10678 setKey.keyDirection);
10679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010680 /* The supplicant may attempt to set the PTK once pre-authentication
10681 is done. Save the key in the UMAC and include it in the ADD BSS
10682 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010683 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010684 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010685 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010686 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010687 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010688 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010689 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010690 return -EINVAL;
10691 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010692
10693 /* issue set key request to SME */
10694 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10695 pAdapter->sessionId, &setKey, &roamId);
10696
10697 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010698 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010699 pHddStaCtx->roam_info.roamingState =
10700 HDD_ROAM_STATE_NONE;
10701 return -EINVAL;
10702 }
10703
10704 /* in case of IBSS as there was no information available about WEP keys during
10705 * IBSS join, group key intialized with NULL key, so re-initialize group key
10706 * with correct value*/
10707 if ((eCSR_BSS_TYPE_START_IBSS ==
10708 pWextState->roamProfile.BSSType)
10709 &&
10710 !((IW_AUTH_KEY_MGMT_802_1X ==
10711 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10712 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10713 pHddStaCtx->conn_info.authType)
10714 )
10715 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10716 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10717 )
10718 ) {
10719 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010720 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010721
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010722 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010723 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10724 setKey.keyDirection);
10725
10726 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10727 pAdapter->sessionId, &setKey,
10728 &roamId);
10729
10730 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010731 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010732 pHddStaCtx->roam_info.roamingState =
10733 HDD_ROAM_STATE_NONE;
10734 return -EINVAL;
10735 }
10736 }
10737 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010738 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010739 return 0;
10740}
10741
10742static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10743 struct net_device *ndev,
10744 u8 key_index, bool pairwise,
10745 const u8 *mac_addr,
10746 struct key_params *params)
10747{
10748 int ret;
10749 cds_ssr_protect(__func__);
10750 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10751 mac_addr, params);
10752 cds_ssr_unprotect(__func__);
10753
10754 return ret;
10755}
10756
10757/*
10758 * FUNCTION: __wlan_hdd_cfg80211_get_key
10759 * This function is used to get the key information
10760 */
10761static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10762 struct net_device *ndev,
10763 u8 key_index, bool pairwise,
10764 const u8 *mac_addr, void *cookie,
10765 void (*callback)(void *cookie,
10766 struct key_params *)
10767 )
10768{
10769 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10770 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10771 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10772 struct key_params params;
10773
10774 ENTER();
10775
Anurag Chouhan6d760662016-02-20 16:05:43 +053010776 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010777 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010778 return -EINVAL;
10779 }
10780
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010781 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010782 hdd_device_mode_to_string(pAdapter->device_mode),
10783 pAdapter->device_mode);
10784
10785 memset(&params, 0, sizeof(params));
10786
10787 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010788 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010789 key_index);
10790 return -EINVAL;
10791 }
10792
10793 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10794 case eCSR_ENCRYPT_TYPE_NONE:
10795 params.cipher = IW_AUTH_CIPHER_NONE;
10796 break;
10797
10798 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10799 case eCSR_ENCRYPT_TYPE_WEP40:
10800 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10801 break;
10802
10803 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10804 case eCSR_ENCRYPT_TYPE_WEP104:
10805 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10806 break;
10807
10808 case eCSR_ENCRYPT_TYPE_TKIP:
10809 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10810 break;
10811
10812 case eCSR_ENCRYPT_TYPE_AES:
10813 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10814 break;
10815
10816 default:
10817 params.cipher = IW_AUTH_CIPHER_NONE;
10818 break;
10819 }
10820
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010821 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010822 TRACE_CODE_HDD_CFG80211_GET_KEY,
10823 pAdapter->sessionId, params.cipher));
10824
10825 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10826 params.seq_len = 0;
10827 params.seq = NULL;
10828 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10829 callback(cookie, &params);
10830
10831 EXIT();
10832 return 0;
10833}
10834
10835static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10836 struct net_device *ndev,
10837 u8 key_index, bool pairwise,
10838 const u8 *mac_addr, void *cookie,
10839 void (*callback)(void *cookie,
10840 struct key_params *)
10841 )
10842{
10843 int ret;
10844
10845 cds_ssr_protect(__func__);
10846 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10847 mac_addr, cookie, callback);
10848 cds_ssr_unprotect(__func__);
10849
10850 return ret;
10851}
10852
10853/**
10854 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10855 * @wiphy: wiphy interface context
10856 * @ndev: pointer to net device
10857 * @key_index: Key index used in 802.11 frames
10858 * @unicast: true if it is unicast key
10859 * @multicast: true if it is multicast key
10860 *
10861 * This function is required for cfg80211_ops API.
10862 * It is used to delete the key information
10863 * Underlying hardware implementation does not have API to delete the
10864 * encryption key. It is automatically deleted when the peer is
10865 * removed. Hence this function currently does nothing.
10866 * Future implementation may interprete delete key operation to
10867 * replacing the key with a random junk value, effectively making it
10868 * useless.
10869 *
10870 * Return: status code, always 0.
10871 */
10872
10873static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10874 struct net_device *ndev,
10875 u8 key_index,
10876 bool pairwise, const u8 *mac_addr)
10877{
10878 EXIT();
10879 return 0;
10880}
10881
10882/**
10883 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10884 * @wiphy: Pointer to wiphy structure.
10885 * @dev: Pointer to net_device structure.
10886 * @key_index: key index
10887 * @pairwise: pairwise
10888 * @mac_addr: mac address
10889 *
10890 * This is the cfg80211 delete key handler function which invokes
10891 * the internal function @__wlan_hdd_cfg80211_del_key with
10892 * SSR protection.
10893 *
10894 * Return: 0 for success, error number on failure.
10895 */
10896static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10897 struct net_device *dev,
10898 u8 key_index,
10899 bool pairwise, const u8 *mac_addr)
10900{
10901 int ret;
10902
10903 cds_ssr_protect(__func__);
10904 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10905 pairwise, mac_addr);
10906 cds_ssr_unprotect(__func__);
10907
10908 return ret;
10909}
10910
10911/*
10912 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10913 * This function is used to set the default tx key index
10914 */
10915static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10916 struct net_device *ndev,
10917 u8 key_index,
10918 bool unicast, bool multicast)
10919{
10920 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10921 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10922 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10923 hdd_context_t *pHddCtx;
10924 int status;
10925
10926 ENTER();
10927
Anurag Chouhan6d760662016-02-20 16:05:43 +053010928 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010929 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010930 return -EINVAL;
10931 }
10932
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010933 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10934 hdd_err("invalid session id: %d", pAdapter->sessionId);
10935 return -EINVAL;
10936 }
10937
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010938 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010939 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10940 pAdapter->sessionId, key_index));
10941
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010942 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010943 hdd_device_mode_to_string(pAdapter->device_mode),
10944 pAdapter->device_mode, key_index);
10945
10946 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010947 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010948 return -EINVAL;
10949 }
10950
10951 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10952 status = wlan_hdd_validate_context(pHddCtx);
10953
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010954 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010955 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010956
Krunal Sonib4326f22016-03-10 13:05:51 -080010957 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10958 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010959 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10960 pHddStaCtx->conn_info.ucEncryptionType) &&
10961 (eCSR_ENCRYPT_TYPE_AES !=
10962 pHddStaCtx->conn_info.ucEncryptionType)) {
10963 /* If default key index is not same as previous one,
10964 * then update the default key index */
10965
10966 tCsrRoamSetKey setKey;
10967 uint32_t roamId = 0xFF;
10968 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10969
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010970 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010971
10972 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010973 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010974 setKey.keyId = key_index;
10975 setKey.keyLength = Keys->KeyLength[key_index];
10976
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010977 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010978 &Keys->KeyMaterial[key_index][0],
10979 Keys->KeyLength[key_index]);
10980
10981 setKey.keyDirection = eSIR_TX_RX;
10982
Anurag Chouhanc5548422016-02-24 18:33:27 +053010983 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010984 &pHddStaCtx->conn_info.bssId);
10985
10986 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10987 pWextState->roamProfile.EncryptionType.
10988 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10989 /* In the case of dynamic wep supplicant hardcodes DWEP type
10990 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10991 * WEP-40 encryption. In this canse the key length is 5 but the
10992 * encryption type is 104 hence checking the key langht(5) and
10993 * encryption type(104) and switching encryption type to 40*/
10994 pWextState->roamProfile.EncryptionType.
10995 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10996 pWextState->roamProfile.mcEncryptionType.
10997 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10998 }
10999
11000 setKey.encType =
11001 pWextState->roamProfile.EncryptionType.
11002 encryptionType[0];
11003
11004 /* Issue set key request */
11005 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11006 pAdapter->sessionId, &setKey,
11007 &roamId);
11008
11009 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011010 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011011 status);
11012 return -EINVAL;
11013 }
11014 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011015 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011016 /* In SoftAp mode setting key direction for default mode */
11017 if ((eCSR_ENCRYPT_TYPE_TKIP !=
11018 pWextState->roamProfile.EncryptionType.encryptionType[0])
11019 && (eCSR_ENCRYPT_TYPE_AES !=
11020 pWextState->roamProfile.EncryptionType.
11021 encryptionType[0])) {
11022 /* Saving key direction for default key index to TX default */
11023 hdd_ap_ctx_t *pAPCtx =
11024 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11025 pAPCtx->wepKey[key_index].keyDirection =
11026 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053011027 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053011028 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053011029 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011030 }
11031 }
11032
11033 EXIT();
11034 return status;
11035}
11036
11037static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
11038 struct net_device *ndev,
11039 u8 key_index,
11040 bool unicast, bool multicast)
11041{
11042 int ret;
11043 cds_ssr_protect(__func__);
11044 ret =
11045 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
11046 multicast);
11047 cds_ssr_unprotect(__func__);
11048
11049 return ret;
11050}
11051
Abhishek Singhc9941602016-08-09 16:06:22 +053011052/*
11053 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
11054 * @wiphy: wiphy pointer
11055 * @channel: channel of the BSS
11056 * @bssid: Bssid of BSS
11057 * @ssid: Ssid of the BSS
11058 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011059 *
Abhishek Singhc9941602016-08-09 16:06:22 +053011060 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011061 */
Abhishek Singhc9941602016-08-09 16:06:22 +053011062#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011063static
Abhishek Singhc9941602016-08-09 16:06:22 +053011064struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
11065 struct ieee80211_channel *channel, const u8 *bssid,
11066 const u8 *ssid, size_t ssid_len)
11067{
11068 return cfg80211_get_bss(wiphy, channel, bssid,
11069 ssid,
11070 ssid_len,
11071 WLAN_CAPABILITY_ESS,
11072 WLAN_CAPABILITY_ESS);
11073}
11074#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011075static
Abhishek Singhc9941602016-08-09 16:06:22 +053011076struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
11077 struct ieee80211_channel *channel, const u8 *bssid,
11078 const u8 *ssid, size_t ssid_len)
11079{
11080 return cfg80211_get_bss(wiphy, channel, bssid,
11081 ssid,
11082 ssid_len,
11083 IEEE80211_BSS_TYPE_ESS,
11084 IEEE80211_PRIVACY_ANY);
11085}
11086#endif
11087
11088
11089/*
11090 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
11091 * interface that BSS might have been lost.
11092 * @pAdapter: adaptor
11093 * @bssid: bssid which might have been lost
11094 *
11095 * Return: bss which is unlinked from kernel cache
11096 */
11097struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
11098 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011099{
11100 struct net_device *dev = pAdapter->dev;
11101 struct wireless_dev *wdev = dev->ieee80211_ptr;
11102 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011103 struct cfg80211_bss *bss = NULL;
11104
Abhishek Singhc9941602016-08-09 16:06:22 +053011105 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
11106 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011107 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011108 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011109 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053011110 hdd_info("cfg80211_unlink_bss called for BSSID "
11111 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011112 cfg80211_unlink_bss(wiphy, bss);
11113 }
11114 return bss;
11115}
11116
Abhishek Singhc9941602016-08-09 16:06:22 +053011117
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011118/**
11119 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
11120 * @pAdapter: Pointer to adapter
11121 * @bss_desc: Pointer to bss descriptor
11122 *
11123 * This function is used to inform the BSS details to nl80211 interface.
11124 *
11125 * Return: struct cfg80211_bss pointer
11126 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053011127struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
11128 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011129{
11130 /*
11131 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
11132 * already exists in bss data base of cfg80211 for that particular BSS
11133 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
11134 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
11135 * As of now there is no possibility to get the mgmt(probe response)
11136 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
11137 * and passing to cfg80211_inform_bss_frame.
11138 */
11139 struct net_device *dev = pAdapter->dev;
11140 struct wireless_dev *wdev = dev->ieee80211_ptr;
11141 struct wiphy *wiphy = wdev->wiphy;
11142 int chan_no = bss_desc->channelId;
11143#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
11144 qcom_ie_age *qie_age = NULL;
11145 int ie_length =
11146 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
11147#else
11148 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
11149#endif
11150 const char *ie =
11151 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
11152 unsigned int freq;
11153 struct ieee80211_channel *chan;
11154 struct ieee80211_mgmt *mgmt = NULL;
11155 struct cfg80211_bss *bss_status = NULL;
11156 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
11157 int rssi = 0;
11158 hdd_context_t *pHddCtx;
11159 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011160 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011161 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011162
11163 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11164 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011165 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011166 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011167
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011168 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011169 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
11170 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011171 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011172 return NULL;
11173 }
11174
11175 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
11176
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011177 /* Android does not want the timestamp from the frame.
11178 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070011179 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011180 mgmt->u.probe_resp.timestamp =
11181 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011182
11183 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
11184 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
11185
11186#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
11187 /* GPS Requirement: need age ie per entry. Using vendor specific. */
11188 /* Assuming this is the last IE, copy at the end */
11189 ie_length -= sizeof(qcom_ie_age);
11190 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
11191 qie_age->element_id = QCOM_VENDOR_IE_ID;
11192 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
11193 qie_age->oui_1 = QCOM_OUI1;
11194 qie_age->oui_2 = QCOM_OUI2;
11195 qie_age->oui_3 = QCOM_OUI3;
11196 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053011197 /*
11198 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
11199 * all bss related timestamp is in units of ms. Due to this when scan
11200 * results are sent to lowi the scan age is high.To address this,
11201 * send age in units of 1/10 ms.
11202 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011203 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053011204 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011205 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070011206 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
11207 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070011208 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
11209 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011210#endif
11211
11212 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
11213 if (bss_desc->fProbeRsp) {
11214 mgmt->frame_control |=
11215 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
11216 } else {
11217 mgmt->frame_control |=
11218 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
11219 }
11220
11221 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070011222 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011223 freq =
11224 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070011225 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011226 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070011227 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011228 freq =
11229 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070011230 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011231 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011232 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011233 kfree(mgmt);
11234 return NULL;
11235 }
11236
11237 chan = __ieee80211_get_channel(wiphy, freq);
11238 /* When the band is changed on the fly using the GUI, three things are done
11239 * 1. scan abort
11240 * 2. flush scan results from cache
11241 * 3. update the band with the new band user specified (refer to the
11242 * hdd_set_band_helper function) as part of the scan abort, message will be
11243 * queued to PE and we proceed with flushing and changinh the band.
11244 * PE will stop the scanning further and report back the results what ever
11245 * it had till now by calling the call back function.
11246 * if the time between update band and scandone call back is sufficient
11247 * enough the band change reflects in SME, SME validates the channels
11248 * and discards the channels correponding to previous band and calls back
11249 * with zero bss results. but if the time between band update and scan done
11250 * callback is very small then band change will not reflect in SME and SME
11251 * reports to HDD all the channels correponding to previous band.this is due
11252 * to race condition.but those channels are invalid to the new band and so
11253 * this function __ieee80211_get_channel will return NULL.Each time we
11254 * report scan result with this pointer null warning kernel trace is printed.
11255 * if the scan results contain large number of APs continuosly kernel
11256 * warning trace is printed and it will lead to apps watch dog bark.
11257 * So drop the bss and continue to next bss.
11258 */
11259 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053011260 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
11261 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011262 kfree(mgmt);
11263 return NULL;
11264 }
11265
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011266 /* Based on .ini configuration, raw rssi can be reported for bss.
11267 * Raw rssi is typically used for estimating power.
11268 */
11269
11270 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
11271 bss_desc->rssi;
11272
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011273 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053011274 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011275
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053011276 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011277 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070011278 (int)(rssi / 100),
11279 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011280
11281 bss_status =
11282 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
11283 GFP_KERNEL);
11284 kfree(mgmt);
11285 return bss_status;
11286}
11287
11288/**
11289 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
11290 * @pAdapter: Pointer to adapter
11291 * @pRoamInfo: Pointer to roam info
11292 *
11293 * This function is used to update the BSS data base of CFG8011
11294 *
11295 * Return: struct cfg80211_bss pointer
11296 */
11297struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
11298 tCsrRoamInfo *pRoamInfo)
11299{
11300 tCsrRoamConnectedProfile roamProfile;
11301 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11302 struct cfg80211_bss *bss = NULL;
11303
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011304 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
11305 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
11306
11307 if (NULL != roamProfile.pBssDesc) {
11308 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11309 roamProfile.pBssDesc);
11310
11311 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011312 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011313
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080011314 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011315 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011316 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011317 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011318 return bss;
11319}
11320/**
11321 * wlan_hdd_cfg80211_update_bss() - update bss
11322 * @wiphy: Pointer to wiphy
11323 * @pAdapter: Pointer to adapter
11324 * @scan_time: scan request timestamp
11325 *
11326 * Return: zero if success, non-zero otherwise
11327 */
11328int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
11329 hdd_adapter_t *pAdapter,
11330 uint32_t scan_time)
11331{
11332 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11333 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011334 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011335 tScanResultHandle pResult;
11336 struct cfg80211_bss *bss_status = NULL;
11337 hdd_context_t *pHddCtx;
11338 int ret;
11339
11340 ENTER();
11341
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011342 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11343 hdd_err("invalid session id: %d", pAdapter->sessionId);
11344 return -EINVAL;
11345 }
11346
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011347 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011348 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
11349 NO_SESSION, pAdapter->sessionId));
11350
11351 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11352 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011353 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011354 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011355
11356 /* start getting scan results and populate cgf80211 BSS database */
11357 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
11358
11359 /* no scan results */
11360 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011361 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053011362 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011363 }
11364
11365 pScanResult = sme_scan_result_get_first(hHal, pResult);
11366
11367 while (pScanResult) {
11368 /*
11369 * - cfg80211_inform_bss() is not updating ie field of bss
11370 * entry if entry already exists in bss data base of cfg80211
11371 * for that particular BSS ID. Using cfg80211_inform_bss_frame
11372 * to update thebss entry instead of cfg80211_inform_bss,
11373 * But this call expects mgmt packet as input. As of now
11374 * there is no possibility to get the mgmt(probe response)
11375 * frame from PE, converting bss_desc to
11376 * ieee80211_mgmt(probe response) and passing to c
11377 * fg80211_inform_bss_frame.
11378 * - Update BSS only if beacon timestamp is later than
11379 * scan request timestamp.
11380 */
11381 if ((scan_time == 0) ||
11382 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053011383 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011384 bss_status =
11385 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11386 &pScanResult->BssDescriptor);
11387
11388 if (NULL == bss_status) {
11389 hdd_info("NULL returned by cfg80211_inform_bss_frame");
11390 } else {
11391 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011392 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011393 bss_status);
11394 }
11395 } else {
11396 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
11397 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
11398 }
11399 pScanResult = sme_scan_result_get_next(hHal, pResult);
11400 }
11401
11402 sme_scan_result_purge(hHal, pResult);
11403 /*
11404 * For SAP mode, scan is invoked by hostapd during SAP start
11405 * if hostapd is restarted, we need to flush previous scan
11406 * result so that it will reflect environment change
11407 */
Krunal Sonib4326f22016-03-10 13:05:51 -080011408 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011409#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
11410 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
11411#endif
11412 )
11413 sme_scan_flush_result(hHal);
11414
11415 EXIT();
11416 return 0;
11417}
11418
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011419/**
11420 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
11421 * @pAdapter: Pointer to adapter
11422 * @pRoamInfo: Pointer to roam info
11423 * @index: Index
11424 * @preauth: Preauth flag
11425 *
11426 * This function is used to notify the supplicant of a new PMKSA candidate.
11427 *
11428 * Return: 0 for success, non-zero for failure
11429 */
11430int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
11431 tCsrRoamInfo *pRoamInfo,
11432 int index, bool preauth)
11433{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011434 struct net_device *dev = pAdapter->dev;
11435 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
11436
11437 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011438 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011439
11440 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011441 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011442 return -EINVAL;
11443 }
11444
11445 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011446 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011447 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
11448 cfg80211_pmksa_candidate_notify(dev, index,
11449 pRoamInfo->bssid.bytes,
11450 preauth, GFP_KERNEL);
11451 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011452 return 0;
11453}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011454
11455#ifdef FEATURE_WLAN_LFR_METRICS
11456/**
11457 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
11458 * @pAdapter: Pointer to adapter
11459 * @pRoamInfo: Pointer to roam info
11460 *
11461 * 802.11r/LFR metrics reporting function to report preauth initiation
11462 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011463 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011464 */
11465#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011466QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011467 tCsrRoamInfo *pRoamInfo)
11468{
11469 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11470 union iwreq_data wrqu;
11471
11472 ENTER();
11473
11474 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011475 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011476 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011477 }
11478
11479 /* create the event */
11480 memset(&wrqu, 0, sizeof(wrqu));
11481 memset(metrics_notification, 0, sizeof(metrics_notification));
11482
11483 wrqu.data.pointer = metrics_notification;
11484 wrqu.data.length = scnprintf(metrics_notification,
11485 sizeof(metrics_notification),
11486 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
11487 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11488
11489 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11490 metrics_notification);
11491
11492 EXIT();
11493
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011494 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011495}
11496
11497/**
11498 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11499 * @pAdapter: Pointer to adapter
11500 * @pRoamInfo: Pointer to roam info
11501 * @preauth_status: Preauth status
11502 *
11503 * 802.11r/LFR metrics reporting function to report handover initiation
11504 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011505 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011506 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011507QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011508wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
11509 tCsrRoamInfo *pRoamInfo,
11510 bool preauth_status)
11511{
11512 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11513 union iwreq_data wrqu;
11514
11515 ENTER();
11516
11517 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011518 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011519 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011520 }
11521
11522 /* create the event */
11523 memset(&wrqu, 0, sizeof(wrqu));
11524 memset(metrics_notification, 0, sizeof(metrics_notification));
11525
11526 scnprintf(metrics_notification, sizeof(metrics_notification),
11527 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
11528 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11529
11530 if (1 == preauth_status)
11531 strlcat(metrics_notification, " true",
11532 sizeof(metrics_notification));
11533 else
11534 strlcat(metrics_notification, " false",
11535 sizeof(metrics_notification));
11536
11537 wrqu.data.pointer = metrics_notification;
11538 wrqu.data.length = strlen(metrics_notification);
11539
11540 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11541 metrics_notification);
11542
11543 EXIT();
11544
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011545 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011546}
11547
11548/**
11549 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11550 * @pAdapter: Pointer to adapter
11551 * @pRoamInfo: Pointer to roam info
11552 *
11553 * 802.11r/LFR metrics reporting function to report handover initiation
11554 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011555 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011556 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011557QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011558 tCsrRoamInfo *pRoamInfo)
11559{
11560 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11561 union iwreq_data wrqu;
11562
11563 ENTER();
11564
11565 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011566 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011567 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011568 }
11569
11570 /* create the event */
11571 memset(&wrqu, 0, sizeof(wrqu));
11572 memset(metrics_notification, 0, sizeof(metrics_notification));
11573
11574 wrqu.data.pointer = metrics_notification;
11575 wrqu.data.length = scnprintf(metrics_notification,
11576 sizeof(metrics_notification),
11577 "QCOM: LFR_PREAUTH_HANDOVER "
11578 MAC_ADDRESS_STR,
11579 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11580
11581 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11582 metrics_notification);
11583
11584 EXIT();
11585
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011586 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587}
11588#endif
11589
11590/**
11591 * hdd_select_cbmode() - select channel bonding mode
11592 * @pAdapter: Pointer to adapter
11593 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011594 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011595 *
11596 * Return: none
11597 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011598void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11599 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011600{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011601 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011602 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011603 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011604
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011605 /*
11606 * CDS api expects secondary channel for calculating
11607 * the channel params
11608 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011609 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011610 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11611 if (operationChannel >= 1 && operationChannel <= 5)
11612 sec_ch = operationChannel + 4;
11613 else if (operationChannel >= 6 && operationChannel <= 13)
11614 sec_ch = operationChannel - 4;
11615 }
11616
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011617 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011618 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011619
11620 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011621 eHddDot11Mode hdd_dot11_mode;
11622 uint8_t iniDot11Mode =
11623 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11624
11625 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11626 switch (iniDot11Mode) {
11627 case eHDD_DOT11_MODE_AUTO:
11628 case eHDD_DOT11_MODE_11ac:
11629 case eHDD_DOT11_MODE_11ac_ONLY:
11630 if (sme_is_feature_supported_by_fw(DOT11AC))
11631 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11632 else
11633 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11634 break;
11635 case eHDD_DOT11_MODE_11n:
11636 case eHDD_DOT11_MODE_11n_ONLY:
11637 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11638 break;
11639 default:
11640 hdd_dot11_mode = iniDot11Mode;
11641 break;
11642 }
11643 ch_info->channel_width = ch_params->ch_width;
11644 ch_info->phy_mode =
11645 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011646 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011647 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011648 hdd_info("ch_info width %d, phymode %d channel %d",
11649 ch_info->channel_width, ch_info->phy_mode,
11650 ch_info->channel);
11651 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011652}
11653
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011654/**
11655 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11656 * @adapter: STA adapter
11657 * @roam_profile: STA roam profile
11658 *
11659 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11660 *
11661 * Return: false if sta-sap conc is not allowed, else return true
11662 */
11663static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11664 tCsrRoamProfile *roam_profile)
11665{
11666 hdd_context_t *hdd_ctx;
11667 hdd_adapter_t *ap_adapter;
11668 hdd_ap_ctx_t *hdd_ap_ctx;
11669 hdd_hostapd_state_t *hostapd_state;
11670 uint8_t channel = 0;
11671 QDF_STATUS status;
11672
11673 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11674 if (!hdd_ctx) {
11675 hdd_err("HDD context is NULL");
11676 return true;
11677 }
11678
11679 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11680 /* probably no sap running, no handling required */
11681 if (ap_adapter == NULL)
11682 return true;
11683
11684 /*
11685 * sap is not in started state, so it is fine to go ahead with sta.
11686 * if sap is currently doing CAC then don't allow sta to go further.
11687 */
11688 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11689 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11690 return true;
11691
11692 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11693 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11694 return false;
11695 }
11696
11697 /*
11698 * log and return error, if we allow STA to go through, we don't
11699 * know what is going to happen better stop sta connection
11700 */
11701 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11702 if (NULL == hdd_ap_ctx) {
11703 hdd_err("AP context not found");
11704 return false;
11705 }
11706
11707 /* sap is on non-dfs channel, nothing to handle */
11708 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11709 hdd_info("sap is on non-dfs channel, sta is allowed");
11710 return true;
11711 }
11712 /*
11713 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011714 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011715 */
11716 status = cds_get_channel_from_scan_result(adapter,
11717 roam_profile, &channel);
11718
Nitesh Shah59774522016-09-16 15:14:21 +053011719 /*
11720 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11721 * channels for roaming case.
11722 */
11723 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11724 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11725 return true;
11726 }
11727
11728 /*
11729 * If channel is 0 or DFS then better to call pcl and find out the
11730 * best channel. If channel is non-dfs 5 GHz then better move SAP
11731 * to STA's channel to make scc, so we have room for 3port MCC
11732 * scenario.
11733 */
11734 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011735 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11736 true);
11737
11738 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11739 qdf_event_reset(&hostapd_state->qdf_event);
11740 status = wlansap_set_channel_change_with_csa(
11741 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11742 hdd_ap_ctx->sapConfig.ch_width_orig);
11743
11744 if (QDF_STATUS_SUCCESS != status) {
11745 hdd_err("Set channel with CSA IE failed, can't allow STA");
11746 return false;
11747 }
11748
11749 /*
11750 * wait here for SAP to finish the channel switch. When channel
11751 * switch happens, SAP sends few beacons with CSA_IE. After
11752 * successfully Transmission of those beacons, it will move its
11753 * state from started to disconnected and move to new channel.
11754 * once it moves to new channel, sap again moves its state
11755 * machine from disconnected to started and set this event.
11756 * wait for 10 secs to finish this.
11757 */
11758 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11759 if (!QDF_IS_STATUS_SUCCESS(status)) {
11760 hdd_err("wait for qdf_event failed, STA not allowed!!");
11761 return false;
11762 }
11763
11764 return true;
11765}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011766
Krunal Soni31949422016-07-29 17:17:53 -070011767/**
11768 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011769 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011770 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011771 * @ssid_len: Length of ssid
11772 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011773 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011774 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011775 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011776 *
11777 * This function is used to start the association process
11778 *
11779 * Return: 0 for success, non-zero for failure
11780 */
Krunal Soni31949422016-07-29 17:17:53 -070011781static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011782 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011783 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011784 u8 operatingChannel,
11785 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011786{
11787 int status = 0;
11788 hdd_wext_state_t *pWextState;
11789 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011790 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011791 uint32_t roamId;
11792 tCsrRoamProfile *pRoamProfile;
11793 eCsrAuthType RSNAuthType;
11794 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011795 uint8_t channel = 0;
11796 struct sir_hw_mode_params hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011797
11798 ENTER();
11799
11800 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11801 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011802 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011803
11804 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011805 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011806 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011807
11808 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011809 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011810 return -EINVAL;
11811 }
11812
11813 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011814 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11815 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011816
11817 if (pRoamProfile) {
11818 hdd_station_ctx_t *pHddStaCtx;
11819 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11820
11821 if (HDD_WMM_USER_MODE_NO_QOS ==
11822 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11823 /*QoS not enabled in cfg file */
11824 pRoamProfile->uapsd_mask = 0;
11825 } else {
11826 /*QoS enabled, update uapsd mask from cfg file */
11827 pRoamProfile->uapsd_mask =
11828 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11829 }
11830
11831 pRoamProfile->SSIDs.numOfSSIDs = 1;
11832 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011833 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011835 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011836 ssid, ssid_len);
11837
Deepak Dhamdherea2785822016-11-17 01:17:45 -080011838 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011839 if (bssid) {
11840 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011841 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011842 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011843 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011844 /*
11845 * Save BSSID in seperate variable as
11846 * pRoamProfile's BSSID is getting zeroed out in the
11847 * association process. In case of join failure
11848 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011849 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011850 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011851 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011852 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011853 } else if (bssid_hint) {
11854 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011855 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011856 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011857 /*
11858 * Save BSSID in a separate variable as
11859 * pRoamProfile's BSSID is getting zeroed out in the
11860 * association process. In case of join failure
11861 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011862 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011863 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011864 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011865 hdd_info("bssid_hint is given by upper layer %pM",
11866 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011867 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011868 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011869 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011870 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011871 }
11872
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011873 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011874 pRoamProfile->SSIDs.SSIDList->SSID.length,
11875 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11876 operatingChannel);
11877
11878 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11879 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011880 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011881 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11882 }
11883#ifdef FEATURE_WLAN_WAPI
11884 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011885 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011886 switch (pAdapter->wapi_info.wapiAuthMode) {
11887 case WAPI_AUTH_MODE_PSK:
11888 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011889 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011890 pAdapter->wapi_info.wapiAuthMode);
11891 pRoamProfile->AuthType.authType[0] =
11892 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11893 break;
11894 }
11895 case WAPI_AUTH_MODE_CERT:
11896 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011897 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011898 pAdapter->wapi_info.wapiAuthMode);
11899 pRoamProfile->AuthType.authType[0] =
11900 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11901 break;
11902 }
11903 } /* End of switch */
11904 if (pAdapter->wapi_info.wapiAuthMode ==
11905 WAPI_AUTH_MODE_PSK
11906 || pAdapter->wapi_info.wapiAuthMode ==
11907 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011908 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011909 pRoamProfile->AuthType.numEntries = 1;
11910 pRoamProfile->EncryptionType.numEntries = 1;
11911 pRoamProfile->EncryptionType.encryptionType[0] =
11912 eCSR_ENCRYPT_TYPE_WPI;
11913 pRoamProfile->mcEncryptionType.numEntries = 1;
11914 pRoamProfile->mcEncryptionType.
11915 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11916 }
11917 }
Krunal Soni31949422016-07-29 17:17:53 -070011918#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011919#ifdef WLAN_FEATURE_GTK_OFFLOAD
11920 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011921 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11922 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011923 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11924 sizeof(tSirGtkOffloadParams));
11925 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11926 GTK_OFFLOAD_DISABLE;
11927 }
11928#endif
11929 pRoamProfile->csrPersona = pAdapter->device_mode;
11930
11931 if (operatingChannel) {
11932 pRoamProfile->ChannelInfo.ChannelList =
11933 &operatingChannel;
11934 pRoamProfile->ChannelInfo.numOfChannels = 1;
11935 } else {
11936 pRoamProfile->ChannelInfo.ChannelList = NULL;
11937 pRoamProfile->ChannelInfo.numOfChannels = 0;
11938 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011939 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011940 && operatingChannel) {
11941 /*
11942 * Need to post the IBSS power save parameters
11943 * to WMA. WMA will configure this parameters
11944 * to firmware if power save is enabled by the
11945 * firmware.
11946 */
11947 status = hdd_set_ibss_power_save_params(pAdapter);
11948
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011949 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011950 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011951 return -EINVAL;
11952 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011953 pRoamProfile->ch_params.ch_width =
11954 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011955 /*
11956 * In IBSS mode while operating in 2.4 GHz,
11957 * the device supports only 20 MHz.
11958 */
11959 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11960 pRoamProfile->ch_params.ch_width =
11961 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011962 hdd_select_cbmode(pAdapter, operatingChannel,
11963 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011964 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011965 /*
11966 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11967 * or pmf=2 is an explicit configuration in the supplicant
11968 * configuration, drop the connection request.
11969 */
11970 if (pWextState->roamProfile.MFPEnabled &&
11971 !(pWextState->roamProfile.MFPRequired ||
11972 pWextState->roamProfile.MFPCapable)) {
11973 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11974 pWextState->roamProfile.MFPEnabled,
11975 pWextState->roamProfile.MFPRequired,
11976 pWextState->roamProfile.MFPCapable);
11977 return -EINVAL;
11978 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011979
Krunal Soni3091bcc2016-06-23 12:28:21 -070011980 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011981 hdd_err("Connection refused: conn in progress");
11982 return -EINVAL;
11983 }
11984
Krunal Soni31949422016-07-29 17:17:53 -070011985 /*
11986 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011987 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011988 * enhancements, the supplicant is not issuing the scan command
11989 * now. So the unicast frames which are sent from the host are
11990 * not having the additional IEs. If it is P2P CLIENT and there
11991 * is no additional IE present in roamProfile, then use the
11992 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011993 */
11994
Krunal Sonib4326f22016-03-10 13:05:51 -080011995 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011996 (!pRoamProfile->pAddIEScan)) {
11997 pRoamProfile->pAddIEScan =
11998 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11999 pRoamProfile->nAddIEScanLength =
12000 pAdapter->scan_info.scanAddIE.length;
12001 }
12002 /*
12003 * When policy manager is enabled from ini file, we shouldn't
12004 * check for other concurrency rules.
12005 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070012006 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080012007 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012008 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012009 pAdapter, pRoamProfile, &roamId))
12010 return 0;
12011 }
12012
Krunal Soni3091bcc2016-06-23 12:28:21 -070012013 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012014 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
12015 pRoamProfile))) {
12016 hdd_err("sap-sta conc will fail, can't allow sta");
12017 hdd_conn_set_connection_state(pAdapter,
12018 eConnectionState_NotConnected);
12019 return -ENOMEM;
12020 }
12021
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012022 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012023 if (!sme_config) {
12024 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012025 hdd_conn_set_connection_state(pAdapter,
12026 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012027 return -ENOMEM;
12028 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012029 sme_get_config_param(pHddCtx->hHal, sme_config);
12030 /* These values are not sessionized. So, any change in these SME
12031 * configs on an older or parallel interface will affect the
12032 * cb mode. So, restoring the default INI params before starting
12033 * interfaces such as sta, cli etc.,
12034 */
12035 sme_config->csrConfig.channelBondingMode5GHz =
12036 pHddCtx->config->nChannelBondingMode5GHz;
12037 sme_config->csrConfig.channelBondingMode24GHz =
12038 pHddCtx->config->nChannelBondingMode24GHz;
12039 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012040 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053012041 /*
12042 * Change conn_state to connecting before sme_roam_connect(),
12043 * because sme_roam_connect() has a direct path to call
12044 * hdd_sme_roam_callback(), which will change the conn_state
12045 * If direct path, conn_state will be accordingly changed to
12046 * NotConnected or Associated by either
12047 * hdd_association_completion_handler() or
12048 * hdd_dis_connect_handler() in sme_RoamCallback()if
12049 * sme_RomConnect is to be queued,
12050 * Connecting state will remain until it is completed.
12051 *
12052 * If connection state is not changed, connection state will
12053 * remain in eConnectionState_NotConnected state.
12054 * In hdd_association_completion_handler, "hddDisconInProgress"
12055 * is set to true if conn state is
12056 * eConnectionState_NotConnected.
12057 * If "hddDisconInProgress" is set to true then cfg80211 layer
12058 * is not informed of connect result indication which
12059 * is an issue.
12060 */
12061 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053012062 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053012063 hdd_conn_set_connection_state(pAdapter,
12064 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012065
Komal Seelama89be8d2016-09-29 11:09:26 +053012066 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
12067 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012068 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12069 pAdapter->sessionId, pRoamProfile,
12070 &roamId);
12071
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012072 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080012073 (QDF_STA_MODE == pAdapter->device_mode ||
12074 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012075 hdd_err("sme_roam_connect (session %d) failed with "
12076 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012077 pAdapter->sessionId, status);
12078 /* change back to NotAssociated */
12079 hdd_conn_set_connection_state(pAdapter,
12080 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053012081 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
12082 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012083 }
12084
12085 pRoamProfile->ChannelInfo.ChannelList = NULL;
12086 pRoamProfile->ChannelInfo.numOfChannels = 0;
12087
Nitesh Shah044fd672016-10-13 18:53:25 +053012088 if (!QDF_IS_STATUS_SUCCESS(
12089 wma_get_current_hw_mode(&hw_mode))) {
12090 hdd_err("wma_get_current_hw_mode failed");
12091 return status;
12092 }
12093
12094 if ((QDF_STA_MODE == pAdapter->device_mode)
12095 && hw_mode.dbs_cap) {
12096 cds_get_channel_from_scan_result(pAdapter,
12097 pRoamProfile, &channel);
12098 if (channel)
12099 cds_checkn_update_hw_mode_single_mac_mode
12100 (channel);
12101 }
12102
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012103 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012104 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012105 return -EINVAL;
12106 }
12107 EXIT();
12108 return status;
12109}
12110
12111/**
12112 * wlan_hdd_cfg80211_set_auth_type() - set auth type
12113 * @pAdapter: Pointer to adapter
12114 * @auth_type: Auth type
12115 *
12116 * This function is used to set the authentication type (OPEN/SHARED).
12117 *
12118 * Return: 0 for success, non-zero for failure
12119 */
12120static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
12121 enum nl80211_auth_type auth_type)
12122{
12123 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12124 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12125
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012126 /*set authentication type */
12127 switch (auth_type) {
12128 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012129 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012130 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
12131 break;
12132
12133 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012134 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012135 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012136 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12137 break;
12138
12139 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012140 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012141 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
12142 break;
12143#ifdef FEATURE_WLAN_ESE
12144 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012145 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012146 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
12147 break;
12148#endif
12149
12150 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012151 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012152 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
12153 return -EINVAL;
12154 }
12155
12156 pWextState->roamProfile.AuthType.authType[0] =
12157 pHddStaCtx->conn_info.authType;
12158 return 0;
12159}
12160
12161/**
12162 * wlan_hdd_set_akm_suite() - set key management type
12163 * @pAdapter: Pointer to adapter
12164 * @key_mgmt: Key management type
12165 *
12166 * This function is used to set the key mgmt type(PSK/8021x).
12167 *
12168 * Return: 0 for success, non-zero for failure
12169 */
12170static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
12171{
12172 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12173
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
12175#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
12176 /*set key mgmt type */
12177 switch (key_mgmt) {
12178 case WLAN_AKM_SUITE_PSK:
12179 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012180 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012181 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012182 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
12183 break;
12184
12185 case WLAN_AKM_SUITE_8021X_SHA256:
12186 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012187 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012188 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012189 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
12190 break;
12191#ifdef FEATURE_WLAN_ESE
12192#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
12193#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
12194 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012195 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012196 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
12197 break;
12198#endif
12199#ifndef WLAN_AKM_SUITE_OSEN
12200#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
12201#endif
12202 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012203 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012204 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
12205 break;
12206
12207 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012208 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012209 return -EINVAL;
12210
12211 }
12212 return 0;
12213}
12214
12215/**
12216 * wlan_hdd_cfg80211_set_cipher() - set encryption type
12217 * @pAdapter: Pointer to adapter
12218 * @cipher: Cipher type
12219 * @ucast: Unicast flag
12220 *
12221 * This function is used to set the encryption type
12222 * (NONE/WEP40/WEP104/TKIP/CCMP).
12223 *
12224 * Return: 0 for success, non-zero for failure
12225 */
12226static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
12227 u32 cipher, bool ucast)
12228{
12229 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12230 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12231 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12232
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012233 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012234 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012235 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12236 } else {
12237
12238 /*set encryption method */
12239 switch (cipher) {
12240 case IW_AUTH_CIPHER_NONE:
12241 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12242 break;
12243
12244 case WLAN_CIPHER_SUITE_WEP40:
12245 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
12246 break;
12247
12248 case WLAN_CIPHER_SUITE_WEP104:
12249 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
12250 break;
12251
12252 case WLAN_CIPHER_SUITE_TKIP:
12253 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
12254 break;
12255
12256 case WLAN_CIPHER_SUITE_CCMP:
12257 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12258 break;
12259#ifdef FEATURE_WLAN_WAPI
12260 case WLAN_CIPHER_SUITE_SMS4:
12261 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
12262 break;
12263#endif
12264
12265#ifdef FEATURE_WLAN_ESE
12266 case WLAN_CIPHER_SUITE_KRK:
12267 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
12268 break;
12269#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12270 case WLAN_CIPHER_SUITE_BTK:
12271 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
12272 break;
12273#endif
12274#endif
12275 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012276 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012277 return -EOPNOTSUPP;
12278 }
12279 }
12280
12281 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012282 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012283 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12284 pWextState->roamProfile.EncryptionType.numEntries = 1;
12285 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12286 encryptionType;
12287 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012288 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012289 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
12290 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
12291 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
12292 encryptionType;
12293 }
12294
12295 return 0;
12296}
12297
12298/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012299 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
12300 * @wext_state: Pointer to wext state
12301 * @gen_ie: Pointer to IE data
12302 * @len: length of IE data
12303 *
12304 * Return: 0 for success, non-zero for failure
12305 */
12306static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
12307 const uint8_t *gen_ie, uint16_t len)
12308{
12309 uint16_t cur_add_ie_len =
12310 wext_state->assocAddIE.length;
12311
12312 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12313 (wext_state->assocAddIE.length + len)) {
12314 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
12315 QDF_ASSERT(0);
12316 return -ENOMEM;
12317 }
12318 memcpy(wext_state->assocAddIE.addIEdata +
12319 cur_add_ie_len, gen_ie, len);
12320 wext_state->assocAddIE.length += len;
12321
12322 wext_state->roamProfile.pAddIEAssoc =
12323 wext_state->assocAddIE.addIEdata;
12324 wext_state->roamProfile.nAddIEAssocLength =
12325 wext_state->assocAddIE.length;
12326 return 0;
12327}
12328
12329/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012330 * wlan_hdd_cfg80211_set_ie() - set IEs
12331 * @pAdapter: Pointer to adapter
12332 * @ie: Pointer ot ie
12333 * @ie: IE length
12334 *
12335 * Return: 0 for success, non-zero for failure
12336 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012337static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012338 size_t ie_len)
12339{
12340 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12341 const uint8_t *genie = ie;
12342 uint16_t remLen = ie_len;
12343#ifdef FEATURE_WLAN_WAPI
12344 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
12345 u16 *tmp;
12346 uint16_t akmsuiteCount;
12347 int *akmlist;
12348#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012349 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012350
12351 /* clear previous assocAddIE */
12352 pWextState->assocAddIE.length = 0;
12353 pWextState->roamProfile.bWPSAssociation = false;
12354 pWextState->roamProfile.bOSENAssociation = false;
12355
12356 while (remLen >= 2) {
12357 uint16_t eLen = 0;
12358 uint8_t elementId;
12359 elementId = *genie++;
12360 eLen = *genie++;
12361 remLen -= 2;
12362
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012363 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012364
12365 switch (elementId) {
12366 case DOT11F_EID_WPA:
12367 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 -070012368 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012369 return -EINVAL;
12370 } else if (0 ==
12371 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
12372 uint16_t curAddIELen =
12373 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012374 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012375
12376 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12377 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012378 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012379 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012380 return -ENOMEM;
12381 }
12382 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12383 memcpy(pWextState->assocAddIE.addIEdata +
12384 curAddIELen, genie - 2, eLen + 2);
12385 pWextState->assocAddIE.length += eLen + 2;
12386
12387 pWextState->roamProfile.bWPSAssociation = true;
12388 pWextState->roamProfile.pAddIEAssoc =
12389 pWextState->assocAddIE.addIEdata;
12390 pWextState->roamProfile.nAddIEAssocLength =
12391 pWextState->assocAddIE.length;
12392 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012393 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012394 memset(pWextState->WPARSNIE, 0,
12395 MAX_WPA_RSN_IE_LEN);
12396 memcpy(pWextState->WPARSNIE, genie - 2,
12397 (eLen + 2));
12398 pWextState->roamProfile.pWPAReqIE =
12399 pWextState->WPARSNIE;
12400 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
12401 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
12402 P2P_OUI_TYPE_SIZE))) {
12403 uint16_t curAddIELen =
12404 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012405 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012406
12407 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12408 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012409 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012410 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012411 return -ENOMEM;
12412 }
12413 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12414 memcpy(pWextState->assocAddIE.addIEdata +
12415 curAddIELen, genie - 2, eLen + 2);
12416 pWextState->assocAddIE.length += eLen + 2;
12417
12418 pWextState->roamProfile.pAddIEAssoc =
12419 pWextState->assocAddIE.addIEdata;
12420 pWextState->roamProfile.nAddIEAssocLength =
12421 pWextState->assocAddIE.length;
12422 }
12423#ifdef WLAN_FEATURE_WFD
12424 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
12425 WFD_OUI_TYPE_SIZE)) &&
12426 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080012427 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012428 pAdapter->device_mode)) {
12429 uint16_t curAddIELen =
12430 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012431 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012432
12433 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12434 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012435 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012436 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012437 return -ENOMEM;
12438 }
12439 /* WFD IE is saved to Additional IE ; it should
12440 * be accumulated to handle WPS IE + P2P IE +
12441 * WFD IE */
12442 memcpy(pWextState->assocAddIE.addIEdata +
12443 curAddIELen, genie - 2, eLen + 2);
12444 pWextState->assocAddIE.length += eLen + 2;
12445
12446 pWextState->roamProfile.pAddIEAssoc =
12447 pWextState->assocAddIE.addIEdata;
12448 pWextState->roamProfile.nAddIEAssocLength =
12449 pWextState->assocAddIE.length;
12450 }
12451#endif
12452 /* Appending HS 2.0 Indication Element in Assiciation Request */
12453 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
12454 HS20_OUI_TYPE_SIZE))) {
12455 uint16_t curAddIELen =
12456 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012457 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012458
12459 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12460 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012461 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012462 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012463 return -ENOMEM;
12464 }
12465 memcpy(pWextState->assocAddIE.addIEdata +
12466 curAddIELen, genie - 2, eLen + 2);
12467 pWextState->assocAddIE.length += eLen + 2;
12468
12469 pWextState->roamProfile.pAddIEAssoc =
12470 pWextState->assocAddIE.addIEdata;
12471 pWextState->roamProfile.nAddIEAssocLength =
12472 pWextState->assocAddIE.length;
12473 }
12474 /* Appending OSEN Information Element in Assiciation Request */
12475 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
12476 OSEN_OUI_TYPE_SIZE))) {
12477 uint16_t curAddIELen =
12478 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012479 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012480
12481 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12482 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012483 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012484 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012485 return -ENOMEM;
12486 }
12487 memcpy(pWextState->assocAddIE.addIEdata +
12488 curAddIELen, genie - 2, eLen + 2);
12489 pWextState->assocAddIE.length += eLen + 2;
12490
12491 pWextState->roamProfile.bOSENAssociation = true;
12492 pWextState->roamProfile.pAddIEAssoc =
12493 pWextState->assocAddIE.addIEdata;
12494 pWextState->roamProfile.nAddIEAssocLength =
12495 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012496 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
12497 MBO_OUI_TYPE_SIZE))){
12498 hdd_info("Set MBO IE(len %d)", eLen + 2);
12499 status = wlan_hdd_add_assoc_ie(pWextState,
12500 genie - 2, eLen + 2);
12501 if (status)
12502 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012503 } else {
12504 uint16_t add_ie_len =
12505 pWextState->assocAddIE.length;
12506
12507 hdd_info("Set OSEN IE(len %d)", eLen + 2);
12508
12509 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12510 (pWextState->assocAddIE.length + eLen)) {
12511 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012512 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012513 return -ENOMEM;
12514 }
12515
12516 memcpy(pWextState->assocAddIE.addIEdata +
12517 add_ie_len, genie - 2, eLen + 2);
12518 pWextState->assocAddIE.length += eLen + 2;
12519
12520 pWextState->roamProfile.pAddIEAssoc =
12521 pWextState->assocAddIE.addIEdata;
12522 pWextState->roamProfile.nAddIEAssocLength =
12523 pWextState->assocAddIE.length;
12524 }
12525 break;
12526 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012527 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012528 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
12529 memcpy(pWextState->WPARSNIE, genie - 2,
12530 (eLen + 2));
12531 pWextState->roamProfile.pRSNReqIE =
12532 pWextState->WPARSNIE;
12533 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12534 break;
12535 /*
12536 * Appending Extended Capabilities with Interworking bit set
12537 * in Assoc Req.
12538 *
12539 * In assoc req this EXT Cap will only be taken into account if
12540 * interworkingService bit is set to 1. Currently
12541 * driver is only interested in interworkingService capability
12542 * from supplicant. If in future any other EXT Cap info is
12543 * required from supplicat, it needs to be handled while
12544 * sending Assoc Req in LIM.
12545 */
12546 case DOT11F_EID_EXTCAP:
12547 {
12548 uint16_t curAddIELen =
12549 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012550 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012551
12552 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12553 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012554 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012555 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012556 return -ENOMEM;
12557 }
12558 memcpy(pWextState->assocAddIE.addIEdata +
12559 curAddIELen, genie - 2, eLen + 2);
12560 pWextState->assocAddIE.length += eLen + 2;
12561
12562 pWextState->roamProfile.pAddIEAssoc =
12563 pWextState->assocAddIE.addIEdata;
12564 pWextState->roamProfile.nAddIEAssocLength =
12565 pWextState->assocAddIE.length;
12566 break;
12567 }
12568#ifdef FEATURE_WLAN_WAPI
12569 case WLAN_EID_WAPI:
12570 /* Setting WAPI Mode to ON=1 */
12571 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012572 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012573 tmp = (u16 *) ie;
12574 tmp = tmp + 2; /* Skip element Id and Len, Version */
12575 akmsuiteCount = WPA_GET_LE16(tmp);
12576 tmp = tmp + 1;
12577 akmlist = (int *)(tmp);
12578 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12579 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12580 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012581 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012582 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012583 return -EINVAL;
12584 }
12585
12586 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012587 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012588 pAdapter->wapi_info.wapiAuthMode =
12589 WAPI_AUTH_MODE_PSK;
12590 }
12591 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012592 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012593 pAdapter->wapi_info.wapiAuthMode =
12594 WAPI_AUTH_MODE_CERT;
12595 }
12596 break;
12597#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012598 case DOT11F_EID_SUPPOPERATINGCLASSES:
12599 {
12600 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12601 status = wlan_hdd_add_assoc_ie(pWextState,
12602 genie - 2, eLen + 2);
12603 if (status)
12604 return status;
12605 break;
12606 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012607 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012608 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012609 /* when Unknown IE is received we should break and continue
12610 * to the next IE in the buffer instead we were returning
12611 * so changing this to break */
12612 break;
12613 }
12614 genie += eLen;
12615 remLen -= eLen;
12616 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012617 return 0;
12618}
12619
12620/**
12621 * hdd_is_wpaie_present() - check for WPA ie
12622 * @ie: Pointer to ie
12623 * @ie_len: Ie length
12624 *
12625 * Parse the received IE to find the WPA IE
12626 *
12627 * Return: true if wpa ie is found else false
12628 */
12629static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12630{
12631 uint8_t eLen = 0;
12632 uint16_t remLen = ie_len;
12633 uint8_t elementId = 0;
12634
12635 while (remLen >= 2) {
12636 elementId = *ie++;
12637 eLen = *ie++;
12638 remLen -= 2;
12639 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012640 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012641 return false;
12642 }
12643 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12644 /* OUI - 0x00 0X50 0XF2
12645 * WPA Information Element - 0x01
12646 * WPA version - 0x01
12647 */
12648 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12649 return true;
12650 }
12651 ie += eLen;
12652 remLen -= eLen;
12653 }
12654 return false;
12655}
12656
12657/**
12658 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12659 * @pAdapter: Pointer to adapter
12660 * @req: Pointer to security parameters
12661 *
12662 * Return: 0 for success, non-zero for failure
12663 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012664static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12665 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012666{
12667 int status = 0;
12668 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12669 ENTER();
12670
12671 /*set wpa version */
12672 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12673
12674 if (req->crypto.wpa_versions) {
12675 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12676 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12677 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12678 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12679 }
12680 }
12681
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012682 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012683
12684 /*set authentication type */
12685 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12686
12687 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012688 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012689 return status;
12690 }
12691
12692 /*set key mgmt type */
12693 if (req->crypto.n_akm_suites) {
12694 status =
12695 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12696 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012697 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012698 return status;
12699 }
12700 }
12701
12702 /*set pairwise cipher type */
12703 if (req->crypto.n_ciphers_pairwise) {
12704 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12705 req->crypto.
12706 ciphers_pairwise[0],
12707 true);
12708 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012709 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012710 return status;
12711 }
12712 } else {
12713 /*Reset previous cipher suite to none */
12714 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12715 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012716 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012717 return status;
12718 }
12719 }
12720
12721 /*set group cipher type */
12722 status =
12723 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12724 false);
12725
12726 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012727 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012728 return status;
12729 }
12730#ifdef WLAN_FEATURE_11W
12731 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12732#endif
12733
12734 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12735 if (req->ie_len) {
12736 status =
12737 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12738 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012739 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012740 return status;
12741 }
12742 }
12743
12744 /*incase of WEP set default key information */
12745 if (req->key && req->key_len) {
12746 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12747 || (WLAN_CIPHER_SUITE_WEP104 ==
12748 req->crypto.ciphers_pairwise[0])
12749 ) {
12750 if (IW_AUTH_KEY_MGMT_802_1X
12751 ==
12752 (pWextState->
12753 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012754 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012755 return -EOPNOTSUPP;
12756 } else {
12757 u8 key_len = req->key_len;
12758 u8 key_idx = req->key_idx;
12759
12760 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12761 key_len)
12762 && (CSR_MAX_NUM_KEY > key_idx)
12763 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012764 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012765 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012766 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012767 Keys.
12768 KeyMaterial[key_idx][0],
12769 req->key, key_len);
12770 pWextState->roamProfile.Keys.
12771 KeyLength[key_idx] = (u8) key_len;
12772 pWextState->roamProfile.Keys.
12773 defaultIndex = (u8) key_idx;
12774 }
12775 }
12776 }
12777 }
12778
12779 return status;
12780}
12781
12782/**
12783 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12784 * @pAdapter: Pointer to adapter
12785 *
12786 * This function is used to disconnect from previous connection
12787 *
12788 * Return: 0 for success, non-zero for failure
12789 */
12790static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12791{
12792 unsigned long rc;
12793 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012794 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012795
12796 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12797
Jeff Johnson9edf9572016-10-03 15:24:49 -070012798 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012799 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12800 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12801 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012802 hdd_conn_set_connection_state(pAdapter,
12803 eConnectionState_Disconnecting);
12804 /* Issue disconnect to CSR */
12805 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012806
12807 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12808 pAdapter->sessionId,
12809 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12810 /*
12811 * Wait here instead of returning directly, this will block the
12812 * next connect command and allow processing of the scan for
12813 * ssid and the previous connect command in CSR. Else we might
12814 * hit some race conditions leading to SME and HDD out of sync.
12815 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012816 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012817 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12818 } else if (0 != status) {
12819 hdd_err("csrRoamDisconnect failure, returned %d",
12820 (int)status);
12821 pHddStaCtx->staDebugState = status;
12822 result = -EINVAL;
12823 goto disconnected;
12824 }
12825
12826 rc = wait_for_completion_timeout(
12827 &pAdapter->disconnect_comp_var,
12828 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012829 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012830 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12831 pAdapter->sessionId, pHddStaCtx->staDebugState);
12832 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012833 }
12834 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012835 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012836 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012837 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012838 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012839 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012840 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012841 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012842 }
12843 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012844disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012845 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12846 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012847}
12848
12849/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012850 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12851 * @adapter: Pointer to the HDD adapter
12852 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012853 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012854 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012855 * This function will start reassociation if prev_bssid is set and bssid/
12856 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012857 *
Naveen Rawat07332902016-07-27 09:13:17 -070012858 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012859 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012860#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12861 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012862static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12863 struct cfg80211_connect_params *req,
12864 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012865{
Naveen Rawat07332902016-07-27 09:13:17 -070012866 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012867 const uint8_t *bssid = NULL;
12868 uint16_t channel = 0;
12869
12870 if (req->bssid)
12871 bssid = req->bssid;
12872 else if (req->bssid_hint)
12873 bssid = req->bssid_hint;
12874
12875 if (req->channel)
12876 channel = req->channel->hw_value;
12877 else if (req->channel_hint)
12878 channel = req->channel_hint->hw_value;
12879
12880 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012881 reassoc = true;
12882 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012883 channel, MAC_ADDR_ARRAY(bssid));
12884 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012885 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012886 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012887 }
Naveen Rawat07332902016-07-27 09:13:17 -070012888 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012889}
12890#else
Naveen Rawat07332902016-07-27 09:13:17 -070012891static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12892 struct cfg80211_connect_params *req,
12893 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012894{
Naveen Rawat07332902016-07-27 09:13:17 -070012895 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012896}
12897#endif
12898
12899/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012900 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12901 * @wiphy: Pointer to wiphy
12902 * @dev: Pointer to network device
12903 * @req: Pointer to cfg80211 connect request
12904 *
12905 * This function is used to start the association process
12906 *
12907 * Return: 0 for success, non-zero for failure
12908 */
12909static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12910 struct net_device *ndev,
12911 struct cfg80211_connect_params *req)
12912{
12913 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012914 u16 channel;
12915#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12916 const u8 *bssid_hint = req->bssid_hint;
12917#else
12918 const u8 *bssid_hint = NULL;
12919#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012920 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12921 hdd_context_t *pHddCtx;
12922
12923 ENTER();
12924
Anurag Chouhan6d760662016-02-20 16:05:43 +053012925 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012926 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012927 return -EINVAL;
12928 }
12929
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012930 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12931 hdd_err("invalid session id: %d", pAdapter->sessionId);
12932 return -EINVAL;
12933 }
12934
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012935 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012936 TRACE_CODE_HDD_CFG80211_CONNECT,
12937 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012938 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012939 hdd_device_mode_to_string(pAdapter->device_mode),
12940 pAdapter->device_mode);
12941
Krunal Sonib4326f22016-03-10 13:05:51 -080012942 if (pAdapter->device_mode != QDF_STA_MODE &&
12943 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012944 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012945 hdd_device_mode_to_string(pAdapter->device_mode),
12946 pAdapter->device_mode);
12947 return -EINVAL;
12948 }
12949
12950 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12951 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012952 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012953 return -EINVAL;
12954 }
12955
12956 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012957 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012958 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012959
Naveen Rawat07332902016-07-27 09:13:17 -070012960 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012961 return status;
12962
Agrawal Ashishf156e942016-08-04 14:54:47 +053012963 /* Try disconnecting if already in connected state */
12964 status = wlan_hdd_try_disconnect(pAdapter);
12965 if (0 > status) {
12966 hdd_err("Failed to disconnect the existing connection");
12967 return -EALREADY;
12968 }
12969
12970 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012971 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012972 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012973 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012974 pAdapter->device_mode),
12975 req->channel->hw_value, HW_MODE_20_MHZ)) {
12976 hdd_err("This concurrency combination is not allowed");
12977 return -ECONNREFUSED;
12978 }
12979 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012980 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012981 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012982 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12983 hdd_err("This concurrency combination is not allowed");
12984 return -ECONNREFUSED;
12985 }
12986 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012987
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012988 /*initialise security parameters */
12989 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12990
12991 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012992 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012993 return status;
12994 }
12995
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012996 if (req->channel)
12997 channel = req->channel->hw_value;
12998 else
12999 channel = 0;
13000 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
13001 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013002 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013003 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013004 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013005 return status;
13006 }
13007 EXIT();
13008 return status;
13009}
13010
13011/**
13012 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
13013 * @wiphy: Pointer to wiphy
13014 * @dev: Pointer to network device
13015 * @req: Pointer to cfg80211 connect request
13016 *
13017 * Return: 0 for success, non-zero for failure
13018 */
13019static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13020 struct net_device *ndev,
13021 struct cfg80211_connect_params *req)
13022{
13023 int ret;
13024 cds_ssr_protect(__func__);
13025 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
13026 cds_ssr_unprotect(__func__);
13027
13028 return ret;
13029}
13030
13031/**
13032 * wlan_hdd_disconnect() - hdd disconnect api
13033 * @pAdapter: Pointer to adapter
13034 * @reason: Disconnect reason code
13035 *
13036 * This function is used to issue a disconnect request to SME
13037 *
13038 * Return: 0 for success, non-zero for failure
13039 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013040static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013041{
13042 int status, result = 0;
13043 unsigned long rc;
13044 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13045 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13046
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013047 ENTER();
13048
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013049 status = wlan_hdd_validate_context(pHddCtx);
13050
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013051 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013052 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013053
13054 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013055 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013056 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
13057 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013058 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013059 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
13060 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13061
13062 /*issue disconnect */
13063
13064 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13065 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053013066 /*
13067 * Wait here instead of returning directly, this will block the next
13068 * connect command and allow processing of the scan for ssid and
13069 * the previous connect command in CSR. Else we might hit some
13070 * race conditions leading to SME and HDD out of sync.
13071 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013072 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013073 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013074 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013075 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013076 (int)status);
13077 pHddStaCtx->staDebugState = status;
13078 result = -EINVAL;
13079 goto disconnected;
13080 }
13081 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13082 msecs_to_jiffies
13083 (WLAN_WAIT_TIME_DISCONNECT));
13084
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013085 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013086 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013087 result = -ETIMEDOUT;
13088 }
13089disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013090 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13091#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
13092 /* Sending disconnect event to userspace for kernel version < 3.11
13093 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
13094 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013095 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053013096 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
13097 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013098#endif
13099
13100 return result;
13101}
13102
13103/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013104 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
13105 * @reason: ieee80211 reason code.
13106 *
13107 * This utility function helps log string conversion of reason code.
13108 *
13109 * Return: string conversion of reason code, if match found;
13110 * "Unknown" otherwise.
13111 */
13112static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
13113{
13114 switch (reason) {
13115 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
13116 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
13117 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
13118 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
13119 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
13120 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
13121 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
13122 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
13123 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
13124 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
13125 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
13126 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
13127 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
13128 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
13129 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
13130 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
13131 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
13132 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
13133 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
13134 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
13135 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
13136 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
13137 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
13138 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
13139 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
13140 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
13141 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
13142 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
13143 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
13144 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
13145 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
13146 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
13147 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
13148 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
13149 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
13150 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
13151 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
13152 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
13153 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
13154 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
13155 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
13156 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
13157 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
13158 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
13159 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
13160 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
13161 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
13162 default:
13163 return "Unknown";
13164 }
13165}
13166
13167/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013168 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
13169 * @wiphy: Pointer to wiphy
13170 * @dev: Pointer to network device
13171 * @reason: Disconnect reason code
13172 *
13173 * This function is used to issue a disconnect request to SME
13174 *
13175 * Return: 0 for success, non-zero for failure
13176 */
13177static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
13178 struct net_device *dev, u16 reason)
13179{
13180 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13181 int status;
13182 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13183 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13184#ifdef FEATURE_WLAN_TDLS
13185 uint8_t staIdx;
13186#endif
13187
13188 ENTER();
13189
Anurag Chouhan6d760662016-02-20 16:05:43 +053013190 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013191 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013192 return -EINVAL;
13193 }
13194
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013195 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13196 hdd_err("invalid session id: %d", pAdapter->sessionId);
13197 return -EINVAL;
13198 }
13199
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013200 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013201 TRACE_CODE_HDD_CFG80211_DISCONNECT,
13202 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013203 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013204 hdd_device_mode_to_string(pAdapter->device_mode),
13205 pAdapter->device_mode, reason);
13206
13207 status = wlan_hdd_validate_context(pHddCtx);
13208
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080013209 if (hdd_is_roaming_in_progress()) {
13210 hdd_err("Roaming In Progress. Ignore!!!");
13211 return -EAGAIN;
13212 }
13213
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013214 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013215 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013216
13217 /* Issue disconnect request to SME, if station is in connected state */
13218 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
13219 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
13220 eCsrRoamDisconnectReason reasonCode =
13221 eCSR_DISCONNECT_REASON_UNSPECIFIED;
13222 hdd_scaninfo_t *pScanInfo;
13223
13224 switch (reason) {
13225 case WLAN_REASON_MIC_FAILURE:
13226 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
13227 break;
13228
13229 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
13230 case WLAN_REASON_DISASSOC_AP_BUSY:
13231 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
13232 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
13233 break;
13234
13235 case WLAN_REASON_PREV_AUTH_NOT_VALID:
13236 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
13237 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
13238 break;
13239
13240 case WLAN_REASON_DEAUTH_LEAVING:
13241 reasonCode =
13242 pHddCtx->config->
13243 gEnableDeauthToDisassocMap ?
13244 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
13245 eCSR_DISCONNECT_REASON_DEAUTH;
13246 break;
13247 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
13248 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
13249 break;
13250 default:
13251 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
13252 break;
13253 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013254 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013255 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013256 pScanInfo = &pAdapter->scan_info;
13257 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013258 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013259 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
13260 eCSR_SCAN_ABORT_DEFAULT);
13261 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053013262 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013263#ifdef FEATURE_WLAN_TDLS
13264 /* First clean up the tdls peers if any */
13265 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
13266 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
13267 pAdapter->sessionId)
13268 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
13269 uint8_t *mac;
13270 mac =
13271 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013272 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
13273 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013274 pHddCtx->tdlsConnInfo[staIdx].staId,
13275 pAdapter->sessionId,
13276 MAC_ADDR_ARRAY(mac));
13277 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
13278 (pAdapter),
13279 pAdapter->sessionId, mac);
13280 }
13281 }
13282#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013283 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013284 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013285 hdd_info("Disconnect request from user space with reason: %s",
13286 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013287 status = wlan_hdd_disconnect(pAdapter, reasonCode);
13288 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013289 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013290 return -EINVAL;
13291 }
13292 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013293 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013294 pHddStaCtx->conn_info.connState);
13295 }
13296
13297 return status;
13298}
13299
13300/**
13301 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
13302 * @wiphy: Pointer to wiphy
13303 * @dev: Pointer to network device
13304 * @reason: Disconnect reason code
13305 *
13306 * Return: 0 for success, non-zero for failure
13307 */
13308static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
13309 struct net_device *dev, u16 reason)
13310{
13311 int ret;
13312 cds_ssr_protect(__func__);
13313 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
13314 cds_ssr_unprotect(__func__);
13315
13316 return ret;
13317}
13318
13319/**
13320 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
13321 * @pAdapter: Pointer to adapter
13322 * @param: Pointer to IBSS parameters
13323 *
13324 * This function is used to initialize the security settings in IBSS mode
13325 *
13326 * Return: 0 for success, non-zero for failure
13327 */
13328static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
13329 struct cfg80211_ibss_params
13330 *params)
13331{
13332 int status = 0;
13333 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13334 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13335 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13336
13337 ENTER();
13338
13339 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013340 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013341 pHddStaCtx->ibss_enc_key_installed = 0;
13342
13343 if (params->ie_len && (NULL != params->ie)) {
13344 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13345 params->ie_len, WLAN_EID_RSN)) {
13346 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13347 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13348 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
13349 tDot11fIEWPA dot11WPAIE;
13350 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13351 u8 *ie;
13352
13353 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
13354 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13355 params->ie_len,
13356 DOT11F_EID_WPA);
13357 if (NULL != ie) {
13358 pWextState->wpaVersion =
13359 IW_AUTH_WPA_VERSION_WPA;
13360 /* Unpack the WPA IE */
13361 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
13362 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
13363 &ie[2 + 4],
13364 ie[1] - 4, &dot11WPAIE);
13365 /*Extract the multicast cipher, the encType for unicast
13366 cipher for wpa-none is none */
13367 encryptionType =
13368 hdd_translate_wpa_to_csr_encryption_type
13369 (dot11WPAIE.multicast_cipher);
13370 }
13371 }
13372
13373 status =
13374 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
13375 params->ie_len);
13376
13377 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013378 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013379 return status;
13380 }
13381 }
13382
13383 pWextState->roamProfile.AuthType.authType[0] =
13384 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13385
13386 if (params->privacy) {
13387 /* Security enabled IBSS, At this time there is no information
13388 * available about the security paramters, so initialise the
13389 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
13390 * The correct security parameters will be updated later in
13391 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
13392 * set inorder enable privacy bit in beacons
13393 */
13394
13395 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
13396 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013397 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013398 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13399 pWextState->roamProfile.EncryptionType.numEntries = 1;
13400 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13401 encryptionType;
13402 return status;
13403}
13404
13405/**
13406 * __wlan_hdd_cfg80211_join_ibss() - join ibss
13407 * @wiphy: Pointer to wiphy
13408 * @dev: Pointer to network device
13409 * @param: Pointer to IBSS join parameters
13410 *
13411 * This function is used to create/join an IBSS network
13412 *
13413 * Return: 0 for success, non-zero for failure
13414 */
13415static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13416 struct net_device *dev,
13417 struct cfg80211_ibss_params *params)
13418{
13419 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13420 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13421 tCsrRoamProfile *pRoamProfile;
13422 int status;
13423 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13424 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053013425 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013426 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013427
13428 ENTER();
13429
Anurag Chouhan6d760662016-02-20 16:05:43 +053013430 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013431 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013432 return -EINVAL;
13433 }
13434
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013435 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13436 hdd_err("invalid session id: %d", pAdapter->sessionId);
13437 return -EINVAL;
13438 }
13439
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013440 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013441 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
13442 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013443 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013444 hdd_device_mode_to_string(pAdapter->device_mode),
13445 pAdapter->device_mode);
13446
13447 status = wlan_hdd_validate_context(pHddCtx);
13448
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013449 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013450 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013451
13452 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053013453 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013454 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
13455 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
13456 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13457 int indx;
13458
13459 /* Get channel number */
13460 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013461 params->
13462 chandef.
13463 chan->
13464 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013465
13466 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
13467 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013468 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013469 return -EOPNOTSUPP;
13470 }
13471
13472 for (indx = 0; indx < numChans; indx++) {
13473 if (channelNum == validChan[indx]) {
13474 break;
13475 }
13476 }
13477 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013478 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013479 return -EINVAL;
13480 }
13481 }
13482
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013483 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013484 HW_MODE_20_MHZ)) {
13485 hdd_err("This concurrency combination is not allowed");
13486 return -ECONNREFUSED;
13487 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013488
Krunal Soni3091bcc2016-06-23 12:28:21 -070013489 status = qdf_reset_connection_update();
13490 if (!QDF_IS_STATUS_SUCCESS(status))
13491 hdd_err("ERR: clear event failed");
13492
13493 status = cds_current_connections_update(pAdapter->sessionId,
13494 channelNum,
13495 SIR_UPDATE_REASON_JOIN_IBSS);
13496 if (QDF_STATUS_E_FAILURE == status) {
13497 hdd_err("ERROR: connections update failed!!");
13498 return -EINVAL;
13499 }
13500
13501 if (QDF_STATUS_SUCCESS == status) {
13502 status = qdf_wait_for_connection_update();
13503 if (!QDF_IS_STATUS_SUCCESS(status)) {
13504 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013505 return -EINVAL;
13506 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013507 }
13508
13509 /*Try disconnecting if already in connected state */
13510 status = wlan_hdd_try_disconnect(pAdapter);
13511 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013512 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013513 return -EALREADY;
13514 }
13515
13516 pRoamProfile = &pWextState->roamProfile;
13517
13518 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013519 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013520 return -EINVAL;
13521 }
13522
13523 /* enable selected protection checks in IBSS mode */
13524 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
13525
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013526 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013527 WNI_CFG_IBSS_ATIM_WIN_SIZE,
13528 pHddCtx->config->
13529 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013530 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013531 }
13532
13533 /* BSSID is provided by upper layers hence no need to AUTO generate */
13534 if (NULL != params->bssid) {
13535 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013536 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013537 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013538 return -EIO;
13539 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013540 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013541 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
13542 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013543 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013544 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013545 return -EIO;
13546 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053013547 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013548 }
13549 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13550 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13551 pRoamProfile->beaconInterval = params->beacon_interval;
13552 else {
13553 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013554 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013555 params->beacon_interval, pRoamProfile->beaconInterval);
13556 }
13557
13558 /* Set Channel */
13559 if (channelNum) {
13560 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013561 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013562 pRoamProfile->ChannelInfo.numOfChannels = 1;
13563 pHddStaCtx->conn_info.operationChannel = channelNum;
13564 pRoamProfile->ChannelInfo.ChannelList =
13565 &pHddStaCtx->conn_info.operationChannel;
13566 }
13567
13568 /* Initialize security parameters */
13569 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13570 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013571 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013572 return status;
13573 }
13574
13575 /* Issue connect start */
13576 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13577 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013578 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013579 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013580 operationChannel,
13581 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013582
13583 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013584 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013585 return status;
13586 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013587 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013588 return 0;
13589}
13590
13591/**
13592 * wlan_hdd_cfg80211_join_ibss() - join ibss
13593 * @wiphy: Pointer to wiphy
13594 * @dev: Pointer to network device
13595 * @param: Pointer to IBSS join parameters
13596 *
13597 * This function is used to create/join an IBSS network
13598 *
13599 * Return: 0 for success, non-zero for failure
13600 */
13601static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13602 struct net_device *dev,
13603 struct cfg80211_ibss_params *params)
13604{
13605 int ret = 0;
13606
13607 cds_ssr_protect(__func__);
13608 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13609 cds_ssr_unprotect(__func__);
13610
13611 return ret;
13612}
13613
13614/**
13615 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13616 * @wiphy: Pointer to wiphy
13617 * @dev: Pointer to network device
13618 *
13619 * This function is used to leave an IBSS network
13620 *
13621 * Return: 0 for success, non-zero for failure
13622 */
13623static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13624 struct net_device *dev)
13625{
13626 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13627 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13628 tCsrRoamProfile *pRoamProfile;
13629 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13630 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013631 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013632 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013633 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013634
13635 ENTER();
13636
Anurag Chouhan6d760662016-02-20 16:05:43 +053013637 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013638 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639 return -EINVAL;
13640 }
13641
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013642 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13643 hdd_err("invalid session id: %d", pAdapter->sessionId);
13644 return -EINVAL;
13645 }
13646
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013647 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013648 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13649 pAdapter->sessionId,
13650 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13651 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013652 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013653 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013654
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013655 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013656 hdd_device_mode_to_string(pAdapter->device_mode),
13657 pAdapter->device_mode);
13658 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013659 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660 return -EIO;
13661 }
13662
13663 pRoamProfile = &pWextState->roamProfile;
13664
13665 /* Issue disconnect only if interface type is set to IBSS */
13666 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013667 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013668 return -EINVAL;
13669 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013670 /* Clearing add IE of beacon */
13671 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13672 sizeof(tSirMacAddr));
13673 updateIE.smeSessionId = pAdapter->sessionId;
13674 updateIE.ieBufferlength = 0;
13675 updateIE.pAdditionIEBuffer = NULL;
13676 updateIE.append = true;
13677 updateIE.notify = true;
13678 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13679 &updateIE,
13680 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013681 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013682 }
13683
13684 /* Reset WNI_CFG_PROBE_RSP Flags */
13685 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013686
13687 /* Issue Disconnect request */
13688 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13689 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13690 pAdapter->sessionId,
13691 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013692 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013693 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013694 hal_status);
13695 return -EAGAIN;
13696 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013697
13698 /* wait for mc thread to cleanup and then return to upper stack
13699 * so by the time upper layer calls the change interface, we are
13700 * all set to proceed further
13701 */
13702 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13703 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13704 if (!rc) {
13705 hdd_err("Failed to disconnect, timed out");
13706 return -ETIMEDOUT;
13707 }
13708
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013709 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013710 return 0;
13711}
13712
13713/**
13714 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13715 * @wiphy: Pointer to wiphy
13716 * @dev: Pointer to network device
13717 *
13718 * This function is used to leave an IBSS network
13719 *
13720 * Return: 0 for success, non-zero for failure
13721 */
13722static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13723 struct net_device *dev)
13724{
13725 int ret = 0;
13726
13727 cds_ssr_protect(__func__);
13728 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13729 cds_ssr_unprotect(__func__);
13730
13731 return ret;
13732}
13733
13734/**
13735 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13736 * @wiphy: Pointer to wiphy
13737 * @changed: Parameters changed
13738 *
13739 * This function is used to set the phy parameters. RTS Threshold/FRAG
13740 * Threshold/Retry Count etc.
13741 *
13742 * Return: 0 for success, non-zero for failure
13743 */
13744static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13745 u32 changed)
13746{
13747 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13748 tHalHandle hHal = pHddCtx->hHal;
13749 int status;
13750
13751 ENTER();
13752
Anurag Chouhan6d760662016-02-20 16:05:43 +053013753 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013754 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013755 return -EINVAL;
13756 }
13757
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013758 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013759 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13760 NO_SESSION, wiphy->rts_threshold));
13761 status = wlan_hdd_validate_context(pHddCtx);
13762
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013763 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013764 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013765
13766 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13767 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13768 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13769
13770 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13771 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013772 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013773 rts_threshold);
13774 return -EINVAL;
13775 }
13776
13777 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13778 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013779 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013780 rts_threshold);
13781 return -EIO;
13782 }
13783
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013784 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013785 }
13786
13787 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13788 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13789 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13790 wiphy->frag_threshold;
13791
13792 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13793 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013794 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013795 frag_threshold);
13796 return -EINVAL;
13797 }
13798
13799 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13800 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013801 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013802 frag_threshold);
13803 return -EIO;
13804 }
13805
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013806 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013807 }
13808
13809 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13810 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13811 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13812 wiphy->retry_short : wiphy->retry_long;
13813
13814 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13815 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013816 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013817 return -EINVAL;
13818 }
13819
13820 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13821 if (0 != sme_cfg_set_int(hHal,
13822 WNI_CFG_LONG_RETRY_LIMIT,
13823 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013824 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013825 retry_value);
13826 return -EIO;
13827 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013828 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013829 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13830 if (0 != sme_cfg_set_int(hHal,
13831 WNI_CFG_SHORT_RETRY_LIMIT,
13832 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013833 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013834 retry_value);
13835 return -EIO;
13836 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013837 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013838 }
13839 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013840 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013841 return 0;
13842}
13843
13844/**
13845 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13846 * @wiphy: Pointer to wiphy
13847 * @changed: Parameters changed
13848 *
13849 * Return: 0 for success, non-zero for failure
13850 */
13851static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13852{
13853 int ret;
13854
13855 cds_ssr_protect(__func__);
13856 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13857 cds_ssr_unprotect(__func__);
13858
13859 return ret;
13860}
13861
13862/**
13863 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13864 * key
13865 * @wiphy: Pointer to wiphy
13866 * @dev: Pointer to network device
13867 * @key_index: Key index
13868 *
13869 * Return: 0
13870 */
13871static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13872 struct net_device *netdev,
13873 u8 key_index)
13874{
13875 ENTER();
13876 return 0;
13877}
13878
13879/**
13880 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13881 * wlan_hdd_set_default_mgmt_key
13882 * @wiphy: pointer to wiphy
13883 * @netdev: pointer to net_device structure
13884 * @key_index: key index
13885 *
13886 * Return: 0 on success, error number on failure
13887 */
13888static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13889 struct net_device *netdev,
13890 u8 key_index)
13891{
13892 int ret;
13893
13894 cds_ssr_protect(__func__);
13895 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13896 cds_ssr_unprotect(__func__);
13897
13898 return ret;
13899}
13900
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013901/**
13902 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13903 * @wiphy: Pointer to wiphy
13904 * @dev: Pointer to network device
13905 * @params: Pointer to tx queue parameters
13906 *
13907 * Return: 0
13908 */
13909static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13910 struct net_device *dev,
13911 struct ieee80211_txq_params *params)
13912{
13913 ENTER();
13914 return 0;
13915}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013916
13917/**
13918 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13919 * @wiphy: pointer to wiphy
13920 * @netdev: pointer to net_device structure
13921 * @params: pointer to ieee80211_txq_params
13922 *
13923 * Return: 0 on success, error number on failure
13924 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013925static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13926 struct net_device *dev,
13927 struct ieee80211_txq_params *params)
13928{
13929 int ret;
13930
13931 cds_ssr_protect(__func__);
13932 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13933 cds_ssr_unprotect(__func__);
13934
13935 return ret;
13936}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013937
13938/**
13939 * __wlan_hdd_cfg80211_del_station() - delete station v2
13940 * @wiphy: Pointer to wiphy
13941 * @param: Pointer to delete station parameter
13942 *
13943 * Return: 0 for success, non-zero for failure
13944 */
13945static
13946int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13947 struct net_device *dev,
13948 struct tagCsrDelStaParams *pDelStaParams)
13949{
13950 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13951 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013952 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013953 hdd_hostapd_state_t *hapd_state;
13954 int status;
13955 uint8_t staId;
13956 uint8_t *mac;
13957
13958 ENTER();
13959
Anurag Chouhan6d760662016-02-20 16:05:43 +053013960 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013961 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013962 return -EINVAL;
13963 }
13964
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013965 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13966 hdd_err("invalid session id: %d", pAdapter->sessionId);
13967 return -EINVAL;
13968 }
13969
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013970 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013971 TRACE_CODE_HDD_CFG80211_DEL_STA,
13972 pAdapter->sessionId, pAdapter->device_mode));
13973
13974 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13975 status = wlan_hdd_validate_context(pHddCtx);
13976
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013977 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013978 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013979
13980 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13981
Krunal Sonib4326f22016-03-10 13:05:51 -080013982 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13983 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013984
13985 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13986 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013987 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013988 return 0;
13989 }
13990
Anurag Chouhanc5548422016-02-24 18:33:27 +053013991 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013992 uint16_t i;
13993 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13994 if ((pAdapter->aStaInfo[i].isUsed) &&
13995 (!pAdapter->aStaInfo[i].
13996 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013997 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013998 mac,
13999 pAdapter->aStaInfo[i].
14000 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053014001 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014002 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
14003 hdd_ipa_wlan_evt(pAdapter,
14004 pAdapter->
14005 aStaInfo[i].
14006 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070014007 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014008 mac);
14009 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014010 hdd_notice("Delete STA with MAC::"
14011 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014012 MAC_ADDR_ARRAY(mac));
14013
14014 if (pHddCtx->dev_dfs_cac_status ==
14015 DFS_CAC_IN_PROGRESS)
14016 goto fn_end;
14017
Wei Song2f76f642016-11-18 16:32:53 +080014018 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014019 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053014020 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014021 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014022 hdd_softap_sta_deauth(pAdapter,
14023 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014024 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014025 pAdapter->aStaInfo[i].
14026 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053014027 qdf_status =
14028 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080014029 &hapd_state->
14030 qdf_sta_disassoc_event,
14031 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053014032 if (!QDF_IS_STATUS_SUCCESS(
14033 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014034 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014035 }
14036 }
14037 }
14038 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014039 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014040 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053014041 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014042 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014043 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014044 hdd_notice("Skip DEL STA as this is not used::"
14045 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014046 MAC_ADDR_ARRAY(mac));
14047 return -ENOENT;
14048 }
14049
14050 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
14051 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070014052 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014053 }
14054
14055 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
14056 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014057 hdd_notice("Skip DEL STA as deauth is in progress::"
14058 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014059 MAC_ADDR_ARRAY(mac));
14060 return -ENOENT;
14061 }
14062
14063 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
14064
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014065 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014066 MAC_ADDR_ARRAY(mac));
14067
14068 /* Case: SAP in ACS selected DFS ch and client connected
14069 * Now Radar detected. Then if random channel is another
14070 * DFS ch then new CAC is initiated and no TX allowed.
14071 * So do not send any mgmt frames as it will timeout
14072 * during CAC.
14073 */
14074
14075 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
14076 goto fn_end;
14077
Wei Song2f76f642016-11-18 16:32:53 +080014078 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053014079 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
14080 (pAdapter), pAdapter->sessionId,
14081 (uint8_t *)&pDelStaParams->peerMacAddr,
14082 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014083 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014084 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014085 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014086 pAdapter->aStaInfo[staId].isDeauthInProgress =
14087 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014088 hdd_notice("STA removal failed for ::"
14089 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014090 MAC_ADDR_ARRAY(mac));
14091 return -ENOENT;
14092 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053014093 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080014094 &hapd_state->
14095 qdf_sta_disassoc_event,
14096 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053014097 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014098 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014099 }
14100 }
14101 }
14102
14103fn_end:
14104 EXIT();
14105 return 0;
14106}
14107
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014108#if defined(USE_CFG80211_DEL_STA_V2)
14109/**
14110 * wlan_hdd_del_station() - delete station wrapper
14111 * @adapter: pointer to the hdd adapter
14112 *
14113 * Return: None
14114 */
14115void wlan_hdd_del_station(hdd_adapter_t *adapter)
14116{
14117 struct station_del_parameters del_sta;
14118 del_sta.mac = NULL;
14119 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
14120 del_sta.reason_code = eCsrForcedDeauthSta;
14121
14122 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
14123 &del_sta);
14124}
14125#else
14126void wlan_hdd_del_station(hdd_adapter_t *adapter)
14127{
14128 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
14129}
14130#endif
14131
14132#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014133/**
14134 * wlan_hdd_cfg80211_del_station() - delete station v2
14135 * @wiphy: Pointer to wiphy
14136 * @param: Pointer to delete station parameter
14137 *
14138 * Return: 0 for success, non-zero for failure
14139 */
14140int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14141 struct net_device *dev,
14142 struct station_del_parameters *param)
14143#else
14144/**
14145 * wlan_hdd_cfg80211_del_station() - delete station
14146 * @wiphy: Pointer to wiphy
14147 * @mac: Pointer to station mac address
14148 *
14149 * Return: 0 for success, non-zero for failure
14150 */
14151#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14152int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14153 struct net_device *dev,
14154 const uint8_t *mac)
14155#else
14156int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14157 struct net_device *dev,
14158 uint8_t *mac)
14159#endif
14160#endif
14161{
14162 int ret;
14163 struct tagCsrDelStaParams delStaParams;
14164
14165 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014166#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014167 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014168 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014169 return -EINVAL;
14170 }
14171 wlansap_populate_del_sta_params(param->mac, param->reason_code,
14172 param->subtype, &delStaParams);
14173#else
14174 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
14175 (SIR_MAC_MGMT_DEAUTH >> 4),
14176 &delStaParams);
14177#endif
14178 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
14179 cds_ssr_unprotect(__func__);
14180
14181 return ret;
14182}
14183
14184/**
14185 * __wlan_hdd_cfg80211_add_station() - add station
14186 * @wiphy: Pointer to wiphy
14187 * @mac: Pointer to station mac address
14188 * @pmksa: Pointer to add station parameter
14189 *
14190 * Return: 0 for success, non-zero for failure
14191 */
14192static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14193 struct net_device *dev,
14194 const uint8_t *mac,
14195 struct station_parameters *params)
14196{
14197 int status = -EPERM;
14198#ifdef FEATURE_WLAN_TDLS
14199 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14200 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14201 u32 mask, set;
14202
14203 ENTER();
14204
Anurag Chouhan6d760662016-02-20 16:05:43 +053014205 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014206 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014207 return -EINVAL;
14208 }
14209
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014210 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14211 hdd_err("invalid session id: %d", pAdapter->sessionId);
14212 return -EINVAL;
14213 }
14214
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014215 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014216 TRACE_CODE_HDD_CFG80211_ADD_STA,
14217 pAdapter->sessionId, params->listen_interval));
14218
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014219 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014220 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014221
14222 mask = params->sta_flags_mask;
14223
14224 set = params->sta_flags_set;
14225
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014226 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014227 MAC_ADDR_ARRAY(mac));
14228
14229 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14230 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14231 status =
14232 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
14233 }
14234 }
14235#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014236 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014237 return status;
14238}
14239
14240/**
14241 * wlan_hdd_cfg80211_add_station() - add station
14242 * @wiphy: Pointer to wiphy
14243 * @mac: Pointer to station mac address
14244 * @pmksa: Pointer to add station parameter
14245 *
14246 * Return: 0 for success, non-zero for failure
14247 */
14248#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14249static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14250 struct net_device *dev,
14251 const uint8_t *mac,
14252 struct station_parameters *params)
14253#else
14254static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14255 struct net_device *dev, uint8_t *mac,
14256 struct station_parameters *params)
14257#endif
14258{
14259 int ret;
14260
14261 cds_ssr_protect(__func__);
14262 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
14263 cds_ssr_unprotect(__func__);
14264
14265 return ret;
14266}
14267
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014268/**
14269 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
14270 * @wiphy: Pointer to wiphy
14271 * @dev: Pointer to network device
14272 * @pmksa: Pointer to set pmksa parameter
14273 *
14274 * Return: 0 for success, non-zero for failure
14275 */
14276static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14277 struct net_device *dev,
14278 struct cfg80211_pmksa *pmksa)
14279{
14280 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14281 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14282 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014283 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014284 int status;
14285 tPmkidCacheInfo pmk_id;
14286
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014287 ENTER();
14288
Anurag Chouhan6d760662016-02-20 16:05:43 +053014289 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014290 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014291 return -EINVAL;
14292 }
14293
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014294 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14295 hdd_err("invalid session id: %d", pAdapter->sessionId);
14296 return -EINVAL;
14297 }
14298
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014299 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014300 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014301 return -EINVAL;
14302 }
14303
14304 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014305 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014306 pmksa->bssid, pmksa->pmkid);
14307 return -EINVAL;
14308 }
14309
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014310 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014311 MAC_ADDR_ARRAY(pmksa->bssid));
14312
14313 status = wlan_hdd_validate_context(pHddCtx);
14314
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014315 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014316 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014317
14318 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14319
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014320 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
14321 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014322
14323 /* Add to the PMKSA ID Cache in CSR */
14324 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
14325 &pmk_id, 1, false);
14326
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014327 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014328 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
14329 pAdapter->sessionId, result));
14330
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014331 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014332 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014333}
14334
14335/**
14336 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
14337 * @wiphy: Pointer to wiphy
14338 * @dev: Pointer to network device
14339 * @pmksa: Pointer to set pmksa parameter
14340 *
14341 * Return: 0 for success, non-zero for failure
14342 */
14343static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14344 struct net_device *dev,
14345 struct cfg80211_pmksa *pmksa)
14346{
14347 int ret;
14348
14349 cds_ssr_protect(__func__);
14350 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
14351 cds_ssr_unprotect(__func__);
14352
14353 return ret;
14354}
14355
14356/**
14357 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14358 * @wiphy: Pointer to wiphy
14359 * @dev: Pointer to network device
14360 * @pmksa: Pointer to pmksa parameter
14361 *
14362 * Return: 0 for success, non-zero for failure
14363 */
14364static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14365 struct net_device *dev,
14366 struct cfg80211_pmksa *pmksa)
14367{
14368 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14369 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14370 tHalHandle halHandle;
14371 int status = 0;
14372
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014373 ENTER();
14374
Anurag Chouhan6d760662016-02-20 16:05:43 +053014375 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014376 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014377 return -EINVAL;
14378 }
14379
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014380 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14381 hdd_err("invalid session id: %d", pAdapter->sessionId);
14382 return -EINVAL;
14383 }
14384
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014385 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014386 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014387 return -EINVAL;
14388 }
14389
14390 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014391 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014392 return -EINVAL;
14393 }
14394
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014395 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014396 MAC_ADDR_ARRAY(pmksa->bssid));
14397
14398 status = wlan_hdd_validate_context(pHddCtx);
14399
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014400 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014401 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014402
14403 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14404
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014405 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014406 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
14407 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014408 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014409 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014410 sme_roam_del_pmkid_from_cache(halHandle,
14411 pAdapter->sessionId, pmksa->bssid,
14412 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014413 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014414 MAC_ADDR_ARRAY(pmksa->bssid));
14415 status = -EINVAL;
14416 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014417 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014418 return status;
14419}
14420
14421/**
14422 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14423 * @wiphy: Pointer to wiphy
14424 * @dev: Pointer to network device
14425 * @pmksa: Pointer to pmksa parameter
14426 *
14427 * Return: 0 for success, non-zero for failure
14428 */
14429static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14430 struct net_device *dev,
14431 struct cfg80211_pmksa *pmksa)
14432{
14433 int ret;
14434
14435 cds_ssr_protect(__func__);
14436 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
14437 cds_ssr_unprotect(__func__);
14438
14439 return ret;
14440
14441}
14442
14443/**
14444 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14445 * @wiphy: Pointer to wiphy
14446 * @dev: Pointer to network device
14447 *
14448 * Return: 0 for success, non-zero for failure
14449 */
14450static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14451 struct net_device *dev)
14452{
14453 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14454 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14455 tHalHandle halHandle;
14456 int status = 0;
14457
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014458 ENTER();
14459
Anurag Chouhan6d760662016-02-20 16:05:43 +053014460 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014461 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014462 return -EINVAL;
14463 }
14464
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014465 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14466 hdd_err("invalid session id: %d", pAdapter->sessionId);
14467 return -EINVAL;
14468 }
14469
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014470 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014471
14472 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14473 status = wlan_hdd_validate_context(pHddCtx);
14474
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014475 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014476 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014477
14478 /* Retrieve halHandle */
14479 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14480
14481 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014482 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014483 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
14484 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014485 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014486 status = -EINVAL;
14487 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014488 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014489 return status;
14490}
14491
14492/**
14493 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14494 * @wiphy: Pointer to wiphy
14495 * @dev: Pointer to network device
14496 *
14497 * Return: 0 for success, non-zero for failure
14498 */
14499static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14500 struct net_device *dev)
14501{
14502 int ret;
14503
14504 cds_ssr_protect(__func__);
14505 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
14506 cds_ssr_unprotect(__func__);
14507
14508 return ret;
14509}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014510
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014511#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014512/**
14513 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14514 * @wiphy: Pointer to wiphy
14515 * @dev: Pointer to network device
14516 * @ftie: Pointer to fast transition ie parameter
14517 *
14518 * Return: 0 for success, non-zero for failure
14519 */
14520static int
14521__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14522 struct net_device *dev,
14523 struct cfg80211_update_ft_ies_params *ftie)
14524{
14525 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14526 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14527 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14528 int status;
14529
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014530 ENTER();
14531
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014532 status = wlan_hdd_validate_context(hdd_ctx);
14533 if (status)
14534 return status;
14535
Anurag Chouhan6d760662016-02-20 16:05:43 +053014536 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014537 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014538 return -EINVAL;
14539 }
14540
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014541 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14542 hdd_err("invalid session id: %d", pAdapter->sessionId);
14543 return -EINVAL;
14544 }
14545
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014546 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014547 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
14548 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
14549 /* Added for debug on reception of Re-assoc Req. */
14550 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014551 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014552 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014553 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014554 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014555 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014556 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014557
14558 /* Pass the received FT IEs to SME */
14559 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
14560 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014561 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014562 return 0;
14563}
14564
14565/**
14566 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14567 * @wiphy: Pointer to wiphy
14568 * @dev: Pointer to network device
14569 * @ftie: Pointer to fast transition ie parameter
14570 *
14571 * Return: 0 for success, non-zero for failure
14572 */
14573static int
14574wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14575 struct net_device *dev,
14576 struct cfg80211_update_ft_ies_params *ftie)
14577{
14578 int ret;
14579
14580 cds_ssr_protect(__func__);
14581 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14582 cds_ssr_unprotect(__func__);
14583
14584 return ret;
14585}
14586#endif
14587
14588#ifdef WLAN_FEATURE_GTK_OFFLOAD
14589/**
14590 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14591 * @callbackContext: Callback context
14592 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14593 *
14594 * Callback rountine called upon receiving response for get offload info
14595 *
14596 * Return: none
14597 */
14598void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14599 tpSirGtkOffloadGetInfoRspParams
14600 pGtkOffloadGetInfoRsp)
14601{
14602 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14603 uint8_t tempReplayCounter[8];
14604 hdd_station_ctx_t *pHddStaCtx;
14605
14606 ENTER();
14607
14608 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014609 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014610 return;
14611 }
14612
14613 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014614 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014615 return;
14616 }
14617
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014618 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014619 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014620 return;
14621 }
14622
14623 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14624 /* Update replay counter */
14625 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14626 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14627
14628 {
14629 /* changing from little to big endian since supplicant
14630 * works on big endian format
14631 */
14632 int i;
14633 uint8_t *p =
14634 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14635
14636 for (i = 0; i < 8; i++) {
14637 tempReplayCounter[7 - i] = (uint8_t) p[i];
14638 }
14639 }
14640
14641 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014642 cfg80211_gtk_rekey_notify(pAdapter->dev,
14643 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014644 tempReplayCounter, GFP_KERNEL);
14645}
14646
14647/**
14648 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14649 * @wiphy: Pointer to wiphy
14650 * @dev: Pointer to network device
14651 * @data: Pointer to rekey data
14652 *
14653 * This function is used to offload GTK rekeying job to the firmware.
14654 *
14655 * Return: 0 for success, non-zero for failure
14656 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014657static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014658int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14659 struct net_device *dev,
14660 struct cfg80211_gtk_rekey_data *data)
14661{
14662 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14663 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14664 hdd_station_ctx_t *pHddStaCtx;
14665 tHalHandle hHal;
14666 int result;
14667 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014668 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014669
14670 ENTER();
14671
Anurag Chouhan6d760662016-02-20 16:05:43 +053014672 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014673 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014674 return -EINVAL;
14675 }
14676
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014677 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14678 hdd_err("invalid session id: %d", pAdapter->sessionId);
14679 return -EINVAL;
14680 }
14681
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014682 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014683 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14684 pAdapter->sessionId, pAdapter->device_mode));
14685
14686 result = wlan_hdd_validate_context(pHddCtx);
14687
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014688 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014689 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014690
14691 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14692 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14693 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014694 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014695 return -EAGAIN;
14696 }
14697
14698 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14699 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14700 NL80211_KCK_LEN);
14701 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14702 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014703 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014704 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014705 {
14706 /* changing from big to little endian since driver
14707 * works on little endian format
14708 */
14709 uint8_t *p =
14710 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14711 ullKeyReplayCounter;
14712 int i;
14713
14714 for (i = 0; i < 8; i++) {
14715 p[7 - i] = data->replay_ctr[i];
14716 }
14717 }
14718
14719 if (true == pHddCtx->hdd_wlan_suspended) {
14720 /* if wlan is suspended, enable GTK offload directly from here */
14721 memcpy(&hddGtkOffloadReqParams,
14722 &pHddStaCtx->gtkOffloadReqParams,
14723 sizeof(tSirGtkOffloadParams));
14724 status =
14725 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14726 pAdapter->sessionId);
14727
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014728 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014729 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014730 status);
14731 return -EINVAL;
14732 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014733 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014734 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014735 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014736 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014737 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014738 return result;
14739}
14740
14741/**
14742 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14743 * @wiphy: Pointer to wiphy
14744 * @dev: Pointer to network device
14745 * @data: Pointer to rekey data
14746 *
14747 * This function is used to offload GTK rekeying job to the firmware.
14748 *
14749 * Return: 0 for success, non-zero for failure
14750 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014751static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014752int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14753 struct net_device *dev,
14754 struct cfg80211_gtk_rekey_data *data)
14755{
14756 int ret;
14757
14758 cds_ssr_protect(__func__);
14759 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14760 cds_ssr_unprotect(__func__);
14761
14762 return ret;
14763}
14764#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14765
14766/**
14767 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14768 * @wiphy: Pointer to wiphy
14769 * @dev: Pointer to network device
14770 * @param: Pointer to access control parameter
14771 *
14772 * Return: 0 for success, non-zero for failure
14773 */
14774static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14775 struct net_device *dev,
14776 const struct cfg80211_acl_data *params)
14777{
14778 int i;
14779 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14780 hdd_hostapd_state_t *pHostapdState;
14781 tsap_Config_t *pConfig;
14782 v_CONTEXT_t p_cds_context = NULL;
14783 hdd_context_t *pHddCtx;
14784 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014785 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014786
14787 ENTER();
14788
Anurag Chouhan6d760662016-02-20 16:05:43 +053014789 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014790 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014791 return -EINVAL;
14792 }
14793
14794 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014795 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014796 return -EINVAL;
14797 }
14798
14799 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14800 status = wlan_hdd_validate_context(pHddCtx);
14801
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014802 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014803 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014804
14805 p_cds_context = pHddCtx->pcds_context;
14806 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14807
14808 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014809 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014810 return -EINVAL;
14811 }
14812
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014813 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014814 params->n_acl_entries);
14815
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014816 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014817 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14818 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014819 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014820 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14821
14822 /* default value */
14823 pConfig->num_accept_mac = 0;
14824 pConfig->num_deny_mac = 0;
14825
14826 /**
14827 * access control policy
14828 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14829 * listed in hostapd.deny file.
14830 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14831 * listed in hostapd.accept file.
14832 */
14833 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14834 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14835 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14836 params->acl_policy) {
14837 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14838 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014839 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014840 params->acl_policy);
14841 return -ENOTSUPP;
14842 }
14843
14844 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14845 pConfig->num_accept_mac = params->n_acl_entries;
14846 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014847 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14848 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014849 MAC_ADDR_ARRAY(
14850 params->mac_addrs[i].addr));
14851
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014852 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014853 params->mac_addrs[i].addr,
14854 sizeof(qcmacaddr));
14855 }
14856 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14857 pConfig->num_deny_mac = params->n_acl_entries;
14858 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014859 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14860 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014861 MAC_ADDR_ARRAY(
14862 params->mac_addrs[i].addr));
14863
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014864 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014865 params->mac_addrs[i].addr,
14866 sizeof(qcmacaddr));
14867 }
14868 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014869 qdf_status = wlansap_set_mac_acl(
14870 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014871 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014872 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014873 return -EINVAL;
14874 }
14875 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014876 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014877 hdd_device_mode_to_string(pAdapter->device_mode),
14878 pAdapter->device_mode);
14879 return -EINVAL;
14880 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014881 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014882 return 0;
14883}
14884
14885/**
14886 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14887 * __wlan_hdd_cfg80211_set_mac_acl
14888 * @wiphy: pointer to wiphy structure
14889 * @dev: pointer to net_device
14890 * @params: pointer to cfg80211_acl_data
14891 *
14892 * Return; 0 on success, error number otherwise
14893 */
14894static int
14895wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14896 struct net_device *dev,
14897 const struct cfg80211_acl_data *params)
14898{
14899 int ret;
14900
14901 cds_ssr_protect(__func__);
14902 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14903 cds_ssr_unprotect(__func__);
14904
14905 return ret;
14906}
14907
14908#ifdef WLAN_NL80211_TESTMODE
14909#ifdef FEATURE_WLAN_LPHB
14910/**
14911 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14912 * @pHddCtx: Pointer to hdd context
14913 * @lphbInd: Pointer to low power heart beat indication parameter
14914 *
14915 * Return: none
14916 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014917static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14918 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014919{
14920 struct sk_buff *skb;
14921
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014922 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014923
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014924 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014925 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014926
14927 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014928 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014929 return;
14930 }
14931
14932 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14933 wiphy, sizeof(tSirLPHBInd),
14934 GFP_ATOMIC);
14935 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014936 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014937 return;
14938 }
14939
14940 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014941 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014942 goto nla_put_failure;
14943 }
14944 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014945 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014946 goto nla_put_failure;
14947 }
14948 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014949 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014950 goto nla_put_failure;
14951 }
14952 cfg80211_testmode_event(skb, GFP_ATOMIC);
14953 return;
14954
14955nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014956 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014957 kfree_skb(skb);
14958
14959 return;
14960}
14961#endif /* FEATURE_WLAN_LPHB */
14962
14963/**
14964 * __wlan_hdd_cfg80211_testmode() - test mode
14965 * @wiphy: Pointer to wiphy
14966 * @data: Data pointer
14967 * @len: Data length
14968 *
14969 * Return: 0 for success, non-zero for failure
14970 */
14971static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14972 void *data, int len)
14973{
14974 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14975 int err;
14976 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14977
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014978 ENTER();
14979
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014980 err = wlan_hdd_validate_context(pHddCtx);
14981 if (err)
14982 return err;
14983
14984 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14985 len, wlan_hdd_tm_policy);
14986 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014987 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014988 return err;
14989 }
14990
14991 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014992 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014993 return -EINVAL;
14994 }
14995
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014996 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014997 TRACE_CODE_HDD_CFG80211_TESTMODE,
14998 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014999 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
15000#ifdef FEATURE_WLAN_LPHB
15001 /* Low Power Heartbeat configuration request */
15002 case WLAN_HDD_TM_CMD_WLAN_HB:
15003 {
15004 int buf_len;
15005 void *buf;
15006 tSirLPHBReq *hb_params = NULL;
15007 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015008 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015009
15010 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015011 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015012 return -EINVAL;
15013 }
15014
15015 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
15016 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
15017
15018 hb_params_temp = (tSirLPHBReq *) buf;
15019 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
15020 && (hb_params_temp->params.lphbTcpParamReq.
15021 timePeriodSec == 0))
15022 return -EINVAL;
15023
15024 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015025 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015026 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015027 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015028 return -ENOMEM;
15029 }
15030
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015031 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015032 smeStatus =
15033 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
15034 hb_params,
15035 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015036 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015037 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015038 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015039 }
15040 return 0;
15041 }
15042#endif /* FEATURE_WLAN_LPHB */
15043
15044#if defined(QCA_WIFI_FTM)
15045 case WLAN_HDD_TM_CMD_WLAN_FTM:
15046 {
15047 int buf_len;
15048 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015049 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015050 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015051 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015052 return -EINVAL;
15053 }
15054
15055 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
15056 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
15057
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015058 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015059
15060 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
15061
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015062 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015063 err = -EBUSY;
15064 break;
15065 }
15066#endif
15067
15068 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015069 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015070 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
15071 return -EOPNOTSUPP;
15072 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015073 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015074 return err;
15075}
15076
15077/**
15078 * wlan_hdd_cfg80211_testmode() - test mode
15079 * @wiphy: Pointer to wiphy
15080 * @dev: Pointer to network device
15081 * @data: Data pointer
15082 * @len: Data length
15083 *
15084 * Return: 0 for success, non-zero for failure
15085 */
15086static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
15087#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
15088 struct wireless_dev *wdev,
15089#endif
15090 void *data, int len)
15091{
15092 int ret;
15093
15094 cds_ssr_protect(__func__);
15095 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
15096 cds_ssr_unprotect(__func__);
15097
15098 return ret;
15099}
15100
15101#if defined(QCA_WIFI_FTM)
15102/**
15103 * wlan_hdd_testmode_rx_event() - test mode rx event handler
15104 * @buf: Pointer to buffer
15105 * @buf_len: Buffer length
15106 *
15107 * Return: none
15108 */
15109void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
15110{
15111 struct sk_buff *skb;
15112 hdd_context_t *hdd_ctx;
15113
15114 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015115 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015116 return;
15117 }
15118
Anurag Chouhan6d760662016-02-20 16:05:43 +053015119 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015120 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015121 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015122 return;
15123 }
15124
15125 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
15126 buf_len, GFP_KERNEL);
15127 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015128 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015129 return;
15130 }
15131
15132 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
15133 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
15134 goto nla_put_failure;
15135
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015136 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015137
15138 cfg80211_testmode_event(skb, GFP_KERNEL);
15139 return;
15140
15141nla_put_failure:
15142 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015143 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015144}
15145#endif
15146#endif /* CONFIG_NL80211_TESTMODE */
15147
15148#ifdef QCA_HT_2040_COEX
15149/**
15150 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
15151 * @wiphy: Pointer to wiphy
15152 * @dev: Pointer to network device
15153 * @chandef: Pointer to channel definition parameter
15154 *
15155 * Return: 0 for success, non-zero for failure
15156 */
15157static int
15158__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
15159 struct net_device *dev,
15160 struct cfg80211_chan_def *chandef)
15161{
15162 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15163 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015164 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015165 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053015166 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015167
Anurag Chouhan6d760662016-02-20 16:05:43 +053015168 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015169 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015170 return -EINVAL;
15171 }
15172
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015173 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15174 hdd_err("invalid session id: %d", pAdapter->sessionId);
15175 return -EINVAL;
15176 }
15177
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015178 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15179 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053015180 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015181 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015182
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015183 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015184 sme_get_config_param(pHddCtx->hHal, &sme_config);
15185 switch (chandef->width) {
15186 case NL80211_CHAN_WIDTH_20:
15187 if (sme_config.csrConfig.channelBondingMode24GHz !=
15188 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
15189 sme_config.csrConfig.channelBondingMode24GHz =
15190 eCSR_INI_SINGLE_CHANNEL_CENTERED;
15191 sme_update_config(pHddCtx->hHal, &sme_config);
15192 cbModeChange = true;
15193 }
15194 break;
15195
15196 case NL80211_CHAN_WIDTH_40:
15197 if (sme_config.csrConfig.channelBondingMode24GHz ==
15198 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
15199 if (NL80211_CHAN_HT40MINUS ==
15200 cfg80211_get_chandef_type(chandef))
15201 sme_config.csrConfig.channelBondingMode24GHz =
15202 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
15203 else
15204 sme_config.csrConfig.channelBondingMode24GHz =
15205 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
15206 sme_update_config(pHddCtx->hHal, &sme_config);
15207 cbModeChange = true;
15208 }
15209 break;
15210
15211 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015212 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015213 return -EINVAL;
15214 }
15215
15216 if (!cbModeChange)
15217 return 0;
15218
Krunal Sonib4326f22016-03-10 13:05:51 -080015219 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015220 return 0;
15221
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015222 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015223 sme_config.csrConfig.channelBondingMode24GHz);
15224
15225 /* Change SAP ht2040 mode */
15226 status = hdd_set_sap_ht2040_mode(pAdapter,
15227 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015228 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015229 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015230 return -EINVAL;
15231 }
15232
15233 return 0;
15234}
15235
15236/**
15237 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
15238 * @wiphy: Pointer to wiphy
15239 * @dev: Pointer to network device
15240 * @chandef: Pointer to channel definition parameter
15241 *
15242 * Return: 0 for success, non-zero for failure
15243 */
15244static int
15245wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
15246 struct net_device *dev,
15247 struct cfg80211_chan_def *chandef)
15248{
15249 int ret;
15250
15251 cds_ssr_protect(__func__);
15252 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
15253 cds_ssr_unprotect(__func__);
15254
15255 return ret;
15256}
15257#endif
15258
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015259#ifdef CHANNEL_SWITCH_SUPPORTED
15260/**
15261 * __wlan_hdd_cfg80211_channel_switch()- function to switch
15262 * channel in SAP/GO
15263 * @wiphy: wiphy pointer
15264 * @dev: dev pointer.
15265 * @csa_params: Change channel params
15266 *
15267 * This function is called to switch channel in SAP/GO
15268 *
15269 * Return: 0 if success else return non zero
15270 */
15271static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15272 struct net_device *dev,
15273 struct cfg80211_csa_settings *csa_params)
15274{
15275 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
15276 hdd_context_t *hdd_ctx;
15277 uint8_t channel;
15278 uint16_t freq;
15279 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080015280 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015281
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015282 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015283 csa_params->chandef.chan->center_freq);
15284
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015285 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
15286 hdd_err("invalid session id: %d", adapter->sessionId);
15287 return -EINVAL;
15288 }
15289
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015290 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
15291 ret = wlan_hdd_validate_context(hdd_ctx);
15292
15293 if (0 != ret)
15294 return ret;
15295
Krunal Sonib4326f22016-03-10 13:05:51 -080015296 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
15297 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015298 return -ENOTSUPP;
15299
15300 freq = csa_params->chandef.chan->center_freq;
15301 channel = cds_freq_to_chan(freq);
15302
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053015303 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
15304
15305 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015306 return ret;
15307}
15308
15309/**
15310 * wlan_hdd_cfg80211_channel_switch()- function to switch
15311 * channel in SAP/GO
15312 * @wiphy: wiphy pointer
15313 * @dev: dev pointer.
15314 * @csa_params: Change channel params
15315 *
15316 * This function is called to switch channel in SAP/GO
15317 *
15318 * Return: 0 if success else return non zero
15319 */
15320static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15321 struct net_device *dev,
15322 struct cfg80211_csa_settings *csa_params)
15323{
15324 int ret;
15325
15326 cds_ssr_protect(__func__);
15327 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
15328 cds_ssr_unprotect(__func__);
15329 return ret;
15330}
15331#endif
15332
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015333/**
15334 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
15335 * translation from NL to policy manager type
15336 * @type: Generic connection mode type defined in NL
15337 *
15338 *
15339 * This function provides the type translation
15340 *
15341 * Return: cds_con_mode enum
15342 */
15343enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
15344 enum nl80211_iftype type)
15345{
15346 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
15347 switch (type) {
15348 case NL80211_IFTYPE_STATION:
15349 mode = CDS_STA_MODE;
15350 break;
15351 case NL80211_IFTYPE_P2P_CLIENT:
15352 mode = CDS_P2P_CLIENT_MODE;
15353 break;
15354 case NL80211_IFTYPE_P2P_GO:
15355 mode = CDS_P2P_GO_MODE;
15356 break;
15357 case NL80211_IFTYPE_AP:
15358 mode = CDS_SAP_MODE;
15359 break;
15360 case NL80211_IFTYPE_ADHOC:
15361 mode = CDS_IBSS_MODE;
15362 break;
15363 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015364 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015365 type);
15366 }
15367 return mode;
15368}
15369
15370/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015371 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15372 * @wiphy: Handle to struct wiphy to get handle to module context.
15373 * @chandef: Contains information about the capture channel to be set.
15374 *
15375 * This interface is called if and only if monitor mode interface alone is
15376 * active.
15377 *
15378 * Return: 0 success or error code on failure.
15379 */
15380static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15381 struct cfg80211_chan_def *chandef)
15382{
15383 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15384 hdd_adapter_t *adapter;
15385 hdd_station_ctx_t *sta_ctx;
15386 struct hdd_mon_set_ch_info *ch_info;
15387 QDF_STATUS status;
15388 tHalHandle hal_hdl;
15389 struct qdf_mac_addr bssid;
15390 tCsrRoamProfile roam_profile;
15391 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015392 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015393 int ret;
15394 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
15395
15396 ENTER();
15397
15398 ret = wlan_hdd_validate_context(hdd_ctx);
15399 if (ret)
15400 return ret;
15401
15402 hal_hdl = hdd_ctx->hHal;
15403
15404 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
15405 if (!adapter)
15406 return -EIO;
15407
15408 hdd_info("%s: set monitor mode Channel %d and freq %d",
15409 adapter->dev->name, chan_num, chandef->chan->center_freq);
15410
15411 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15412 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015413 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
15414 roam_profile.ChannelInfo.numOfChannels = 1;
15415 roam_profile.phyMode = ch_info->phy_mode;
15416 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015417 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015418
15419 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
15420 QDF_MAC_ADDR_SIZE);
15421
15422 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015423 /*
15424 * CDS api expects secondary channel for calculating
15425 * the channel params
15426 */
15427 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
15428 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
15429 if (chan_num >= 1 && chan_num <= 5)
15430 sec_ch = chan_num + 4;
15431 else if (chan_num >= 6 && chan_num <= 13)
15432 sec_ch = chan_num - 4;
15433 }
15434 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015435 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
15436 &roam_profile);
15437 if (status) {
15438 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
15439 status);
15440 ret = qdf_status_to_os_return(status);
15441 return ret;
15442 }
15443 EXIT();
15444 return 0;
15445}
15446
15447/**
15448 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15449 * @wiphy: Handle to struct wiphy to get handle to module context.
15450 * @chandef: Contains information about the capture channel to be set.
15451 *
15452 * This interface is called if and only if monitor mode interface alone is
15453 * active.
15454 *
15455 * Return: 0 success or error code on failure.
15456 */
15457static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15458 struct cfg80211_chan_def *chandef)
15459{
15460 int ret;
15461
15462 cds_ssr_protect(__func__);
15463 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
15464 cds_ssr_unprotect(__func__);
15465 return ret;
15466}
15467
15468/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015469 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
15470 * @adapter: pointer to adapter
15471 *
15472 * Wrapper function to clear link layer stats.
15473 * return - void
15474 */
15475void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
15476{
15477 tSirLLStatsClearReq link_layer_stats_clear_req;
15478 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
15479
Mukul Sharma491021c2016-09-29 21:39:19 +053015480 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
15481 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015482 link_layer_stats_clear_req.stopReq = 0;
15483 link_layer_stats_clear_req.reqId = 1;
15484 link_layer_stats_clear_req.staId = adapter->sessionId;
15485 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
15486
15487 return;
15488}
15489
15490/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015491 * struct cfg80211_ops - cfg80211_ops
15492 *
15493 * @add_virtual_intf: Add virtual interface
15494 * @del_virtual_intf: Delete virtual interface
15495 * @change_virtual_intf: Change virtual interface
15496 * @change_station: Change station
15497 * @add_beacon: Add beacon in sap mode
15498 * @del_beacon: Delete beacon in sap mode
15499 * @set_beacon: Set beacon in sap mode
15500 * @start_ap: Start ap
15501 * @change_beacon: Change beacon
15502 * @stop_ap: Stop ap
15503 * @change_bss: Change bss
15504 * @add_key: Add key
15505 * @get_key: Get key
15506 * @del_key: Delete key
15507 * @set_default_key: Set default key
15508 * @set_channel: Set channel
15509 * @scan: Scan
15510 * @connect: Connect
15511 * @disconnect: Disconnect
15512 * @join_ibss = Join ibss
15513 * @leave_ibss = Leave ibss
15514 * @set_wiphy_params = Set wiphy params
15515 * @set_tx_power = Set tx power
15516 * @get_tx_power = get tx power
15517 * @remain_on_channel = Remain on channel
15518 * @cancel_remain_on_channel = Cancel remain on channel
15519 * @mgmt_tx = Tx management frame
15520 * @mgmt_tx_cancel_wait = Cancel management tx wait
15521 * @set_default_mgmt_key = Set default management key
15522 * @set_txq_params = Set tx queue parameters
15523 * @get_station = Get station
15524 * @set_power_mgmt = Set power management
15525 * @del_station = Delete station
15526 * @add_station = Add station
15527 * @set_pmksa = Set pmksa
15528 * @del_pmksa = Delete pmksa
15529 * @flush_pmksa = Flush pmksa
15530 * @update_ft_ies = Update FT IEs
15531 * @tdls_mgmt = Tdls management
15532 * @tdls_oper = Tdls operation
15533 * @set_rekey_data = Set rekey data
15534 * @sched_scan_start = Scheduled scan start
15535 * @sched_scan_stop = Scheduled scan stop
15536 * @resume = Resume wlan
15537 * @suspend = Suspend wlan
15538 * @set_mac_acl = Set mac acl
15539 * @testmode_cmd = Test mode command
15540 * @set_ap_chanwidth = Set AP channel bandwidth
15541 * @dump_survey = Dump survey
15542 * @key_mgmt_set_pmk = Set pmk key management
15543 */
15544static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
15545 .add_virtual_intf = wlan_hdd_add_virtual_intf,
15546 .del_virtual_intf = wlan_hdd_del_virtual_intf,
15547 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
15548 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015549 .start_ap = wlan_hdd_cfg80211_start_ap,
15550 .change_beacon = wlan_hdd_cfg80211_change_beacon,
15551 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015552 .change_bss = wlan_hdd_cfg80211_change_bss,
15553 .add_key = wlan_hdd_cfg80211_add_key,
15554 .get_key = wlan_hdd_cfg80211_get_key,
15555 .del_key = wlan_hdd_cfg80211_del_key,
15556 .set_default_key = wlan_hdd_cfg80211_set_default_key,
15557 .scan = wlan_hdd_cfg80211_scan,
15558 .connect = wlan_hdd_cfg80211_connect,
15559 .disconnect = wlan_hdd_cfg80211_disconnect,
15560 .join_ibss = wlan_hdd_cfg80211_join_ibss,
15561 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
15562 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
15563 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
15564 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
15565 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
15566 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
15567 .mgmt_tx = wlan_hdd_mgmt_tx,
15568 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
15569 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
15570 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053015571 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015572 .get_station = wlan_hdd_cfg80211_get_station,
15573 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
15574 .del_station = wlan_hdd_cfg80211_del_station,
15575 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015576 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
15577 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
15578 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015579#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015580 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
15581#endif
15582#ifdef FEATURE_WLAN_TDLS
15583 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
15584 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
15585#endif
15586#ifdef WLAN_FEATURE_GTK_OFFLOAD
15587 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
15588#endif /* WLAN_FEATURE_GTK_OFFLOAD */
15589#ifdef FEATURE_WLAN_SCAN_PNO
15590 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
15591 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
15592#endif /*FEATURE_WLAN_SCAN_PNO */
15593 .resume = wlan_hdd_cfg80211_resume_wlan,
15594 .suspend = wlan_hdd_cfg80211_suspend_wlan,
15595 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
15596#ifdef WLAN_NL80211_TESTMODE
15597 .testmode_cmd = wlan_hdd_cfg80211_testmode,
15598#endif
15599#ifdef QCA_HT_2040_COEX
15600 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
15601#endif
15602 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015603#ifdef CHANNEL_SWITCH_SUPPORTED
15604 .channel_switch = wlan_hdd_cfg80211_channel_switch,
15605#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015606 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053015607#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
15608 defined(CFG80211_ABORT_SCAN)
15609 .abort_scan = wlan_hdd_cfg80211_abort_scan,
15610#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015611};