blob: 864171e5efb8b286957254e8c17f51e95b07ca77 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002 * Copyright (c) 2012-2016 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
Jeff Johnson9c50e782016-06-29 15:28:56 -070035/* denote that this file does not allow legacy hddLog */
36#define HDD_DISALLOW_LEGACY_HDDLOG 1
37
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080038#include <linux/version.h>
39#include <linux/module.h>
40#include <linux/kernel.h>
41#include <linux/init.h>
42#include <linux/etherdevice.h>
43#include <linux/wireless.h>
44#include <wlan_hdd_includes.h>
45#include <net/arp.h>
46#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053047#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048#include <wlan_hdd_wowl.h>
49#include <ani_global.h>
50#include "sir_params.h"
51#include "dot11f.h"
52#include "wlan_hdd_assoc.h"
53#include "wlan_hdd_wext.h"
54#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070055#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080056#include "wlan_hdd_p2p.h"
57#include "wlan_hdd_cfg80211.h"
58#include "wlan_hdd_hostapd.h"
59#include "wlan_hdd_softap_tx_rx.h"
60#include "wlan_hdd_main.h"
61#include "wlan_hdd_power.h"
62#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053063#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053064#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080065#include "cds_utils.h"
66#include "cds_sched.h"
67#include "wlan_hdd_scan.h"
68#include <qc_sap_ioctl.h>
69#include "wlan_hdd_tdls.h"
70#include "wlan_hdd_wmm.h"
71#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053072#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080073#include "wlan_hdd_misc.h"
74#include "wlan_hdd_nan.h"
75#include <wlan_hdd_ipa.h>
76#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053077#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053078#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053079#include "pld_common.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053080
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 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001103};
1104
1105/**
1106 * __is_driver_dfs_capable() - get driver DFS capability
1107 * @wiphy: pointer to wireless wiphy structure.
1108 * @wdev: pointer to wireless_dev structure.
1109 * @data: Pointer to the data to be passed via vendor interface
1110 * @data_len:Length of the data to be passed
1111 *
1112 * This function is called by userspace to indicate whether or not
1113 * the driver supports DFS offload.
1114 *
1115 * Return: 0 on success, negative errno on failure
1116 */
1117static int __is_driver_dfs_capable(struct wiphy *wiphy,
1118 struct wireless_dev *wdev,
1119 const void *data,
1120 int data_len)
1121{
1122 u32 dfs_capability = 0;
1123 struct sk_buff *temp_skbuff;
1124 int ret_val;
1125 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1126
Jeff Johnson1f61b612016-02-12 16:28:33 -08001127 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001128
1129 ret_val = wlan_hdd_validate_context(hdd_ctx);
1130 if (ret_val)
1131 return ret_val;
1132
Anurag Chouhan6d760662016-02-20 16:05:43 +05301133 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134 hdd_err("Command not allowed in FTM mode");
1135 return -EPERM;
1136 }
1137
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001138 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001139
1140 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1141 NLMSG_HDRLEN);
1142
1143 if (temp_skbuff != NULL) {
1144 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1145 dfs_capability);
1146 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001147 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001148 kfree_skb(temp_skbuff);
1149
1150 return ret_val;
1151 }
1152
1153 return cfg80211_vendor_cmd_reply(temp_skbuff);
1154 }
1155
Jeff Johnson020db452016-06-29 14:37:26 -07001156 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001157 return -ENOMEM;
1158}
1159
1160/**
1161 * is_driver_dfs_capable() - get driver DFS capability
1162 * @wiphy: pointer to wireless wiphy structure.
1163 * @wdev: pointer to wireless_dev structure.
1164 * @data: Pointer to the data to be passed via vendor interface
1165 * @data_len:Length of the data to be passed
1166 *
1167 * This function is called by userspace to indicate whether or not
1168 * the driver supports DFS offload. This is an SSR-protected
1169 * wrapper function.
1170 *
1171 * Return: 0 on success, negative errno on failure
1172 */
1173static int is_driver_dfs_capable(struct wiphy *wiphy,
1174 struct wireless_dev *wdev,
1175 const void *data,
1176 int data_len)
1177{
1178 int ret;
1179
1180 cds_ssr_protect(__func__);
1181 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1182 cds_ssr_unprotect(__func__);
1183
1184 return ret;
1185}
1186
1187/**
1188 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1189 *
1190 * @adapter: SAP adapter pointer
1191 *
1192 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1193 * radio. So in case of DFS MCC scenario override current SAP given config
1194 * to follow concurrent SAP DFS config
1195 *
1196 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1197 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001198int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1199{
1200 hdd_adapter_t *con_sap_adapter;
1201 tsap_Config_t *sap_config, *con_sap_config;
1202 int con_ch;
1203
1204 /*
1205 * Check if AP+AP case, once primary AP chooses a DFS
1206 * channel secondary AP should always follow primary APs channel
1207 */
1208 if (!cds_concurrent_beaconing_sessions_running())
1209 return 0;
1210
1211 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1212 if (!con_sap_adapter)
1213 return 0;
1214
1215 sap_config = &adapter->sessionCtx.ap.sapConfig;
1216 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1217 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1218
1219 if (!CDS_IS_DFS_CH(con_ch))
1220 return 0;
1221
Jeff Johnson020db452016-06-29 14:37:26 -07001222 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001224 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225 sap_config->channel = con_ch;
1226
1227 if (con_sap_config->acs_cfg.acs_mode == true) {
1228 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1229 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001230 hdd_err("Primary AP channel config error");
1231 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001232 con_ch, con_sap_config->acs_cfg.pri_ch,
1233 con_sap_config->acs_cfg.ht_sec_ch);
1234 return -EINVAL;
1235 }
1236 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1237 * MCC restriction. So free ch list allocated in do_acs
1238 * func for Sec AP and realloc for Pri AP ch list size
1239 */
1240 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301241 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301243 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001244 &con_sap_config->acs_cfg,
1245 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301246 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001247 sizeof(uint8_t) *
1248 con_sap_config->acs_cfg.ch_list_count);
1249 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001250 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001251 return -ENOMEM;
1252 }
1253
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301254 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 con_sap_config->acs_cfg.ch_list,
1256 con_sap_config->acs_cfg.ch_list_count);
1257
1258 } else {
1259 sap_config->acs_cfg.pri_ch = con_ch;
1260 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1261 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1262 }
1263
1264 return con_ch;
1265}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001266
1267/**
1268 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1269 * @sap_cfg: pointer to SAP config struct
1270 *
1271 * This function sets the default ACS start and end channel for the given band
1272 * and also parses the given ACS channel list.
1273 *
1274 * Return: None
1275 */
1276
1277static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1278 bool vht_enabled)
1279{
1280 int i;
1281 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1282 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001283 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1284 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001285 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1286 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001287 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1288 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1290 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001291 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1292 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001293 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1294 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001295 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1296 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 }
1298
1299 if (ht_enabled)
1300 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1301
1302 if (vht_enabled)
1303 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1304
1305
1306 /* Parse ACS Chan list from hostapd */
1307 if (!sap_cfg->acs_cfg.ch_list)
1308 return;
1309
1310 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1311 sap_cfg->acs_cfg.end_ch =
1312 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1313 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301314 /* avoid channel as start channel */
1315 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1316 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001317 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1318 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1319 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1320 }
1321}
1322
1323
1324static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1325
1326/**
1327 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1328 * @adapter: pointer to SAP adapter struct
1329 *
1330 * This function starts the ACS procedure if there are no
1331 * constraints like MBSSID DFS restrictions.
1332 *
1333 * Return: Status of ACS Start procedure
1334 */
1335
1336static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1337{
1338
1339 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1340 tsap_Config_t *sap_config;
1341 tpWLAN_SAPEventCB acs_event_callback;
1342 int status;
1343
1344 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301345 if (hdd_ctx->acs_policy.acs_channel)
1346 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1347 else
1348 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001349
1350 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1351 if (status < 0) {
1352 return status;
1353 } else {
1354 if (status > 0) {
1355 /*notify hostapd about channel override */
1356 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1357 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1358 return 0;
1359 }
1360 }
1361 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1362 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001363 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364 return -EINVAL;
1365 }
1366
1367 acs_event_callback = hdd_hostapd_sap_event_cb;
1368
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301369 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301370 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001371 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001373 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374 acs_event_callback, sap_config, adapter->dev);
1375
1376
1377 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001378 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379 return -EINVAL;
1380 }
1381 sap_config->acs_cfg.acs_mode = true;
1382 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1383
1384 return 0;
1385}
1386
1387/**
1388 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1389 * @wiphy: Linux wiphy struct pointer
1390 * @wdev: Linux wireless device struct pointer
1391 * @data: ACS information from hostapd
1392 * @data_len: ACS information length
1393 *
1394 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1395 * and starts ACS procedure.
1396 *
1397 * Return: ACS procedure start status
1398 */
1399
1400static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1401 struct wireless_dev *wdev,
1402 const void *data, int data_len)
1403{
1404 struct net_device *ndev = wdev->netdev;
1405 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1406 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1407 tsap_Config_t *sap_config;
1408 struct sk_buff *temp_skbuff;
1409 int status = -EINVAL, i = 0;
1410 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1411 bool ht_enabled, ht40_enabled, vht_enabled;
1412 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301413 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001414
1415 /* ***Note*** Donot set SME config related to ACS operation here because
1416 * ACS operation is not synchronouse and ACS for Second AP may come when
1417 * ACS operation for first AP is going on. So only do_acs is split to
1418 * seperate start_acs routine. Also SME-PMAC struct that is used to
1419 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1420 * config shall be set only from start_acs.
1421 */
1422
1423 /* nla_policy Policy template. Policy not applied as some attributes are
1424 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1425 *
1426 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1427 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1428 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1429 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1430 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1431 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1432 */
1433
Jeff Johnson1f61b612016-02-12 16:28:33 -08001434 ENTER_DEV(ndev);
1435
Anurag Chouhan6d760662016-02-20 16:05:43 +05301436 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001437 hdd_err("Command not allowed in FTM mode");
1438 return -EPERM;
1439 }
1440
1441 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001442 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001443 return -EPERM;
1444 }
1445
1446 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301447 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001448 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301449
Naveen Rawat64e477e2016-05-20 10:34:56 -07001450 if (cds_is_sub_20_mhz_enabled()) {
1451 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1452 status = -EINVAL;
1453 goto out;
1454 }
1455
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301457 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001458
1459 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1460 NULL);
1461 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001462 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001463 goto out;
1464 }
1465
1466 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001467 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001468 goto out;
1469 }
1470 sap_config->acs_cfg.hw_mode = nla_get_u8(
1471 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1472
1473 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1474 ht_enabled =
1475 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1476 else
1477 ht_enabled = 0;
1478
1479 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1480 ht40_enabled =
1481 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1482 else
1483 ht40_enabled = 0;
1484
1485 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1486 vht_enabled =
1487 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1488 else
1489 vht_enabled = 0;
1490
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301491 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1492 vht_enabled = 0;
1493 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1494 }
1495
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001496 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1497 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1498 } else {
1499 if (ht_enabled && ht40_enabled)
1500 ch_width = 40;
1501 else
1502 ch_width = 20;
1503 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301504
1505 /* this may be possible, when sap_force_11n_for_11ac is set */
1506 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1507 if (ht_enabled && ht40_enabled)
1508 ch_width = 40;
1509 else
1510 ch_width = 20;
1511 }
1512
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001513 if (ch_width == 80)
1514 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1515 else if (ch_width == 40)
1516 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1517 else
1518 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1519
1520 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1521 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1522 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1523 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1524 * since it contains the frequency values of the channels in
1525 * the channel list.
1526 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1527 * is present
1528 */
1529 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1530 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1531 sap_config->acs_cfg.ch_list_count = nla_len(
1532 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1533 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301534 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001535 sizeof(uint8_t) *
1536 sap_config->acs_cfg.ch_list_count);
1537 if (sap_config->acs_cfg.ch_list == NULL)
1538 goto out;
1539
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301540 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541 sap_config->acs_cfg.ch_list_count);
1542 }
1543 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1544 uint32_t *freq =
1545 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1546 sap_config->acs_cfg.ch_list_count = nla_len(
1547 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1548 sizeof(uint32_t);
1549 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301550 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001551 sap_config->acs_cfg.ch_list_count);
1552 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001553 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001554 status = -ENOMEM;
1555 goto out;
1556 }
1557
1558 /* convert frequency to channel */
1559 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1560 sap_config->acs_cfg.ch_list[i] =
1561 ieee80211_frequency_to_channel(freq[i]);
1562 }
1563 }
1564
1565 hdd_debug("get pcl for DO_ACS vendor command");
1566
1567 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001568 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301569 sap_config->acs_cfg.pcl_channels,
1570 &sap_config->acs_cfg.pcl_ch_count,
1571 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301572 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001573 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001574
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001575 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301576 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
1577 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07001578 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001579 vht_enabled = 1;
1580 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1581 sap_config->acs_cfg.ch_width =
1582 hdd_ctx->config->vhtChannelWidth;
1583 /* No VHT80 in 2.4G so perform ACS accordingly */
1584 if (sap_config->acs_cfg.end_ch <= 14 &&
1585 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1586 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1587 }
1588
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301589 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1590
Jeff Johnson020db452016-06-29 14:37:26 -07001591 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 -08001592 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1593 ch_width, ht_enabled, vht_enabled,
1594 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1595
1596 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001597 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001598 sap_config->acs_cfg.ch_list_count);
1599 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001600 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001601 }
1602 sap_config->acs_cfg.acs_mode = true;
1603 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001604 /* ***Note*** Completion variable usage is not allowed
1605 * here since ACS scan operation may take max 2.2 sec
1606 * for 5G band:
1607 * 9 Active channel X 40 ms active scan time +
1608 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001609 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1610 * for this long. So we split up the scanning part.
1611 */
1612 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001613 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001614 status = 0;
1615 } else {
1616 status = wlan_hdd_cfg80211_start_acs(adapter);
1617 }
1618
1619out:
1620 if (0 == status) {
1621 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1622 NLMSG_HDRLEN);
1623 if (temp_skbuff != NULL)
1624 return cfg80211_vendor_cmd_reply(temp_skbuff);
1625 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001626 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001627 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1628
1629 return status;
1630}
1631
1632 /**
1633 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1634 * @wiphy: Linux wiphy struct pointer
1635 * @wdev: Linux wireless device struct pointer
1636 * @data: ACS information from hostapd
1637 * @data_len: ACS information len
1638 *
1639 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1640 * and starts ACS procedure.
1641 *
1642 * Return: ACS procedure start status
1643 */
1644
1645static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1646 struct wireless_dev *wdev,
1647 const void *data, int data_len)
1648{
1649 int ret;
1650
1651 cds_ssr_protect(__func__);
1652 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1653 cds_ssr_unprotect(__func__);
1654
1655 return ret;
1656}
1657
1658/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001659 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
1660 * @adapter: Pointer to adapter struct
1661 *
1662 * This function handle cleanup of what was done in DO_ACS, including free
1663 * memory.
1664 *
1665 * Return: void
1666 */
1667
1668void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
1669{
1670 if (adapter == NULL)
1671 return;
1672 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
1673 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
1674 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
1675 }
1676}
1677
1678/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001679 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1680 * @work: Linux workqueue struct pointer for ACS work
1681 *
1682 * This function starts the ACS procedure which was marked pending when an ACS
1683 * procedure was in progress for a concurrent SAP interface.
1684 *
1685 * Return: None
1686 */
1687
1688static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1689{
1690 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1691 acs_pending_work.work);
1692 wlan_hdd_cfg80211_start_acs(adapter);
1693}
1694
1695/**
1696 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1697 * @adapter: Pointer to SAP adapter struct
1698 * @pri_channel: SAP ACS procedure selected Primary channel
1699 * @sec_channel: SAP ACS procedure selected secondary channel
1700 *
1701 * This is a callback function from SAP module on ACS procedure is completed.
1702 * This function send the ACS selected channel information to hostapd
1703 *
1704 * Return: None
1705 */
1706
1707void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1708{
1709 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1710 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1711 struct sk_buff *vendor_event;
1712 int ret_val;
1713 hdd_adapter_t *con_sap_adapter;
1714 uint16_t ch_width;
1715
1716 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001717 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001718 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1719 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1720 GFP_KERNEL);
1721
1722 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001723 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001724 return;
1725 }
1726
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001727 ret_val = nla_put_u8(vendor_event,
1728 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1729 sap_cfg->acs_cfg.pri_ch);
1730 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001731 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001732 kfree_skb(vendor_event);
1733 return;
1734 }
1735
1736 ret_val = nla_put_u8(vendor_event,
1737 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1738 sap_cfg->acs_cfg.ht_sec_ch);
1739 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001740 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001741 kfree_skb(vendor_event);
1742 return;
1743 }
1744
1745 ret_val = nla_put_u8(vendor_event,
1746 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1747 sap_cfg->acs_cfg.vht_seg0_center_ch);
1748 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001749 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001750 kfree_skb(vendor_event);
1751 return;
1752 }
1753
1754 ret_val = nla_put_u8(vendor_event,
1755 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1756 sap_cfg->acs_cfg.vht_seg1_center_ch);
1757 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001758 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001759 kfree_skb(vendor_event);
1760 return;
1761 }
1762
1763 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1764 ch_width = 80;
1765 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1766 ch_width = 40;
1767 else
1768 ch_width = 20;
1769
1770 ret_val = nla_put_u16(vendor_event,
1771 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1772 ch_width);
1773 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001774 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001775 kfree_skb(vendor_event);
1776 return;
1777 }
1778 if (sap_cfg->acs_cfg.pri_ch > 14)
1779 ret_val = nla_put_u8(vendor_event,
1780 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1781 QCA_ACS_MODE_IEEE80211A);
1782 else
1783 ret_val = nla_put_u8(vendor_event,
1784 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1785 QCA_ACS_MODE_IEEE80211G);
1786
1787 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001788 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001789 kfree_skb(vendor_event);
1790 return;
1791 }
1792
Jeff Johnson46b40792016-06-29 14:03:14 -07001793 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 -08001794 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1795 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1796 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1797
1798 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1799 /* ***Note*** As already mentioned Completion variable usage is not
1800 * allowed here since ACS scan operation may take max 2.2 sec.
1801 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1802 * operation.
1803 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1804 * when Primary AP ACS is complete and secondary AP ACS is started here
1805 * immediately, Primary AP start_bss may come inbetween ACS operation
1806 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1807 * delay. This path and below constraint will be removed on sessionizing
1808 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1809 * As per design constraint user space control application must take
1810 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1811 * this code path. Sec AP hostapd should be started after Primary AP
1812 * start beaconing which can be confirmed by getchannel iwpriv command
1813 */
1814
1815 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1816 if (con_sap_adapter &&
1817 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001818 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1819 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001820 /* Lets give 500ms for OBSS + START_BSS to complete */
1821 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1822 msecs_to_jiffies(500));
1823 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1824 }
1825
1826 return;
1827}
1828
1829static int
1830__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1831 struct wireless_dev *wdev,
1832 const void *data,
1833 int data_len)
1834{
1835 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1836 struct sk_buff *skb = NULL;
1837 uint32_t fset = 0;
1838 int ret;
1839
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001840 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301841
Anurag Chouhan6d760662016-02-20 16:05:43 +05301842 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843 hdd_err("Command not allowed in FTM mode");
1844 return -EPERM;
1845 }
1846
1847 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301848 if (ret)
1849 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001850
1851 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001852 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001853 fset |= WIFI_FEATURE_INFRA;
1854 }
1855 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001856 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001857 fset |= WIFI_FEATURE_INFRA_5G;
1858 }
1859#ifdef WLAN_FEATURE_P2P
1860 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1861 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001862 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001863 fset |= WIFI_FEATURE_P2P;
1864 }
1865#endif
1866 fset |= WIFI_FEATURE_SOFT_AP;
1867
1868 /* HOTSPOT is a supplicant feature, enable it by default */
1869 fset |= WIFI_FEATURE_HOTSPOT;
1870
1871#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301872 if (pHddCtx->config->extscan_enabled &&
1873 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001874 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001875 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1876 }
1877#endif
1878 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001879 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001880 fset |= WIFI_FEATURE_NAN;
1881 }
1882 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001883 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001884 fset |= WIFI_FEATURE_D2D_RTT;
1885 fset |= WIFI_FEATURE_D2AP_RTT;
1886 }
1887#ifdef FEATURE_WLAN_SCAN_PNO
1888 if (pHddCtx->config->configPNOScanSupport &&
1889 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001890 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891 fset |= WIFI_FEATURE_PNO;
1892 }
1893#endif
1894 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1895#ifdef FEATURE_WLAN_TDLS
1896 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1897 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001898 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001899 fset |= WIFI_FEATURE_TDLS;
1900 }
1901 if (sme_is_feature_supported_by_fw(TDLS) &&
1902 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1903 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001904 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001905 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1906 }
1907#endif
1908#ifdef WLAN_AP_STA_CONCURRENCY
1909 fset |= WIFI_FEATURE_AP_STA;
1910#endif
1911 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07001912 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001913
1914 if (hdd_link_layer_stats_supported())
1915 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1916
1917 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1918 NLMSG_HDRLEN);
1919 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001920 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001921 return -EINVAL;
1922 }
Jeff Johnson020db452016-06-29 14:37:26 -07001923 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001924 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001925 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001926 goto nla_put_failure;
1927 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301928 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301929 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930nla_put_failure:
1931 kfree_skb(skb);
1932 return -EINVAL;
1933}
1934
1935/**
1936 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1937 * @wiphy: pointer to wireless wiphy structure.
1938 * @wdev: pointer to wireless_dev structure.
1939 * @data: Pointer to the data to be passed via vendor interface
1940 * @data_len:Length of the data to be passed
1941 *
1942 * Return: Return the Success or Failure code.
1943 */
1944static int
1945wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1946 struct wireless_dev *wdev,
1947 const void *data, int data_len)
1948{
1949 int ret = 0;
1950
1951 cds_ssr_protect(__func__);
1952 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1953 data, data_len);
1954 cds_ssr_unprotect(__func__);
1955
1956 return ret;
1957}
1958
1959/**
1960 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1961 * @wiphy: pointer to wireless wiphy structure.
1962 * @wdev: pointer to wireless_dev structure.
1963 * @data: Pointer to the data to be passed via vendor interface
1964 * @data_len:Length of the data to be passed
1965 *
1966 * Set the MAC address that is to be used for scanning.
1967 *
1968 * Return: Return the Success or Failure code.
1969 */
1970static int
1971__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1972 struct wireless_dev *wdev,
1973 const void *data,
1974 int data_len)
1975{
1976 tpSirScanMacOui pReqMsg = NULL;
1977 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1978 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301979 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001980 int ret;
1981
Jeff Johnson1f61b612016-02-12 16:28:33 -08001982 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983
Anurag Chouhan6d760662016-02-20 16:05:43 +05301984 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 hdd_err("Command not allowed in FTM mode");
1986 return -EPERM;
1987 }
1988
1989 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301990 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001991 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992
1993 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001994 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001995 return -ENOTSUPP;
1996 }
1997
1998 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1999 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002000 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002001 return -EINVAL;
2002 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302003 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002004 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002005 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002006 return -ENOMEM;
2007 }
2008 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002009 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010 goto fail;
2011 }
2012 nla_memcpy(&pReqMsg->oui[0],
2013 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2014 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002015 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002016 pReqMsg->oui[1], pReqMsg->oui[2]);
2017 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302018 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002019 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020 goto fail;
2021 }
2022 return 0;
2023fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302024 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 return -EINVAL;
2026}
2027
2028/**
2029 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2030 * @wiphy: pointer to wireless wiphy structure.
2031 * @wdev: pointer to wireless_dev structure.
2032 * @data: Pointer to the data to be passed via vendor interface
2033 * @data_len:Length of the data to be passed
2034 *
2035 * Set the MAC address that is to be used for scanning. This is an
2036 * SSR-protecting wrapper function.
2037 *
2038 * Return: Return the Success or Failure code.
2039 */
2040static int
2041wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2042 struct wireless_dev *wdev,
2043 const void *data,
2044 int data_len)
2045{
2046 int ret;
2047
2048 cds_ssr_protect(__func__);
2049 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2050 data, data_len);
2051 cds_ssr_unprotect(__func__);
2052
2053 return ret;
2054}
2055
2056/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302057 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2058 * @wiphy: pointer phy adapter
2059 * @wdev: pointer to wireless device structure
2060 * @data: pointer to data buffer
2061 * @data_len: length of data
2062 *
2063 * This routine will give concurrency matrix
2064 *
2065 * Return: int status code
2066 */
2067static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2068 struct wireless_dev *wdev,
2069 const void *data,
2070 int data_len)
2071{
2072 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2073 uint8_t i, feature_sets, max_feature_sets;
2074 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2075 struct sk_buff *reply_skb;
2076 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2077 int ret;
2078
2079 ENTER_DEV(wdev->netdev);
2080
2081 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2082 hdd_err("Command not allowed in FTM mode");
2083 return -EPERM;
2084 }
2085
2086 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302087 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302088 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302089
2090 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2091 data, data_len, NULL)) {
2092 hdd_err("Invalid ATTR");
2093 return -EINVAL;
2094 }
2095
2096 /* Parse and fetch max feature set */
2097 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2098 hdd_err("Attr max feature set size failed");
2099 return -EINVAL;
2100 }
2101 max_feature_sets = nla_get_u32(tb[
2102 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2103 hdd_info("Max feature set size: %d", max_feature_sets);
2104
2105 /* Fill feature combination matrix */
2106 feature_sets = 0;
2107 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002108 WIFI_FEATURE_P2P;
2109 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2110 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302111 /* Add more feature combinations here */
2112
2113 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002114 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302115 hdd_info("Feature set matrix");
2116 for (i = 0; i < feature_sets; i++)
2117 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2118
2119 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2120 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2121 if (!reply_skb) {
2122 hdd_err("Feature set matrix: buffer alloc fail");
2123 return -ENOMEM;
2124 }
2125
2126 if (nla_put_u32(reply_skb,
2127 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2128 feature_sets) ||
2129 nla_put(reply_skb,
2130 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2131 sizeof(u32) * feature_sets,
2132 feature_set_matrix)) {
2133 hdd_err("nla put fail");
2134 kfree_skb(reply_skb);
2135 return -EINVAL;
2136 }
2137 return cfg80211_vendor_cmd_reply(reply_skb);
2138}
2139
2140/**
2141 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2142 * @wiphy: pointer to wireless wiphy structure.
2143 * @wdev: pointer to wireless_dev structure.
2144 * @data: Pointer to the data to be passed via vendor interface
2145 * @data_len:Length of the data to be passed
2146 *
2147 * Retrieves the concurrency feature set matrix
2148 *
2149 * Return: 0 on success, negative errno on failure
2150 */
2151static int
2152wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2153 struct wireless_dev *wdev,
2154 const void *data,
2155 int data_len)
2156{
2157 int ret;
2158
2159 cds_ssr_protect(__func__);
2160 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2161 data, data_len);
2162 cds_ssr_unprotect(__func__);
2163
2164 return ret;
2165}
2166
2167/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002168 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2169 * @feature_flags: pointer to the byte array of features.
2170 * @feature: Feature to be turned ON in the byte array.
2171 *
2172 * Return: None
2173 *
2174 * This is called to turn ON or SET the feature flag for the requested feature.
2175 **/
2176#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002177static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2178 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002179{
2180 uint32_t index;
2181 uint8_t bit_mask;
2182
2183 index = feature / NUM_BITS_IN_BYTE;
2184 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2185 feature_flags[index] |= bit_mask;
2186}
2187
2188/**
2189 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2190 * @wiphy: pointer to wireless wiphy structure.
2191 * @wdev: pointer to wireless_dev structure.
2192 * @data: Pointer to the data to be passed via vendor interface
2193 * @data_len:Length of the data to be passed
2194 *
2195 * This is called when wlan driver needs to send supported feature set to
2196 * supplicant upon a request/query from the supplicant.
2197 *
2198 * Return: Return the Success or Failure code.
2199 **/
2200#define MAX_CONCURRENT_CHAN_ON_24G 2
2201#define MAX_CONCURRENT_CHAN_ON_5G 2
2202static int
2203__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2204 struct wireless_dev *wdev,
2205 const void *data, int data_len)
2206{
2207 struct sk_buff *skb = NULL;
2208 uint32_t dbs_capability = 0;
2209 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302210 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002211 int ret_val;
2212
2213 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2214 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2215
Jeff Johnson1f61b612016-02-12 16:28:33 -08002216 ENTER_DEV(wdev->netdev);
2217
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002218 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2219 if (ret_val)
2220 return ret_val;
2221
Anurag Chouhan6d760662016-02-20 16:05:43 +05302222 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002223 hdd_err("Command not allowed in FTM mode");
2224 return -EPERM;
2225 }
2226
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002227 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002228 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002229 wlan_hdd_cfg80211_set_feature(feature_flags,
2230 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2231 }
2232
2233 wlan_hdd_cfg80211_set_feature(feature_flags,
2234 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2235 if (wma_is_scan_simultaneous_capable())
2236 wlan_hdd_cfg80211_set_feature(feature_flags,
2237 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002238
2239 if (wma_is_p2p_lo_capable())
2240 wlan_hdd_cfg80211_set_feature(feature_flags,
2241 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2242
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002243 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2244 NLMSG_HDRLEN);
2245
2246 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002247 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002248 return -ENOMEM;
2249 }
2250
2251 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2252 sizeof(feature_flags), feature_flags))
2253 goto nla_put_failure;
2254
2255 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302256 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002257 if (one_by_one_dbs)
2258 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2259
2260 if (two_by_two_dbs)
2261 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2262
2263 if (!one_by_one_dbs && !two_by_two_dbs)
2264 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2265 } else {
2266 hdd_err("wma_get_dbs_hw_mode failed");
2267 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2268 }
2269
2270 hdd_info("dbs_capability is %d", dbs_capability);
2271
2272 if (nla_put_u32(skb,
2273 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2274 MAX_CONCURRENT_CHAN_ON_24G))
2275 goto nla_put_failure;
2276
2277 if (nla_put_u32(skb,
2278 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2279 MAX_CONCURRENT_CHAN_ON_5G))
2280 goto nla_put_failure;
2281
2282 return cfg80211_vendor_cmd_reply(skb);
2283
2284nla_put_failure:
2285 kfree_skb(skb);
2286 return -EINVAL;
2287}
2288
2289/**
2290 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2291 * @wiphy: pointer to wireless wiphy structure.
2292 * @wdev: pointer to wireless_dev structure.
2293 * @data: Pointer to the data to be passed via vendor interface
2294 * @data_len:Length of the data to be passed
2295 *
2296 * This is called when wlan driver needs to send supported feature set to
2297 * supplicant upon a request/query from the supplicant.
2298 *
2299 * Return: Return the Success or Failure code.
2300 */
2301static int
2302wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2303 struct wireless_dev *wdev,
2304 const void *data, int data_len)
2305{
2306 int ret;
2307
2308 cds_ssr_protect(__func__);
2309 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2310 data, data_len);
2311 cds_ssr_unprotect(__func__);
2312
2313 return ret;
2314}
2315
2316
2317/**
2318 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2319 * @wiphy: The wiphy structure
2320 * @wdev: The wireless device
2321 * @data: Data passed by framework
2322 * @data_len: Parameters to be configured passed as data
2323 *
2324 * The roaming related parameters are configured by the framework
2325 * using this interface.
2326 *
2327 * Return: Return either success or failure code.
2328 */
2329static int
2330__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2331 struct wireless_dev *wdev, const void *data, int data_len)
2332{
2333 struct net_device *dev = wdev->netdev;
2334 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2335 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2336 uint8_t session_id;
2337 struct roam_ext_params roam_params;
2338 uint32_t cmd_type, req_id;
2339 struct nlattr *curr_attr;
2340 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2341 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2342 int rem, i;
2343 uint32_t buf_len = 0;
2344 int ret;
2345
Jeff Johnson1f61b612016-02-12 16:28:33 -08002346 ENTER_DEV(dev);
2347
Anurag Chouhan6d760662016-02-20 16:05:43 +05302348 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002349 hdd_err("Command not allowed in FTM mode");
2350 return -EPERM;
2351 }
2352
2353 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302354 if (ret)
2355 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002356
2357 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2358 data, data_len,
2359 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002360 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002361 return -EINVAL;
2362 }
2363 /* Parse and fetch Command Type*/
2364 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002365 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002366 goto fail;
2367 }
2368 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302369 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002370 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2371 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002372 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002373 goto fail;
2374 }
2375 req_id = nla_get_u32(
2376 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002377 hdd_debug("Req Id (%d)", req_id);
2378 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379 switch (cmd_type) {
2380 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2381 i = 0;
2382 nla_for_each_nested(curr_attr,
2383 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2384 rem) {
2385 if (nla_parse(tb2,
2386 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2387 nla_data(curr_attr), nla_len(curr_attr),
2388 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002389 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002390 goto fail;
2391 }
2392 /* Parse and Fetch allowed SSID list*/
2393 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002394 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002395 goto fail;
2396 }
2397 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2398 /*
2399 * Upper Layers include a null termination character.
2400 * Check for the actual permissible length of SSID and
2401 * also ensure not to copy the NULL termination
2402 * character to the driver buffer.
2403 */
2404 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2405 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2406 nla_memcpy(
2407 roam_params.ssid_allowed_list[i].ssId,
2408 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2409 buf_len - 1);
2410 roam_params.ssid_allowed_list[i].length =
2411 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002412 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002413 roam_params.ssid_allowed_list[i].length,
2414 roam_params.ssid_allowed_list[i].ssId,
2415 roam_params.ssid_allowed_list[i].length);
2416 i++;
2417 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002418 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002419 }
2420 }
2421 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002422 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002423 roam_params.num_ssid_allowed_list);
2424 sme_update_roam_params(pHddCtx->hHal, session_id,
2425 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2426 break;
2427 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2428 /* Parse and fetch 5G Boost Threshold */
2429 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002430 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002431 goto fail;
2432 }
2433 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2434 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002435 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002436 roam_params.raise_rssi_thresh_5g);
2437 /* Parse and fetch 5G Penalty Threshold */
2438 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002439 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440 goto fail;
2441 }
2442 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2443 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002444 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 roam_params.drop_rssi_thresh_5g);
2446 /* Parse and fetch 5G Boost Factor */
2447 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002448 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449 goto fail;
2450 }
2451 roam_params.raise_factor_5g = nla_get_u32(
2452 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002453 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 roam_params.raise_factor_5g);
2455 /* Parse and fetch 5G Penalty factor */
2456 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002457 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458 goto fail;
2459 }
2460 roam_params.drop_factor_5g = nla_get_u32(
2461 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002462 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 roam_params.drop_factor_5g);
2464 /* Parse and fetch 5G Max Boost */
2465 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002466 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002467 goto fail;
2468 }
2469 roam_params.max_raise_rssi_5g = nla_get_u32(
2470 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002471 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 roam_params.max_raise_rssi_5g);
2473 /* Parse and fetch Rssi Diff */
2474 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002475 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476 goto fail;
2477 }
2478 roam_params.rssi_diff = nla_get_s32(
2479 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002480 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002481 roam_params.rssi_diff);
2482 /* Parse and fetch Alert Rssi Threshold */
2483 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002484 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002485 goto fail;
2486 }
2487 roam_params.alert_rssi_threshold = nla_get_u32(
2488 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002489 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002490 roam_params.alert_rssi_threshold);
2491 sme_update_roam_params(pHddCtx->hHal, session_id,
2492 roam_params,
2493 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2494 break;
2495 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2496 /* Parse and fetch Activate Good Rssi Roam */
2497 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002498 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002499 goto fail;
2500 }
2501 roam_params.good_rssi_roam = nla_get_s32(
2502 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002503 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002504 roam_params.good_rssi_roam);
2505 sme_update_roam_params(pHddCtx->hHal, session_id,
2506 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2507 break;
2508 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2509 /* Parse and fetch number of preferred BSSID */
2510 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002511 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002512 goto fail;
2513 }
2514 roam_params.num_bssid_favored = nla_get_u32(
2515 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002516 hdd_debug("Num of Preferred BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002517 roam_params.num_bssid_favored);
2518 i = 0;
2519 nla_for_each_nested(curr_attr,
2520 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2521 rem) {
2522 if (nla_parse(tb2,
2523 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2524 nla_data(curr_attr), nla_len(curr_attr),
2525 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002526 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002527 goto fail;
2528 }
2529 /* Parse and fetch MAC address */
2530 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002531 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002532 goto fail;
2533 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002534 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002535 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302536 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002537 hdd_debug(MAC_ADDRESS_STR,
2538 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 /* Parse and fetch preference factor*/
2540 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002541 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 goto fail;
2543 }
2544 roam_params.bssid_favored_factor[i] = nla_get_u32(
2545 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002546 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 roam_params.bssid_favored_factor[i]);
2548 i++;
2549 }
2550 sme_update_roam_params(pHddCtx->hHal, session_id,
2551 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2552 break;
2553 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2554 /* Parse and fetch number of blacklist BSSID */
2555 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002556 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 goto fail;
2558 }
2559 roam_params.num_bssid_avoid_list = nla_get_u32(
2560 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002561 hdd_debug("Num of blacklist BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002562 roam_params.num_bssid_avoid_list);
2563 i = 0;
2564 nla_for_each_nested(curr_attr,
2565 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2566 rem) {
2567 if (nla_parse(tb2,
2568 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2569 nla_data(curr_attr), nla_len(curr_attr),
2570 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002571 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002572 goto fail;
2573 }
2574 /* Parse and fetch MAC address */
2575 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002576 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002577 goto fail;
2578 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002579 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002580 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302581 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002582 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002583 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002584 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002585 i++;
2586 }
2587 sme_update_roam_params(pHddCtx->hHal, session_id,
2588 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2589 break;
2590 }
2591 return 0;
2592fail:
2593 return -EINVAL;
2594}
2595
2596/**
2597 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2598 * @wiphy: pointer to wireless wiphy structure.
2599 * @wdev: pointer to wireless_dev structure.
2600 * @data: Pointer to the data to be passed via vendor interface
2601 * @data_len:Length of the data to be passed
2602 *
2603 * Return: Return the Success or Failure code.
2604 */
2605static int
2606wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2607 struct wireless_dev *wdev,
2608 const void *data,
2609 int data_len)
2610{
2611 int ret;
2612
2613 cds_ssr_protect(__func__);
2614 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2615 data, data_len);
2616 cds_ssr_unprotect(__func__);
2617
2618 return ret;
2619}
2620
2621static const struct nla_policy
2622wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2623 +1] = {
2624 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2625};
2626
2627/**
2628 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2629 * @hdd_ctx: HDD context
2630 * @device_mode: device mode
2631 * Return: bool
2632 */
2633static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002634 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002635{
2636 hdd_adapter_t *adapter;
2637 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2638 hdd_ap_ctx_t *ap_ctx;
2639 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302640 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002641
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302642 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002643 &adapter_node);
2644
2645 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302646 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002647 adapter = adapter_node->pAdapter;
2648
2649 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002650 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002651 ap_ctx =
2652 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2653
2654 /*
2655 * if there is SAP already running on DFS channel,
2656 * do not disable scan on dfs channels. Note that
2657 * with SAP on DFS, there cannot be conurrency on
2658 * single radio. But then we can have multiple
2659 * radios !!
2660 */
2661 if (CHANNEL_STATE_DFS ==
2662 cds_get_channel_state(
2663 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002664 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002665 return true;
2666 }
2667 }
2668
2669 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002670 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671 sta_ctx =
2672 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2673
2674 /*
2675 * if STA is already connected on DFS channel,
2676 * do not disable scan on dfs channels
2677 */
2678 if (hdd_conn_is_connected(sta_ctx) &&
2679 (CHANNEL_STATE_DFS ==
2680 cds_get_channel_state(
2681 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002682 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002683 return true;
2684 }
2685 }
2686
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302687 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002688 adapter_node,
2689 &next);
2690 adapter_node = next;
2691 }
2692
2693 return false;
2694}
2695
2696/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002697 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2698 * @hdd_ctx: HDD context within host driver
2699 * @adapter: Adapter pointer
2700 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2701 *
2702 * Loops through devices to see who is operating on DFS channels
2703 * and then disables/enables DFS channels by calling SME API.
2704 * Fails the disable request if any device is active on a DFS channel.
2705 *
2706 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002707 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002708
2709int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2710 hdd_adapter_t *adapter,
2711 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002712{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002713 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302714 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002715 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002716
2717 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2718 if (no_dfs_flag) {
2719 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002720 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002721
2722 if (true == status)
2723 return -EOPNOTSUPP;
2724
2725 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002726 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002727
2728 if (true == status)
2729 return -EOPNOTSUPP;
2730 }
2731
2732 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2733
2734 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2735
2736 /*
2737 * call the SME API to tunnel down the new channel list
2738 * to the firmware
2739 */
2740 status = sme_handle_dfs_chan_scan(
2741 h_hal, hdd_ctx->config->enableDFSChnlScan);
2742
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302743 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002744 ret_val = 0;
2745
2746 /*
2747 * Clear the SME scan cache also. Note that the
2748 * clearing of scan results is independent of session;
2749 * so no need to iterate over
2750 * all sessions
2751 */
2752 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302753 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002754 ret_val = -EPERM;
2755 }
2756
2757 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002758 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002759 ret_val = 0;
2760 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002761 return ret_val;
2762}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002763
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002764/**
2765 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2766 * @wiphy: corestack handler
2767 * @wdev: wireless device
2768 * @data: data
2769 * @data_len: data length
2770 * Return: success(0) or reason code for failure
2771 */
2772static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2773 struct wireless_dev *wdev,
2774 const void *data,
2775 int data_len)
2776{
2777 struct net_device *dev = wdev->netdev;
2778 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2779 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2780 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2781 int ret_val;
2782 uint32_t no_dfs_flag = 0;
2783
Jeff Johnson1f61b612016-02-12 16:28:33 -08002784 ENTER_DEV(dev);
2785
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002786 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302787 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002788 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002789
2790 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2791 data, data_len,
2792 wlan_hdd_set_no_dfs_flag_config_policy)) {
2793 hdd_err("invalid attr");
2794 return -EINVAL;
2795 }
2796
2797 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2798 hdd_err("attr dfs flag failed");
2799 return -EINVAL;
2800 }
2801
2802 no_dfs_flag = nla_get_u32(
2803 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2804
Jeff Johnson020db452016-06-29 14:37:26 -07002805 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002806
2807 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002808 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002809 return -EINVAL;
2810 }
2811
2812 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2813 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002814 return ret_val;
2815}
2816
2817/**
2818 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2819 *
2820 * @wiphy: wiphy device pointer
2821 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002822 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823 * @data_len: Buffer length
2824 *
2825 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2826 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2827 *
2828 * Return: EOK or other error codes.
2829 */
2830
2831static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2832 struct wireless_dev *wdev,
2833 const void *data,
2834 int data_len)
2835{
2836 int ret;
2837
2838 cds_ssr_protect(__func__);
2839 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2840 data, data_len);
2841 cds_ssr_unprotect(__func__);
2842
2843 return ret;
2844}
2845
Manikandan Mohan80dea792016-04-28 16:36:48 -07002846static const struct nla_policy
2847wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2848 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2849};
2850
2851/**
2852 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2853 * @wiphy: wiphy device pointer
2854 * @wdev: wireless device pointer
2855 * @data: Vendor command data buffer
2856 * @data_len: Buffer length
2857 *
2858 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2859 * setup WISA Mode features.
2860 *
2861 * Return: Success(0) or reason code for failure
2862 */
2863static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2864 struct wireless_dev *wdev, const void *data, int data_len)
2865{
2866 struct net_device *dev = wdev->netdev;
2867 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2868 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2869 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2870 struct sir_wisa_params wisa;
2871 int ret_val;
2872 QDF_STATUS status;
2873 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07002874 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2875 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002876
2877 ENTER_DEV(dev);
2878 ret_val = wlan_hdd_validate_context(hdd_ctx);
2879 if (ret_val)
2880 goto err;
2881
2882 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2883 hdd_err("Command not allowed in FTM mode");
2884 return -EPERM;
2885 }
2886
2887 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2888 wlan_hdd_wisa_cmd_policy)) {
2889 hdd_err("Invalid WISA cmd attributes");
2890 ret_val = -EINVAL;
2891 goto err;
2892 }
2893 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2894 hdd_err("Invalid WISA mode");
2895 ret_val = -EINVAL;
2896 goto err;
2897 }
2898
2899 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2900 hdd_info("WISA Mode: %d", wisa_mode);
2901 wisa.mode = wisa_mode;
2902 wisa.vdev_id = adapter->sessionId;
2903 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002904 if (!QDF_IS_STATUS_SUCCESS(status)) {
2905 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002906 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002907 }
2908 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07002909 cdp_set_wisa_mode(soc,
2910 cdp_get_vdev_from_vdev_id(soc, pdev,
2911 adapter->sessionId),
2912 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002913err:
2914 EXIT();
2915 return ret_val;
2916}
2917
2918/**
2919 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2920 * @wiphy: corestack handler
2921 * @wdev: wireless device
2922 * @data: data
2923 * @data_len: data length
2924 *
2925 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2926 * setup WISA mode features.
2927 *
2928 * Return: Success(0) or reason code for failure
2929 */
2930static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2931 struct wireless_dev *wdev,
2932 const void *data,
2933 int data_len)
2934{
2935 int ret;
2936
2937 cds_ssr_protect(__func__);
2938 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2939 cds_ssr_unprotect(__func__);
2940
2941 return ret;
2942}
2943
Anurag Chouhan96919482016-07-13 16:36:57 +05302944/*
2945 * define short names for the global vendor params
2946 * used by __wlan_hdd_cfg80211_get_station_cmd()
2947 */
2948#define STATION_INVALID \
2949 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2950#define STATION_INFO \
2951 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2952#define STATION_ASSOC_FAIL_REASON \
2953 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2954#define STATION_MAX \
2955 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2956
2957static const struct nla_policy
2958hdd_get_station_policy[STATION_MAX + 1] = {
2959 [STATION_INFO] = {.type = NLA_FLAG},
2960 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2961};
2962
2963/**
2964 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2965 * @hdd_ctx: HDD context within host driver
2966 * @wdev: wireless device
2967 *
2968 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
2969 * Validate cmd attributes and send the station info to upper layers.
2970 *
2971 * Return: Success(0) or reason code for failure
2972 */
2973static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
2974 hdd_adapter_t *adapter)
2975{
2976 struct sk_buff *skb = NULL;
2977 uint32_t nl_buf_len;
2978 hdd_station_ctx_t *hdd_sta_ctx;
2979
2980 nl_buf_len = NLMSG_HDRLEN;
2981 nl_buf_len += sizeof(uint32_t);
2982 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
2983
2984 if (!skb) {
2985 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
2986 return -ENOMEM;
2987 }
2988
2989 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2990
2991 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
2992 hdd_sta_ctx->conn_info.assoc_status_code)) {
2993 hdd_err("put fail");
2994 goto fail;
2995 }
2996 return cfg80211_vendor_cmd_reply(skb);
2997fail:
2998 if (skb)
2999 kfree_skb(skb);
3000 return -EINVAL;
3001}
3002
3003/**
3004 * hdd_map_auth_type() - transform auth type specific to
3005 * vendor command
3006 * @auth_type: csr auth type
3007 *
3008 * Return: Success(0) or reason code for failure
3009 */
3010static int hdd_convert_auth_type(uint32_t auth_type)
3011{
3012 uint32_t ret_val;
3013
3014 switch (auth_type) {
3015 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3016 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3017 break;
3018 case eCSR_AUTH_TYPE_SHARED_KEY:
3019 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3020 break;
3021 case eCSR_AUTH_TYPE_WPA:
3022 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3023 break;
3024 case eCSR_AUTH_TYPE_WPA_PSK:
3025 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3026 break;
3027 case eCSR_AUTH_TYPE_AUTOSWITCH:
3028 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3029 break;
3030 case eCSR_AUTH_TYPE_WPA_NONE:
3031 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3032 break;
3033 case eCSR_AUTH_TYPE_RSN:
3034 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3035 break;
3036 case eCSR_AUTH_TYPE_RSN_PSK:
3037 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3038 break;
3039 case eCSR_AUTH_TYPE_FT_RSN:
3040 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3041 break;
3042 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3043 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3044 break;
3045 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3046 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3047 break;
3048 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3049 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3050 break;
3051 case eCSR_AUTH_TYPE_CCKM_WPA:
3052 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3053 break;
3054 case eCSR_AUTH_TYPE_CCKM_RSN:
3055 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3056 break;
3057 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3058 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3059 break;
3060 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3061 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3062 break;
3063 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3064 case eCSR_AUTH_TYPE_FAILED:
3065 case eCSR_AUTH_TYPE_NONE:
3066 default:
3067 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3068 break;
3069 }
3070 return ret_val;
3071}
3072
3073/**
3074 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3075 * vendor command
3076 * @dot11mode: dot11mode
3077 *
3078 * Return: Success(0) or reason code for failure
3079 */
3080static int hdd_convert_dot11mode(uint32_t dot11mode)
3081{
3082 uint32_t ret_val;
3083
3084 switch (dot11mode) {
3085 case eCSR_CFG_DOT11_MODE_11A:
3086 ret_val = QCA_WLAN_802_11_MODE_11A;
3087 break;
3088 case eCSR_CFG_DOT11_MODE_11B:
3089 ret_val = QCA_WLAN_802_11_MODE_11B;
3090 break;
3091 case eCSR_CFG_DOT11_MODE_11G:
3092 ret_val = QCA_WLAN_802_11_MODE_11G;
3093 break;
3094 case eCSR_CFG_DOT11_MODE_11N:
3095 ret_val = QCA_WLAN_802_11_MODE_11N;
3096 break;
3097 case eCSR_CFG_DOT11_MODE_11AC:
3098 ret_val = QCA_WLAN_802_11_MODE_11AC;
3099 break;
3100 case eCSR_CFG_DOT11_MODE_AUTO:
3101 case eCSR_CFG_DOT11_MODE_ABG:
3102 default:
3103 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3104 }
3105 return ret_val;
3106}
3107
3108/**
3109 * hdd_add_tx_bitrate() - add tx bitrate attribute
3110 * @skb: pointer to sk buff
3111 * @hdd_sta_ctx: pointer to hdd station context
3112 * @idx: attribute index
3113 *
3114 * Return: Success(0) or reason code for failure
3115 */
3116static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3117 hdd_station_ctx_t *hdd_sta_ctx,
3118 int idx)
3119{
3120 struct nlattr *nla_attr;
3121 uint32_t bitrate, bitrate_compat;
3122
3123 nla_attr = nla_nest_start(skb, idx);
3124 if (!nla_attr)
3125 goto fail;
3126 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3127 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3128
3129 /* report 16-bit bitrate only if we can */
3130 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3131 if (bitrate > 0 &&
3132 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3133 hdd_err("put fail");
3134 goto fail;
3135 }
3136 if (bitrate_compat > 0 &&
3137 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3138 hdd_err("put fail");
3139 goto fail;
3140 }
3141 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3142 hdd_sta_ctx->conn_info.txrate.nss)) {
3143 hdd_err("put fail");
3144 goto fail;
3145 }
3146 nla_nest_end(skb, nla_attr);
3147 return 0;
3148fail:
3149 return -EINVAL;
3150}
3151
3152/**
3153 * hdd_add_sta_info() - add station info attribute
3154 * @skb: pointer to sk buff
3155 * @hdd_sta_ctx: pointer to hdd station context
3156 * @idx: attribute index
3157 *
3158 * Return: Success(0) or reason code for failure
3159 */
3160static int32_t hdd_add_sta_info(struct sk_buff *skb,
3161 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3162{
3163 struct nlattr *nla_attr;
3164
3165 nla_attr = nla_nest_start(skb, idx);
3166 if (!nla_attr)
3167 goto fail;
3168 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3169 (hdd_sta_ctx->conn_info.signal + 100))) {
3170 hdd_err("put fail");
3171 goto fail;
3172 }
3173 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3174 goto fail;
3175 nla_nest_end(skb, nla_attr);
3176 return 0;
3177fail:
3178 return -EINVAL;
3179}
3180
3181/**
3182 * hdd_add_survey_info() - add survey info attribute
3183 * @skb: pointer to sk buff
3184 * @hdd_sta_ctx: pointer to hdd station context
3185 * @idx: attribute index
3186 *
3187 * Return: Success(0) or reason code for failure
3188 */
3189static int32_t hdd_add_survey_info(struct sk_buff *skb,
3190 hdd_station_ctx_t *hdd_sta_ctx,
3191 int idx)
3192{
3193 struct nlattr *nla_attr;
3194
3195 nla_attr = nla_nest_start(skb, idx);
3196 if (!nla_attr)
3197 goto fail;
3198 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3199 hdd_sta_ctx->conn_info.freq) ||
3200 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3201 (hdd_sta_ctx->conn_info.noise + 100))) {
3202 hdd_err("put fail");
3203 goto fail;
3204 }
3205 nla_nest_end(skb, nla_attr);
3206 return 0;
3207fail:
3208 return -EINVAL;
3209}
3210
3211/**
3212 * hdd_add_link_standard_info() - add link info attribute
3213 * @skb: pointer to sk buff
3214 * @hdd_sta_ctx: pointer to hdd station context
3215 * @idx: attribute index
3216 *
3217 * Return: Success(0) or reason code for failure
3218 */
3219static int32_t
3220hdd_add_link_standard_info(struct sk_buff *skb,
3221 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3222{
3223 struct nlattr *nla_attr;
3224
3225 nla_attr = nla_nest_start(skb, idx);
3226 if (!nla_attr)
3227 goto fail;
3228 if (nla_put(skb,
3229 NL80211_ATTR_SSID,
3230 hdd_sta_ctx->conn_info.SSID.SSID.length,
3231 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3232 hdd_err("put fail");
3233 goto fail;
3234 }
3235 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3236 goto fail;
3237 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3238 goto fail;
3239 nla_nest_end(skb, nla_attr);
3240 return 0;
3241fail:
3242 return -EINVAL;
3243}
3244
3245/**
3246 * hdd_add_ap_standard_info() - add ap info attribute
3247 * @skb: pointer to sk buff
3248 * @hdd_sta_ctx: pointer to hdd station context
3249 * @idx: attribute index
3250 *
3251 * Return: Success(0) or reason code for failure
3252 */
3253static int32_t
3254hdd_add_ap_standard_info(struct sk_buff *skb,
3255 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3256{
3257 struct nlattr *nla_attr;
3258
3259 nla_attr = nla_nest_start(skb, idx);
3260 if (!nla_attr)
3261 goto fail;
3262 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3263 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3264 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3265 &hdd_sta_ctx->conn_info.vht_caps)) {
3266 hdd_err("put fail");
3267 goto fail;
3268 }
3269 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3270 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3271 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3272 &hdd_sta_ctx->conn_info.ht_caps)) {
3273 hdd_err("put fail");
3274 goto fail;
3275 }
3276 nla_nest_end(skb, nla_attr);
3277 return 0;
3278fail:
3279 return -EINVAL;
3280}
3281
3282/**
3283 * hdd_get_station_info() - send BSS information to supplicant
3284 * @hdd_ctx: pointer to hdd context
3285 * @adapter: pointer to adapter
3286 *
3287 * Return: 0 if success else error status
3288 */
3289static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3290 hdd_adapter_t *adapter)
3291{
3292 struct sk_buff *skb = NULL;
3293 uint8_t *tmp_hs20 = NULL;
3294 uint32_t nl_buf_len;
3295 hdd_station_ctx_t *hdd_sta_ctx;
3296
3297 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3298
3299 nl_buf_len = NLMSG_HDRLEN;
3300 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3301 sizeof(hdd_sta_ctx->conn_info.freq) +
3302 sizeof(hdd_sta_ctx->conn_info.noise) +
3303 sizeof(hdd_sta_ctx->conn_info.signal) +
3304 (sizeof(uint32_t) * 2) +
3305 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3306 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3307 sizeof(hdd_sta_ctx->conn_info.authType) +
3308 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3309 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3310 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3311 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3312 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3313 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3314 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3315 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3316 1);
3317 }
3318 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3319 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3320 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3321 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3322
3323
3324 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3325 if (!skb) {
3326 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3327 return -ENOMEM;
3328 }
3329
3330 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3331 LINK_INFO_STANDARD_NL80211_ATTR)) {
3332 hdd_err("put fail");
3333 goto fail;
3334 }
3335 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3336 AP_INFO_STANDARD_NL80211_ATTR)) {
3337 hdd_err("put fail");
3338 goto fail;
3339 }
3340 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3341 hdd_sta_ctx->conn_info.roam_count) ||
3342 nla_put_u32(skb, INFO_AKM,
3343 hdd_convert_auth_type(
3344 hdd_sta_ctx->conn_info.authType)) ||
3345 nla_put_u32(skb, WLAN802_11_MODE,
3346 hdd_convert_dot11mode(
3347 hdd_sta_ctx->conn_info.dot11Mode))) {
3348 hdd_err("put fail");
3349 goto fail;
3350 }
3351 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3352 if (nla_put(skb, HT_OPERATION,
3353 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3354 &hdd_sta_ctx->conn_info.ht_operation)) {
3355 hdd_err("put fail");
3356 goto fail;
3357 }
3358 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3359 if (nla_put(skb, VHT_OPERATION,
3360 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3361 &hdd_sta_ctx->conn_info.vht_operation)) {
3362 hdd_err("put fail");
3363 goto fail;
3364 }
3365 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3366 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3367 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3368 tmp_hs20 + 1)) {
3369 hdd_err("put fail");
3370 goto fail;
3371 }
3372
3373 return cfg80211_vendor_cmd_reply(skb);
3374fail:
3375 if (skb)
3376 kfree_skb(skb);
3377 return -EINVAL;
3378}
3379
3380/**
3381 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3382 * @wiphy: corestack handler
3383 * @wdev: wireless device
3384 * @data: data
3385 * @data_len: data length
3386 *
3387 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3388 * Validate cmd attributes and send the station info to upper layers.
3389 *
3390 * Return: Success(0) or reason code for failure
3391 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303392static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303393__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3394 struct wireless_dev *wdev,
3395 const void *data,
3396 int data_len)
3397{
3398 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3399 struct net_device *dev = wdev->netdev;
3400 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3401 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3402 int32_t status;
3403
3404 ENTER_DEV(dev);
3405 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3406 hdd_err("Command not allowed in FTM mode");
3407 status = -EPERM;
3408 goto out;
3409 }
3410
3411 status = wlan_hdd_validate_context(hdd_ctx);
3412 if (0 != status)
3413 goto out;
3414
3415
3416 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3417 data, data_len, NULL);
3418 if (status) {
3419 hdd_err("Invalid ATTR");
3420 goto out;
3421 }
3422
3423 /* Parse and fetch Command Type*/
3424 if (tb[STATION_INFO]) {
3425 status = hdd_get_station_info(hdd_ctx, adapter);
3426 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3427 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3428 } else {
3429 hdd_err("get station info cmd type failed");
3430 status = -EINVAL;
3431 goto out;
3432 }
3433 EXIT();
3434out:
3435 return status;
3436}
3437
3438/**
3439 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3440 * @wiphy: corestack handler
3441 * @wdev: wireless device
3442 * @data: data
3443 * @data_len: data length
3444 *
3445 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3446 * Validate cmd attributes and send the station info to upper layers.
3447 *
3448 * Return: Success(0) or reason code for failure
3449 */
3450static int32_t
3451hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3452 struct wireless_dev *wdev,
3453 const void *data,
3454 int data_len)
3455{
3456 int ret;
3457
3458 cds_ssr_protect(__func__);
3459 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3460 cds_ssr_unprotect(__func__);
3461
3462 return ret;
3463}
3464
3465/*
3466 * undef short names defined for get station command
3467 * used by __wlan_hdd_cfg80211_get_station_cmd()
3468 */
3469#undef STATION_INVALID
3470#undef STATION_INFO
3471#undef STATION_ASSOC_FAIL_REASON
3472#undef STATION_MAX
3473
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003474#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3475/**
3476 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3477 * @wiphy: pointer to wireless wiphy structure.
3478 * @wdev: pointer to wireless_dev structure.
3479 * @data: Pointer to the Key data
3480 * @data_len:Length of the data passed
3481 *
3482 * This is called when wlan driver needs to save the keys received via
3483 * vendor specific command.
3484 *
3485 * Return: Return the Success or Failure code.
3486 */
3487static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3488 struct wireless_dev *wdev,
3489 const void *data, int data_len)
3490{
3491 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3492 struct net_device *dev = wdev->netdev;
3493 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3494 hdd_context_t *hdd_ctx_ptr;
3495 int status;
3496
Jeff Johnson1f61b612016-02-12 16:28:33 -08003497 ENTER_DEV(dev);
3498
Anurag Chouhan6d760662016-02-20 16:05:43 +05303499 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003500 hdd_err("Command not allowed in FTM mode");
3501 return -EPERM;
3502 }
3503
3504 if ((data == NULL) || (data_len == 0) ||
3505 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003506 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003507 return -EINVAL;
3508 }
3509
3510 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3511 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003512 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003513 return -EINVAL;
3514 }
3515
3516 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303517 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003518 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003519 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3520 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003521 true,
3522 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303523 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3524 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003525 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3526 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3527 return 0;
3528}
3529
3530/**
3531 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3532 * @wiphy: pointer to wireless wiphy structure.
3533 * @wdev: pointer to wireless_dev structure.
3534 * @data: Pointer to the Key data
3535 * @data_len:Length of the data passed
3536 *
3537 * This is called when wlan driver needs to save the keys received via
3538 * vendor specific command.
3539 *
3540 * Return: Return the Success or Failure code.
3541 */
3542static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3543 struct wireless_dev *wdev,
3544 const void *data, int data_len)
3545{
3546 int ret;
3547
3548 cds_ssr_protect(__func__);
3549 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3550 cds_ssr_unprotect(__func__);
3551
3552 return ret;
3553}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003554#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003555
3556static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3557 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3558 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3559 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003560 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561};
3562
3563/**
3564 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3565 * @wiphy: pointer to wireless wiphy structure.
3566 * @wdev: pointer to wireless_dev structure.
3567 * @data: Pointer to the data to be passed via vendor interface
3568 * @data_len:Length of the data to be passed
3569 *
3570 * This is called when wlan driver needs to send wifi driver related info
3571 * (driver/fw version) to the user space application upon request.
3572 *
3573 * Return: Return the Success or Failure code.
3574 */
3575static int
3576__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3577 struct wireless_dev *wdev,
3578 const void *data, int data_len)
3579{
3580 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3581 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003582 tSirVersionString driver_version;
3583 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003584 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003586 struct sk_buff *reply_skb;
3587 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003588
Jeff Johnson1f61b612016-02-12 16:28:33 -08003589 ENTER_DEV(wdev->netdev);
3590
Anurag Chouhan6d760662016-02-20 16:05:43 +05303591 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003592 hdd_err("Command not allowed in FTM mode");
3593 return -EPERM;
3594 }
3595
3596 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303597 if (status)
3598 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003599
3600 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3601 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003602 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003603 return -EINVAL;
3604 }
3605
3606 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003607 hdd_err("Rcvd req for Driver version");
3608 strlcpy(driver_version, QWLAN_VERSIONSTR,
3609 sizeof(driver_version));
3610 skb_len += strlen(driver_version) + 1;
3611 count++;
3612 }
3613
3614 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3615 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003616 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3617 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003618 snprintf(firmware_version, sizeof(firmware_version),
3619 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3620 skb_len += strlen(firmware_version) + 1;
3621 count++;
3622 }
3623
3624 if (count == 0) {
3625 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003626 return -EINVAL;
3627 }
3628
Ryan Hsu7ac88852016-04-28 10:20:34 -07003629 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3630 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3631
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003632 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003633 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003634 return -ENOMEM;
3635 }
3636
Ryan Hsu7ac88852016-04-28 10:20:34 -07003637 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3638 if (nla_put_string(reply_skb,
3639 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3640 driver_version))
3641 goto error_nla_fail;
3642 }
3643
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05303644 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003645 if (nla_put_string(reply_skb,
3646 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3647 firmware_version))
3648 goto error_nla_fail;
3649 }
3650
3651 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3652 if (nla_put_u32(reply_skb,
3653 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3654 hdd_ctx->radio_index))
3655 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003656 }
3657
3658 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003659
3660error_nla_fail:
3661 hdd_err("nla put fail");
3662 kfree_skb(reply_skb);
3663 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003664}
3665
3666/**
3667 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3668 * @wiphy: pointer to wireless wiphy structure.
3669 * @wdev: pointer to wireless_dev structure.
3670 * @data: Pointer to the data to be passed via vendor interface
3671 * @data_len:Length of the data to be passed
3672 *
3673 * This is called when wlan driver needs to send wifi driver related info
3674 * (driver/fw version) to the user space application upon request.
3675 *
3676 * Return: Return the Success or Failure code.
3677 */
3678static int
3679wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3680 struct wireless_dev *wdev,
3681 const void *data, int data_len)
3682{
3683 int ret;
3684
3685 cds_ssr_protect(__func__);
3686 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3687 cds_ssr_unprotect(__func__);
3688
3689 return ret;
3690}
3691
3692/**
3693 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3694 * @wiphy: pointer to wireless wiphy structure.
3695 * @wdev: pointer to wireless_dev structure.
3696 * @data: Pointer to the data to be passed via vendor interface
3697 * @data_len:Length of the data to be passed
3698 *
3699 * This is called by userspace to know the supported logger features
3700 *
3701 * Return: Return the Success or Failure code.
3702 */
3703static int
3704__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3705 struct wireless_dev *wdev,
3706 const void *data, int data_len)
3707{
3708 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3709 int status;
3710 uint32_t features;
3711 struct sk_buff *reply_skb = NULL;
3712
Jeff Johnson1f61b612016-02-12 16:28:33 -08003713 ENTER_DEV(wdev->netdev);
3714
Anurag Chouhan6d760662016-02-20 16:05:43 +05303715 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003716 hdd_err("Command not allowed in FTM mode");
3717 return -EPERM;
3718 }
3719
3720 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303721 if (status)
3722 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003723
3724 features = 0;
3725
3726 if (hdd_is_memdump_supported())
3727 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3728 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3729 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3730 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3731
3732 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3733 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3734 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003735 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003736 return -ENOMEM;
3737 }
3738
Jeff Johnson020db452016-06-29 14:37:26 -07003739 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003740 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3741 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003742 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003743 kfree_skb(reply_skb);
3744 return -EINVAL;
3745 }
3746
3747 return cfg80211_vendor_cmd_reply(reply_skb);
3748}
3749
3750/**
3751 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3752 * @wiphy: pointer to wireless wiphy structure.
3753 * @wdev: pointer to wireless_dev structure.
3754 * @data: Pointer to the data to be passed via vendor interface
3755 * @data_len:Length of the data to be passed
3756 *
3757 * This is called by userspace to know the supported logger features
3758 *
3759 * Return: Return the Success or Failure code.
3760 */
3761static int
3762wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3763 struct wireless_dev *wdev,
3764 const void *data, int data_len)
3765{
3766 int ret;
3767
3768 cds_ssr_protect(__func__);
3769 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3770 data, data_len);
3771 cds_ssr_unprotect(__func__);
3772
3773 return ret;
3774}
3775
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003776#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003777/**
3778 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3779 * @hdd_ctx_ptr: pointer to HDD Context.
3780 * @bssid: pointer to bssid of roamed AP.
3781 * @req_rsn_ie: Pointer to request RSN IE
3782 * @req_rsn_len: Length of the request RSN IE
3783 * @rsp_rsn_ie: Pointer to response RSN IE
3784 * @rsp_rsn_len: Length of the response RSN IE
3785 * @roam_info_ptr: Pointer to the roaming related information
3786 *
3787 * This is called when wlan driver needs to send the roaming and
3788 * authorization information after roaming.
3789 *
3790 * The information that would be sent is the request RSN IE, response
3791 * RSN IE and BSSID of the newly roamed AP.
3792 *
3793 * If the Authorized status is authenticated, then additional parameters
3794 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3795 * supplicant.
3796 *
3797 * The supplicant upon receiving this event would ignore the legacy
3798 * cfg80211_roamed call and use the entire information from this event.
3799 * The cfg80211_roamed should still co-exist since the kernel will
3800 * make use of the parameters even if the supplicant ignores it.
3801 *
3802 * Return: Return the Success or Failure code.
3803 */
3804int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3805 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3806 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3807{
3808 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003809 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003810 ENTER();
3811
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303812 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003813 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003814
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003815 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003816 !roam_info_ptr->roamSynchInProgress)
3817 return 0;
3818
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003819 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3820 NULL,
3821 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3822 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3823 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003824 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003825 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3826 GFP_KERNEL);
3827
3828 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003829 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003830 return -EINVAL;
3831 }
3832
3833 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3834 ETH_ALEN, bssid) ||
3835 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3836 req_rsn_len, req_rsn_ie) ||
3837 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3838 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003839 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003840 goto nla_put_failure;
3841 }
Jeff Johnson020db452016-06-29 14:37:26 -07003842 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003843 if (roam_info_ptr->synchAuthStatus ==
3844 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003845 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003846 if (nla_put_u8(skb,
3847 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3848 hdd_err("nla put fail");
3849 goto nla_put_failure;
3850 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003851 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3852 /* if FT or CCKM connection: dont send replay counter */
3853 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3854 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3855 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3856 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3857 nla_put(skb,
3858 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3859 SIR_REPLAY_CTR_LEN,
3860 roam_info_ptr->replay_ctr)) {
3861 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003862 hdd_err("failed to send replay counter.");
3863 goto nla_put_failure;
3864 }
3865 if (nla_put(skb,
3866 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3867 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3868 nla_put(skb,
3869 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3870 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3871 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003872 goto nla_put_failure;
3873 }
3874 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003875 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003876 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3877 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003878 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003879 goto nla_put_failure;
3880 }
3881 }
3882
Jeff Johnson020db452016-06-29 14:37:26 -07003883 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003884 roam_info_ptr->subnet_change_status);
3885
3886 /*
3887 * Add subnet change status if subnet has changed
3888 * 0 = unchanged
3889 * 1 = changed
3890 * 2 = unknown
3891 */
3892 if (roam_info_ptr->subnet_change_status) {
3893 if (nla_put_u8(skb,
3894 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3895 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003896 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003897 goto nla_put_failure;
3898 }
3899 }
3900
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003901 cfg80211_vendor_event(skb, GFP_KERNEL);
3902 return 0;
3903
3904nla_put_failure:
3905 kfree_skb(skb);
3906 return -EINVAL;
3907}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003908#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909
3910static const struct nla_policy
3911wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3912
3913 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3914 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3915 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303916 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303917 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3918 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003919 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
3920 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
3921 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
3922 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
3923 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05303924 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003925};
3926
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003927/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303928 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3929 *
3930 * @adapter: Pointer to HDD adapter
3931 * @ie_data: Pointer to Scan IEs buffer
3932 * @ie_len: Length of Scan IEs
3933 *
3934 * Return: 0 on success; error number otherwise
3935 */
3936static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3937 uint8_t *ie_data, uint8_t ie_len)
3938{
3939 hdd_scaninfo_t *scan_info = NULL;
3940 scan_info = &adapter->scan_info;
3941
3942 if (scan_info->default_scan_ies) {
3943 qdf_mem_free(scan_info->default_scan_ies);
3944 scan_info->default_scan_ies = NULL;
3945 }
3946
3947 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3948 if (!scan_info->default_scan_ies)
3949 return -ENOMEM;
3950
3951 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3952 scan_info->default_scan_ies_len = ie_len;
3953 return 0;
3954}
3955
3956/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003957 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3958 * vendor command
3959 *
3960 * @wiphy: wiphy device pointer
3961 * @wdev: wireless device pointer
3962 * @data: Vendor command data buffer
3963 * @data_len: Buffer length
3964 *
3965 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3966 *
3967 * Return: Error code.
3968 */
3969static int
3970__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3971 struct wireless_dev *wdev,
3972 const void *data,
3973 int data_len)
3974{
3975 struct net_device *dev = wdev->netdev;
3976 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3977 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3978 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3979 int ret_val = 0;
3980 u32 modulated_dtim;
3981 u16 stats_avg_factor;
3982 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303983 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003984 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07003985 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303986 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303987 int attr_len;
3988 int access_policy = 0;
3989 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3990 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303991 uint16_t scan_ie_len = 0;
3992 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303993 struct sir_set_tx_rx_aggregation_size request;
3994 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003995 uint8_t retry, delay;
3996 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05303997 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303998
Jeff Johnson1f61b612016-02-12 16:28:33 -08003999 ENTER_DEV(dev);
4000
Anurag Chouhan6d760662016-02-20 16:05:43 +05304001 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004002 hdd_err("Command not allowed in FTM mode");
4003 return -EPERM;
4004 }
4005
4006 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304007 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004008 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004009
4010 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4011 data, data_len,
4012 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004013 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004014 return -EINVAL;
4015 }
4016
Krunal Sonie3531942016-04-12 17:43:53 -07004017 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4018 ftm_capab = nla_get_u32(tb[
4019 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4020 hdd_ctx->config->fine_time_meas_cap =
4021 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4022 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304023 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004024 hdd_ctx->config->fine_time_meas_cap);
4025 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4026 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4027 hdd_ctx->config->fine_time_meas_cap);
4028 }
4029
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004030 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4031 modulated_dtim = nla_get_u32(
4032 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4033
4034 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4035 adapter->sessionId,
4036 modulated_dtim);
4037
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304038 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004039 ret_val = -EPERM;
4040 }
4041
Kapil Gupta6213c012016-09-02 19:39:09 +05304042 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4043 qpower = nla_get_u8(
4044 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4045 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4046 ret_val = -EINVAL;
4047 }
4048
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004049 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4050 stats_avg_factor = nla_get_u16(
4051 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4052 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4053 adapter->sessionId,
4054 stats_avg_factor);
4055
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304056 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004057 ret_val = -EPERM;
4058 }
4059
4060
4061 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4062 guard_time = nla_get_u32(
4063 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4064 status = sme_configure_guard_time(hdd_ctx->hHal,
4065 adapter->sessionId,
4066 guard_time);
4067
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304068 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004069 ret_val = -EPERM;
4070 }
4071
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304072 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4073 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4074 attr_len = nla_len(
4075 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4076 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4077 hdd_info("Invalid value. attr_len %d",
4078 attr_len);
4079 return -EINVAL;
4080 }
4081
4082 nla_memcpy(&vendor_ie,
4083 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4084 attr_len);
4085 vendor_ie_present = true;
4086 hdd_info("Access policy vendor ie present.attr_len %d",
4087 attr_len);
4088 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4089 &vendor_ie[0], attr_len);
4090 }
4091
4092 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4093 access_policy = (int) nla_get_u32(
4094 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4095 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4096 (access_policy >
4097 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4098 hdd_info("Invalid value. access_policy %d",
4099 access_policy);
4100 return -EINVAL;
4101 }
4102 access_policy_present = true;
4103 hdd_info("Access policy present. access_policy %d",
4104 access_policy);
4105 }
4106
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004107 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4108 retry = nla_get_u8(tb[
4109 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4110 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4111 CFG_NON_AGG_RETRY_MAX : retry;
4112 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4113 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4114 retry, PDEV_CMD);
4115 }
4116
4117 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4118 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4119 retry = retry > CFG_AGG_RETRY_MAX ?
4120 CFG_AGG_RETRY_MAX : retry;
4121
4122 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4123 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4124 CFG_AGG_RETRY_MIN : retry;
4125 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4126 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4127 retry, PDEV_CMD);
4128 }
4129
4130 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4131 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4132 retry = retry > CFG_MGMT_RETRY_MAX ?
4133 CFG_MGMT_RETRY_MAX : retry;
4134 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4135 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4136 retry, PDEV_CMD);
4137 }
4138
4139 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4140 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4141 retry = retry > CFG_CTRL_RETRY_MAX ?
4142 CFG_CTRL_RETRY_MAX : retry;
4143 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4144 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4145 retry, PDEV_CMD);
4146 }
4147
4148 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4149 delay = nla_get_u8(tb[
4150 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4151 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4152 CFG_PROPAGATION_DELAY_MAX : delay;
4153 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4154 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4155 delay, PDEV_CMD);
4156 }
4157
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304158 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4159 tx_fail_count = nla_get_u32(
4160 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4161 if (tx_fail_count) {
4162 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4163 adapter->sessionId, tx_fail_count);
4164 if (QDF_STATUS_SUCCESS != status) {
4165 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4166 status);
4167 return -EINVAL;
4168 }
4169 }
4170 }
4171
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304172 if (vendor_ie_present && access_policy_present) {
4173 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4174 access_policy =
4175 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304176 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304177 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304178 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304179
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304180 hdd_info("calling sme_update_access_policy_vendor_ie");
4181 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4182 adapter->sessionId, &vendor_ie[0],
4183 access_policy);
4184 if (QDF_STATUS_SUCCESS != status) {
4185 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304186 return -EINVAL;
4187 }
4188 }
4189
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304190 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4191 set_value = nla_get_u8(
4192 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4193 hdd_info("set_value: %d", set_value);
4194 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4195 }
4196
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304197 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4198 scan_ie_len = nla_len(
4199 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4200 hdd_info("Received default scan IE of len %d session %d device mode %d",
4201 scan_ie_len, adapter->sessionId,
4202 adapter->device_mode);
4203 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4204 scan_ie = (uint8_t *) nla_data(tb
4205 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304206
4207 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4208 scan_ie_len))
4209 hdd_err("Failed to save default scan IEs");
4210
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304211 if (adapter->device_mode == QDF_STA_MODE) {
4212 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4213 adapter->sessionId, scan_ie,
4214 scan_ie_len);
4215 if (QDF_STATUS_SUCCESS != status)
4216 ret_val = -EPERM;
4217 }
4218 } else
4219 ret_val = -EPERM;
4220 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304221
4222 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4223 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4224 /* if one is specified, both must be specified */
4225 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4226 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4227 hdd_err("Both TX and RX MPDU Aggregation required");
4228 return -EINVAL;
4229 }
4230
4231 request.tx_aggregation_size = nla_get_u8(
4232 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4233 request.rx_aggregation_size = nla_get_u8(
4234 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4235 request.vdev_id = adapter->sessionId;
4236
4237 if (request.tx_aggregation_size >=
4238 CFG_TX_AGGREGATION_SIZE_MIN &&
4239 request.tx_aggregation_size <=
4240 CFG_TX_AGGREGATION_SIZE_MAX &&
4241 request.rx_aggregation_size >=
4242 CFG_RX_AGGREGATION_SIZE_MIN &&
4243 request.rx_aggregation_size <=
4244 CFG_RX_AGGREGATION_SIZE_MAX) {
4245 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4246 if (qdf_status != QDF_STATUS_SUCCESS) {
4247 hdd_err("failed to set aggr sizes err %d",
4248 qdf_status);
4249 ret_val = -EPERM;
4250 }
4251 } else {
4252 hdd_err("TX %d RX %d MPDU aggr size not in range",
4253 request.tx_aggregation_size,
4254 request.rx_aggregation_size);
4255 ret_val = -EINVAL;
4256 }
4257 }
4258
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304259 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4260 uint8_t ignore_assoc_disallowed;
4261
4262 ignore_assoc_disallowed
4263 = nla_get_u8(tb[
4264 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4265 hdd_info("Set ignore_assoc_disallowed value - %d",
4266 ignore_assoc_disallowed);
4267 if ((ignore_assoc_disallowed <
4268 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4269 (ignore_assoc_disallowed >
4270 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4271 return -EPERM;
4272
4273 sme_update_session_param(hdd_ctx->hHal,
4274 adapter->sessionId,
4275 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4276 ignore_assoc_disallowed);
4277 }
4278
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 return ret_val;
4280}
4281
4282/**
4283 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4284 * vendor command
4285 *
4286 * @wiphy: wiphy device pointer
4287 * @wdev: wireless device pointer
4288 * @data: Vendor command data buffer
4289 * @data_len: Buffer length
4290 *
4291 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4292 *
4293 * Return: EOK or other error codes.
4294 */
4295static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4296 struct wireless_dev *wdev,
4297 const void *data,
4298 int data_len)
4299{
4300 int ret;
4301
4302 cds_ssr_protect(__func__);
4303 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4304 data, data_len);
4305 cds_ssr_unprotect(__func__);
4306
4307 return ret;
4308}
4309
4310static const struct
4311nla_policy
4312qca_wlan_vendor_wifi_logger_start_policy
4313[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4314 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4315 = {.type = NLA_U32 },
4316 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4317 = {.type = NLA_U32 },
4318 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4319 = {.type = NLA_U32 },
4320};
4321
4322/**
4323 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4324 * or disable the collection of packet statistics from the firmware
4325 * @wiphy: WIPHY structure pointer
4326 * @wdev: Wireless device structure pointer
4327 * @data: Pointer to the data received
4328 * @data_len: Length of the data received
4329 *
4330 * This function enables or disables the collection of packet statistics from
4331 * the firmware
4332 *
4333 * Return: 0 on success and errno on failure
4334 */
4335static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4336 struct wireless_dev *wdev,
4337 const void *data,
4338 int data_len)
4339{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304340 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004341 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4342 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4343 struct sir_wifi_start_log start_log;
4344
Jeff Johnson1f61b612016-02-12 16:28:33 -08004345 ENTER_DEV(wdev->netdev);
4346
Anurag Chouhan6d760662016-02-20 16:05:43 +05304347 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004348 hdd_err("Command not allowed in FTM mode");
4349 return -EPERM;
4350 }
4351
4352 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304353 if (status)
4354 return status;
4355
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004356
4357 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4358 data, data_len,
4359 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004360 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004361 return -EINVAL;
4362 }
4363
4364 /* Parse and fetch ring id */
4365 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004366 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004367 return -EINVAL;
4368 }
4369 start_log.ring_id = nla_get_u32(
4370 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004371 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004372
4373 /* Parse and fetch verbose level */
4374 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004375 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004376 return -EINVAL;
4377 }
4378 start_log.verbose_level = nla_get_u32(
4379 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004380 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004381
4382 /* Parse and fetch flag */
4383 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004384 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004385 return -EINVAL;
4386 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304387 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304389 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004390
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304391 /* size is buff size which can be set using iwpriv command*/
4392 start_log.size = 0;
4393
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004394 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4395
4396 if (start_log.ring_id == RING_ID_WAKELOCK) {
4397 /* Start/stop wakelock events */
4398 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4399 cds_set_wakelock_logging(true);
4400 else
4401 cds_set_wakelock_logging(false);
4402 return 0;
4403 }
4404
4405 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304406 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004407 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004408 status);
4409 return -EINVAL;
4410 }
4411 return 0;
4412}
4413
4414/**
4415 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4416 * or disable the collection of packet statistics from the firmware
4417 * @wiphy: WIPHY structure pointer
4418 * @wdev: Wireless device structure pointer
4419 * @data: Pointer to the data received
4420 * @data_len: Length of the data received
4421 *
4422 * This function is used to enable or disable the collection of packet
4423 * statistics from the firmware
4424 *
4425 * Return: 0 on success and errno on failure
4426 */
4427static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4428 struct wireless_dev *wdev,
4429 const void *data,
4430 int data_len)
4431{
4432 int ret = 0;
4433
4434 cds_ssr_protect(__func__);
4435 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4436 wdev, data, data_len);
4437 cds_ssr_unprotect(__func__);
4438
4439 return ret;
4440}
4441
4442static const struct
4443nla_policy
4444qca_wlan_vendor_wifi_logger_get_ring_data_policy
4445[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4446 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4447 = {.type = NLA_U32 },
4448};
4449
4450/**
4451 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4452 * @wiphy: WIPHY structure pointer
4453 * @wdev: Wireless device structure pointer
4454 * @data: Pointer to the data received
4455 * @data_len: Length of the data received
4456 *
4457 * This function is used to flush or retrieve the per packet statistics from
4458 * the driver
4459 *
4460 * Return: 0 on success and errno on failure
4461 */
4462static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4463 struct wireless_dev *wdev,
4464 const void *data,
4465 int data_len)
4466{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304467 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004468 uint32_t ring_id;
4469 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4470 struct nlattr *tb
4471 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4472
Jeff Johnson1f61b612016-02-12 16:28:33 -08004473 ENTER_DEV(wdev->netdev);
4474
Anurag Chouhan6d760662016-02-20 16:05:43 +05304475 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004476 hdd_err("Command not allowed in FTM mode");
4477 return -EPERM;
4478 }
4479
4480 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304481 if (status)
4482 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004483
4484 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4485 data, data_len,
4486 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004487 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004488 return -EINVAL;
4489 }
4490
4491 /* Parse and fetch ring id */
4492 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004493 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004494 return -EINVAL;
4495 }
4496
4497 ring_id = nla_get_u32(
4498 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4499
4500 if (ring_id == RING_ID_PER_PACKET_STATS) {
4501 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004502 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304503 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4504 /*
4505 * As part of DRIVER ring ID, flush both driver and fw logs.
4506 * For other Ring ID's driver doesn't have any rings to flush
4507 */
4508 hdd_notice("Bug report triggered by framework");
4509
4510 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4511 WLAN_LOG_INDICATOR_FRAMEWORK,
4512 WLAN_LOG_REASON_CODE_UNUSED,
4513 true, false);
4514 if (QDF_STATUS_SUCCESS != status) {
4515 hdd_err("Failed to trigger bug report");
4516 return -EINVAL;
4517 }
4518 } else {
4519 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4520 WLAN_LOG_INDICATOR_FRAMEWORK,
4521 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004522 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004523 return 0;
4524}
4525
4526/**
4527 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4528 * @wiphy: WIPHY structure pointer
4529 * @wdev: Wireless device structure pointer
4530 * @data: Pointer to the data received
4531 * @data_len: Length of the data received
4532 *
4533 * This function is used to flush or retrieve the per packet statistics from
4534 * the driver
4535 *
4536 * Return: 0 on success and errno on failure
4537 */
4538static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4539 struct wireless_dev *wdev,
4540 const void *data,
4541 int data_len)
4542{
4543 int ret = 0;
4544
4545 cds_ssr_protect(__func__);
4546 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4547 wdev, data, data_len);
4548 cds_ssr_unprotect(__func__);
4549
4550 return ret;
4551}
4552
4553#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4554/**
4555 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4556 * @hdd_ctx: HDD context
4557 * @request_id: [input] request id
4558 * @pattern_id: [output] pattern id
4559 *
4560 * This function loops through request id to pattern id array
4561 * if the slot is available, store the request id and return pattern id
4562 * if entry exists, return the pattern id
4563 *
4564 * Return: 0 on success and errno on failure
4565 */
4566static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4567 uint32_t request_id,
4568 uint8_t *pattern_id)
4569{
4570 uint32_t i;
4571
4572 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4573 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4574 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4575 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4576 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4577 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4578 return 0;
4579 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4580 request_id) {
4581 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4582 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4583 return 0;
4584 }
4585 }
4586 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4587 return -EINVAL;
4588}
4589
4590/**
4591 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4592 * @hdd_ctx: HDD context
4593 * @request_id: [input] request id
4594 * @pattern_id: [output] pattern id
4595 *
4596 * This function loops through request id to pattern id array
4597 * reset request id to 0 (slot available again) and
4598 * return pattern id
4599 *
4600 * Return: 0 on success and errno on failure
4601 */
4602static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4603 uint32_t request_id,
4604 uint8_t *pattern_id)
4605{
4606 uint32_t i;
4607
4608 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4609 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4610 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4611 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4612 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4613 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4614 return 0;
4615 }
4616 }
4617 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4618 return -EINVAL;
4619}
4620
4621
4622/*
4623 * define short names for the global vendor params
4624 * used by __wlan_hdd_cfg80211_offloaded_packets()
4625 */
4626#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4627#define PARAM_REQUEST_ID \
4628 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4629#define PARAM_CONTROL \
4630 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4631#define PARAM_IP_PACKET \
4632 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4633#define PARAM_SRC_MAC_ADDR \
4634 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4635#define PARAM_DST_MAC_ADDR \
4636 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4637#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4638
4639/**
4640 * wlan_hdd_add_tx_ptrn() - add tx pattern
4641 * @adapter: adapter pointer
4642 * @hdd_ctx: hdd context
4643 * @tb: nl attributes
4644 *
4645 * This function reads the NL attributes and forms a AddTxPtrn message
4646 * posts it to SME.
4647 *
4648 */
4649static int
4650wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4651 struct nlattr **tb)
4652{
4653 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304654 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004655 uint32_t request_id, ret, len;
4656 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304657 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004658 uint16_t eth_type = htons(ETH_P_IP);
4659
4660 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004661 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004662 return -ENOTSUPP;
4663 }
4664
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304665 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004666 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004667 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004668 return -ENOMEM;
4669 }
4670
4671 /* Parse and fetch request Id */
4672 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004673 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004674 goto fail;
4675 }
4676
4677 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4678 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004679 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680 return -EINVAL;
4681 }
Jeff Johnson77848112016-06-29 14:52:06 -07004682 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683
4684 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004685 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004686 goto fail;
4687 }
4688 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004689 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004691 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004692 goto fail;
4693 }
4694
4695 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004696 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697 goto fail;
4698 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004699 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304700 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004701 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004702 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004703
Anurag Chouhanc5548422016-02-24 18:33:27 +05304704 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004705 &adapter->macAddressCurrent)) {
4706 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004707 goto fail;
4708 }
4709
4710 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004711 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004712 goto fail;
4713 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304714 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004715 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004716 MAC_ADDR_ARRAY(dst_addr.bytes));
4717
4718 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004719 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004720 goto fail;
4721 }
4722 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004723 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004724
4725 if (add_req->ucPtrnSize < 0 ||
4726 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4727 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004728 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004729 add_req->ucPtrnSize);
4730 goto fail;
4731 }
4732
4733 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304734 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304735 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304736 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304737 QDF_MAC_ADDR_SIZE);
4738 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304739 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004740 len += 2;
4741
4742 /*
4743 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4744 * ------------------------------------------------------------
4745 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4746 * ------------------------------------------------------------
4747 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304748 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004749 nla_data(tb[PARAM_IP_PACKET]),
4750 add_req->ucPtrnSize);
4751 add_req->ucPtrnSize += len;
4752
4753 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4754 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004755 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004756 goto fail;
4757 }
4758 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004759 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004760
4761 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304762 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004763 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004764 goto fail;
4765 }
4766
4767 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304768 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004769 return 0;
4770
4771fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304772 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004773 return -EINVAL;
4774}
4775
4776/**
4777 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4778 * @adapter: adapter pointer
4779 * @hdd_ctx: hdd context
4780 * @tb: nl attributes
4781 *
4782 * This function reads the NL attributes and forms a DelTxPtrn message
4783 * posts it to SME.
4784 *
4785 */
4786static int
4787wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4788 struct nlattr **tb)
4789{
4790 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304791 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004792 uint32_t request_id, ret;
4793 uint8_t pattern_id = 0;
4794
4795 /* Parse and fetch request Id */
4796 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004797 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004798 return -EINVAL;
4799 }
4800 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4801 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004802 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004803 return -EINVAL;
4804 }
4805
4806 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4807 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004808 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004809 return -EINVAL;
4810 }
4811
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304812 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004813 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004814 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004815 return -ENOMEM;
4816 }
4817
Anurag Chouhanc5548422016-02-24 18:33:27 +05304818 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004819 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004820 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004821 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004822 request_id, del_req->ucPtrnId);
4823
4824 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304825 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004826 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004827 goto fail;
4828 }
4829
4830 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304831 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004832 return 0;
4833
4834fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304835 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004836 return -EINVAL;
4837}
4838
4839
4840/**
4841 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4842 * @wiphy: Pointer to wireless phy
4843 * @wdev: Pointer to wireless device
4844 * @data: Pointer to data
4845 * @data_len: Data length
4846 *
4847 * Return: 0 on success, negative errno on failure
4848 */
4849static int
4850__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4851 struct wireless_dev *wdev,
4852 const void *data,
4853 int data_len)
4854{
4855 struct net_device *dev = wdev->netdev;
4856 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4857 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4858 struct nlattr *tb[PARAM_MAX + 1];
4859 uint8_t control;
4860 int ret;
4861 static const struct nla_policy policy[PARAM_MAX + 1] = {
4862 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4863 [PARAM_CONTROL] = { .type = NLA_U32 },
4864 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304865 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004866 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304867 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004868 [PARAM_PERIOD] = { .type = NLA_U32 },
4869 };
4870
Jeff Johnson1f61b612016-02-12 16:28:33 -08004871 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004872
Anurag Chouhan6d760662016-02-20 16:05:43 +05304873 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004874 hdd_err("Command not allowed in FTM mode");
4875 return -EPERM;
4876 }
4877
4878 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304879 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004880 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004881
4882 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004883 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004884 return -ENOTSUPP;
4885 }
4886
4887 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004888 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004889 return -EINVAL;
4890 }
4891
4892 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004893 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004894 return -EINVAL;
4895 }
4896 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004897 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004898
4899 if (control == WLAN_START_OFFLOADED_PACKETS)
4900 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4901 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4902 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4903 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004904 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004905 return -EINVAL;
4906 }
4907}
4908
4909/*
4910 * done with short names for the global vendor params
4911 * used by __wlan_hdd_cfg80211_offloaded_packets()
4912 */
4913#undef PARAM_MAX
4914#undef PARAM_REQUEST_ID
4915#undef PARAM_CONTROL
4916#undef PARAM_IP_PACKET
4917#undef PARAM_SRC_MAC_ADDR
4918#undef PARAM_DST_MAC_ADDR
4919#undef PARAM_PERIOD
4920
4921/**
4922 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4923 * @wiphy: wiphy structure pointer
4924 * @wdev: Wireless device structure pointer
4925 * @data: Pointer to the data received
4926 * @data_len: Length of @data
4927 *
4928 * Return: 0 on success; errno on failure
4929 */
4930static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4931 struct wireless_dev *wdev,
4932 const void *data,
4933 int data_len)
4934{
4935 int ret = 0;
4936
4937 cds_ssr_protect(__func__);
4938 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4939 wdev, data, data_len);
4940 cds_ssr_unprotect(__func__);
4941
4942 return ret;
4943}
4944#endif
4945
4946/*
4947 * define short names for the global vendor params
4948 * used by __wlan_hdd_cfg80211_monitor_rssi()
4949 */
4950#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4951#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4952#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4953#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4954#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4955
4956/**
4957 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4958 * @wiphy: Pointer to wireless phy
4959 * @wdev: Pointer to wireless device
4960 * @data: Pointer to data
4961 * @data_len: Data length
4962 *
4963 * Return: 0 on success, negative errno on failure
4964 */
4965static int
4966__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4967 struct wireless_dev *wdev,
4968 const void *data,
4969 int data_len)
4970{
4971 struct net_device *dev = wdev->netdev;
4972 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4973 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4974 struct nlattr *tb[PARAM_MAX + 1];
4975 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304976 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004977 int ret;
4978 uint32_t control;
4979 static const struct nla_policy policy[PARAM_MAX + 1] = {
4980 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4981 [PARAM_CONTROL] = { .type = NLA_U32 },
4982 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4983 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4984 };
4985
Jeff Johnson1f61b612016-02-12 16:28:33 -08004986 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004987
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05304988 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
4989 hdd_err("invalid session id: %d", adapter->sessionId);
4990 return -EINVAL;
4991 }
4992
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004993 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304994 if (ret)
4995 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004996
4997 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004998 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004999 return -ENOTSUPP;
5000 }
5001
5002 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005003 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005004 return -EINVAL;
5005 }
5006
5007 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005008 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005009 return -EINVAL;
5010 }
5011
5012 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005013 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005014 return -EINVAL;
5015 }
5016
5017 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5018 req.session_id = adapter->sessionId;
5019 control = nla_get_u32(tb[PARAM_CONTROL]);
5020
5021 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5022 req.control = true;
5023 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005024 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005025 return -EINVAL;
5026 }
5027
5028 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005029 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005030 return -EINVAL;
5031 }
5032
5033 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5034 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5035
5036 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005037 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005038 req.min_rssi, req.max_rssi);
5039 return -EINVAL;
5040 }
Jeff Johnson77848112016-06-29 14:52:06 -07005041 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005042 req.min_rssi, req.max_rssi);
5043
5044 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5045 req.control = false;
5046 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005047 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048 return -EINVAL;
5049 }
Jeff Johnson77848112016-06-29 14:52:06 -07005050 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005051 req.request_id, req.session_id, req.control);
5052
5053 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305054 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005055 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005056 return -EINVAL;
5057 }
5058
5059 return 0;
5060}
5061
5062/*
5063 * done with short names for the global vendor params
5064 * used by __wlan_hdd_cfg80211_monitor_rssi()
5065 */
5066#undef PARAM_MAX
5067#undef PARAM_CONTROL
5068#undef PARAM_REQUEST_ID
5069#undef PARAM_MAX_RSSI
5070#undef PARAM_MIN_RSSI
5071
5072/**
5073 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5074 * @wiphy: wiphy structure pointer
5075 * @wdev: Wireless device structure pointer
5076 * @data: Pointer to the data received
5077 * @data_len: Length of @data
5078 *
5079 * Return: 0 on success; errno on failure
5080 */
5081static int
5082wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5083 const void *data, int data_len)
5084{
5085 int ret;
5086
5087 cds_ssr_protect(__func__);
5088 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5089 cds_ssr_unprotect(__func__);
5090
5091 return ret;
5092}
5093
5094/**
5095 * hdd_rssi_threshold_breached() - rssi breached NL event
5096 * @hddctx: HDD context
5097 * @data: rssi breached event data
5098 *
5099 * This function reads the rssi breached event %data and fill in the skb with
5100 * NL attributes and send up the NL event.
5101 *
5102 * Return: none
5103 */
5104void hdd_rssi_threshold_breached(void *hddctx,
5105 struct rssi_breach_event *data)
5106{
5107 hdd_context_t *hdd_ctx = hddctx;
5108 struct sk_buff *skb;
5109
5110 ENTER();
5111
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305112 if (wlan_hdd_validate_context(hdd_ctx))
5113 return;
5114 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005115 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005116 return;
5117 }
5118
5119 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5120 NULL,
5121 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5122 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5123 GFP_KERNEL);
5124
5125 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005126 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005127 return;
5128 }
5129
Jeff Johnson77848112016-06-29 14:52:06 -07005130 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005131 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005132 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005133 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5134
5135 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5136 data->request_id) ||
5137 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5138 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5139 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5140 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005141 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005142 goto fail;
5143 }
5144
5145 cfg80211_vendor_event(skb, GFP_KERNEL);
5146 return;
5147
5148fail:
5149 kfree_skb(skb);
5150 return;
5151}
5152
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305153static const struct nla_policy
5154ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5155 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5156};
5157
5158/**
5159 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5160 * @wiphy: Pointer to wireless phy
5161 * @wdev: Pointer to wireless device
5162 * @data: Pointer to data
5163 * @data_len: Length of @data
5164 *
5165 * Return: 0 on success, negative errno on failure
5166 */
5167static int
5168__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5169 struct wireless_dev *wdev,
5170 const void *data, int data_len)
5171{
5172 int status;
5173 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5174 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005175 struct net_device *dev = wdev->netdev;
5176 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305177
5178 ENTER_DEV(wdev->netdev);
5179
5180 status = wlan_hdd_validate_context(pHddCtx);
5181 if (0 != status)
5182 return status;
5183 if (!pHddCtx->config->fhostNSOffload) {
5184 hdd_err("ND Offload not supported");
5185 return -EINVAL;
5186 }
5187
5188 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5189 (struct nlattr *)data,
5190 data_len, ns_offload_set_policy)) {
5191 hdd_err("nla_parse failed");
5192 return -EINVAL;
5193 }
5194
5195 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5196 hdd_err("ND Offload flag attribute not present");
5197 return -EINVAL;
5198 }
5199
5200 pHddCtx->ns_offload_enable =
5201 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5202
Dustin Brownd8279d22016-09-07 14:52:57 -07005203 /* update ns offload in case it is already enabled/disabled */
5204 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5205
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305206 return 0;
5207}
5208
5209/**
5210 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5211 * @wiphy: pointer to wireless wiphy structure.
5212 * @wdev: pointer to wireless_dev structure.
5213 * @data: Pointer to the data to be passed via vendor interface
5214 * @data_len:Length of the data to be passed
5215 *
5216 * Return: Return the Success or Failure code.
5217 */
5218static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5219 struct wireless_dev *wdev,
5220 const void *data, int data_len)
5221{
5222 int ret;
5223
5224 cds_ssr_protect(__func__);
5225 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5226 cds_ssr_unprotect(__func__);
5227
5228 return ret;
5229}
5230
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5232 * @wiphy: Pointer to wireless phy
5233 * @wdev: Pointer to wireless device
5234 * @data: Pointer to data
5235 * @data_len: Data length
5236 *
5237 * This function return the preferred frequency list generated by the policy
5238 * manager.
5239 *
5240 * Return: success or failure code
5241 */
5242static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5243 struct wireless_dev
5244 *wdev, const void *data,
5245 int data_len)
5246{
5247 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5248 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305249 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305250 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005251 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305252 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005253 enum cds_con_mode intf_mode;
5254 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5255 struct sk_buff *reply_skb;
5256
Jeff Johnson1f61b612016-02-12 16:28:33 -08005257 ENTER_DEV(wdev->netdev);
5258
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005259 ret = wlan_hdd_validate_context(hdd_ctx);
5260 if (ret)
5261 return -EINVAL;
5262
5263 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5264 data, data_len, NULL)) {
5265 hdd_err("Invalid ATTR");
5266 return -EINVAL;
5267 }
5268
5269 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5270 hdd_err("attr interface type failed");
5271 return -EINVAL;
5272 }
5273
5274 intf_mode = nla_get_u32(tb
5275 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5276
5277 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5278 hdd_err("Invalid interface type");
5279 return -EINVAL;
5280 }
5281
5282 hdd_debug("Userspace requested pref freq list");
5283
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305284 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5285 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305286 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005287 hdd_err("Get pcl failed");
5288 return -EINVAL;
5289 }
5290
5291 /* convert channel number to frequency */
5292 for (i = 0; i < pcl_len; i++) {
5293 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5294 freq_list[i] =
5295 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005296 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005297 else
5298 freq_list[i] =
5299 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005300 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005301 }
5302
5303 /* send the freq_list back to supplicant */
5304 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5305 sizeof(u32) *
5306 pcl_len +
5307 NLMSG_HDRLEN);
5308
5309 if (!reply_skb) {
5310 hdd_err("Allocate reply_skb failed");
5311 return -EINVAL;
5312 }
5313
5314 if (nla_put_u32(reply_skb,
5315 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5316 intf_mode) ||
5317 nla_put(reply_skb,
5318 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5319 sizeof(uint32_t) * pcl_len,
5320 freq_list)) {
5321 hdd_err("nla put fail");
5322 kfree_skb(reply_skb);
5323 return -EINVAL;
5324 }
5325
5326 return cfg80211_vendor_cmd_reply(reply_skb);
5327}
5328
5329/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5330 * @wiphy: Pointer to wireless phy
5331 * @wdev: Pointer to wireless device
5332 * @data: Pointer to data
5333 * @data_len: Data length
5334 *
5335 * This function return the preferred frequency list generated by the policy
5336 * manager.
5337 *
5338 * Return: success or failure code
5339 */
5340static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5341 struct wireless_dev
5342 *wdev, const void *data,
5343 int data_len)
5344{
5345 int ret = 0;
5346
5347 cds_ssr_protect(__func__);
5348 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5349 data, data_len);
5350 cds_ssr_unprotect(__func__);
5351
5352 return ret;
5353}
5354
5355/**
5356 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5357 * @wiphy: Pointer to wireless phy
5358 * @wdev: Pointer to wireless device
5359 * @data: Pointer to data
5360 * @data_len: Data length
5361 *
5362 * Return: 0 on success, negative errno on failure
5363 */
5364static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5365 struct wireless_dev *wdev,
5366 const void *data,
5367 int data_len)
5368{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305369 struct net_device *ndev = wdev->netdev;
5370 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005371 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5372 int ret = 0;
5373 enum cds_con_mode intf_mode;
5374 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5375 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376
Jeff Johnson1f61b612016-02-12 16:28:33 -08005377 ENTER_DEV(ndev);
5378
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005379 ret = wlan_hdd_validate_context(hdd_ctx);
5380 if (ret)
5381 return ret;
5382
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005383 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5384 data, data_len, NULL)) {
5385 hdd_err("Invalid ATTR");
5386 return -EINVAL;
5387 }
5388
5389 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5390 hdd_err("attr interface type failed");
5391 return -EINVAL;
5392 }
5393
5394 intf_mode = nla_get_u32(tb
5395 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5396
5397 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5398 hdd_err("Invalid interface type");
5399 return -EINVAL;
5400 }
5401
5402 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5403 hdd_err("attr probable freq failed");
5404 return -EINVAL;
5405 }
5406
5407 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5408 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5409
5410 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005411 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005412 channel_hint, HW_MODE_20_MHZ)) {
5413 hdd_err("Set channel hint failed due to concurrency check");
5414 return -EINVAL;
5415 }
5416
Krunal Soni09e55032016-06-07 10:06:55 -07005417 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5418 hdd_warn("Remain On Channel Pending");
5419
Krunal Soni3091bcc2016-06-23 12:28:21 -07005420 ret = qdf_reset_connection_update();
5421 if (!QDF_IS_STATUS_SUCCESS(ret))
5422 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005423
Krunal Soni3091bcc2016-06-23 12:28:21 -07005424 ret = cds_current_connections_update(adapter->sessionId,
5425 channel_hint,
5426 SIR_UPDATE_REASON_SET_OPER_CHAN);
5427 if (QDF_STATUS_E_FAILURE == ret) {
5428 /* return in the failure case */
5429 hdd_err("ERROR: connections update failed!!");
5430 return -EINVAL;
5431 }
5432
5433 if (QDF_STATUS_SUCCESS == ret) {
5434 /*
5435 * Success is the only case for which we expect hw mode
5436 * change to take place, hence we need to wait.
5437 * For any other return value it should be a pass
5438 * through
5439 */
5440 ret = qdf_wait_for_connection_update();
5441 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5442 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443 return -EINVAL;
5444 }
5445
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446 }
5447
5448 return 0;
5449}
5450
5451/**
5452 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5453 * @wiphy: Pointer to wireless phy
5454 * @wdev: Pointer to wireless device
5455 * @data: Pointer to data
5456 * @data_len: Data length
5457 *
5458 * Return: 0 on success, negative errno on failure
5459 */
5460static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5461 struct wireless_dev *wdev,
5462 const void *data,
5463 int data_len)
5464{
5465 int ret = 0;
5466
5467 cds_ssr_protect(__func__);
5468 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5469 data, data_len);
5470 cds_ssr_unprotect(__func__);
5471
5472 return ret;
5473}
5474
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305475static const struct
5476nla_policy
5477qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5478 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5479};
5480
5481/**
5482 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5483 * @wiphy: WIPHY structure pointer
5484 * @wdev: Wireless device structure pointer
5485 * @data: Pointer to the data received
5486 * @data_len: Length of the data received
5487 *
5488 * This function is used to get link properties like nss, rate flags and
5489 * operating frequency for the active connection with the given peer.
5490 *
5491 * Return: 0 on success and errno on failure
5492 */
5493static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5494 struct wireless_dev *wdev,
5495 const void *data,
5496 int data_len)
5497{
5498 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5499 struct net_device *dev = wdev->netdev;
5500 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5501 hdd_station_ctx_t *hdd_sta_ctx;
5502 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305503 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305504 uint32_t sta_id;
5505 struct sk_buff *reply_skb;
5506 uint32_t rate_flags = 0;
5507 uint8_t nss;
5508 uint8_t final_rate_flags = 0;
5509 uint32_t freq;
5510
Jeff Johnson1f61b612016-02-12 16:28:33 -08005511 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305512
Anurag Chouhan6d760662016-02-20 16:05:43 +05305513 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305514 hdd_err("Command not allowed in FTM mode");
5515 return -EPERM;
5516 }
5517
5518 if (0 != wlan_hdd_validate_context(hdd_ctx))
5519 return -EINVAL;
5520
5521 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5522 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005523 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305524 return -EINVAL;
5525 }
5526
5527 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005528 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305529 adapter->device_mode);
5530 return -EINVAL;
5531 }
5532
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305533 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305534 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005535 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305536 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5537
Krunal Sonib4326f22016-03-10 13:05:51 -08005538 if (adapter->device_mode == QDF_STA_MODE ||
5539 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305540 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5541 if ((hdd_sta_ctx->conn_info.connState !=
5542 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305543 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305544 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005545 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305546 MAC_ADDR_ARRAY(peer_mac));
5547 return -EINVAL;
5548 }
5549
5550 nss = hdd_sta_ctx->conn_info.nss;
5551 freq = cds_chan_to_freq(
5552 hdd_sta_ctx->conn_info.operationChannel);
5553 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005554 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5555 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305556
5557 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5558 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305559 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305560 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305561 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305562 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305563 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305564 break;
5565 }
5566
5567 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005568 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305569 MAC_ADDR_ARRAY(peer_mac));
5570 return -EINVAL;
5571 }
5572
5573 nss = adapter->aStaInfo[sta_id].nss;
5574 freq = cds_chan_to_freq(
5575 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5576 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5577 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005578 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305579 MAC_ADDR_ARRAY(peer_mac));
5580 return -EINVAL;
5581 }
5582
5583 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5584 if (rate_flags & eHAL_TX_RATE_VHT80) {
5585 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005586#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305587 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005588#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305589 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5590 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005591#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305592 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005593#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305594 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5595 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5596 } else if (rate_flags &
5597 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5598 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005599#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305600 if (rate_flags & eHAL_TX_RATE_HT40)
5601 final_rate_flags |=
5602 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005603#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305604 }
5605
5606 if (rate_flags & eHAL_TX_RATE_SGI) {
5607 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5608 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5609 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5610 }
5611 }
5612
5613 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5614 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5615
5616 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005617 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305618 return -EINVAL;
5619 }
5620
5621 if (nla_put_u8(reply_skb,
5622 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5623 nss) ||
5624 nla_put_u8(reply_skb,
5625 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5626 final_rate_flags) ||
5627 nla_put_u32(reply_skb,
5628 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5629 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005630 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305631 kfree_skb(reply_skb);
5632 return -EINVAL;
5633 }
5634
5635 return cfg80211_vendor_cmd_reply(reply_skb);
5636}
5637
5638/**
5639 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5640 * properties.
5641 * @wiphy: WIPHY structure pointer
5642 * @wdev: Wireless device structure pointer
5643 * @data: Pointer to the data received
5644 * @data_len: Length of the data received
5645 *
5646 * This function is used to get link properties like nss, rate flags and
5647 * operating frequency for the active connection with the given peer.
5648 *
5649 * Return: 0 on success and errno on failure
5650 */
5651static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5652 struct wireless_dev *wdev,
5653 const void *data,
5654 int data_len)
5655{
5656 int ret = 0;
5657
5658 cds_ssr_protect(__func__);
5659 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5660 wdev, data, data_len);
5661 cds_ssr_unprotect(__func__);
5662
5663 return ret;
5664}
5665
Peng Xu278d0122015-09-24 16:34:17 -07005666static const struct
5667nla_policy
5668qca_wlan_vendor_ota_test_policy
5669[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5670 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5671};
5672
5673/**
5674 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5675 * @wiphy: Pointer to wireless phy
5676 * @wdev: Pointer to wireless device
5677 * @data: Pointer to data
5678 * @data_len: Data length
5679 *
5680 * Return: 0 on success, negative errno on failure
5681 */
5682static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5683 struct wireless_dev *wdev,
5684 const void *data,
5685 int data_len)
5686{
5687 struct net_device *dev = wdev->netdev;
5688 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5689 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5690 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5691 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5692 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305693 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005694 uint32_t current_roam_state;
5695
Jeff Johnson1f61b612016-02-12 16:28:33 -08005696 ENTER_DEV(dev);
5697
Anurag Chouhan6d760662016-02-20 16:05:43 +05305698 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005699 hdd_err("Command not allowed in FTM mode");
5700 return -EPERM;
5701 }
5702
5703 if (0 != wlan_hdd_validate_context(hdd_ctx))
5704 return -EINVAL;
5705
5706 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5707 data, data_len,
5708 qca_wlan_vendor_ota_test_policy)) {
5709 hdd_err("invalid attr");
5710 return -EINVAL;
5711 }
5712
5713 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5714 hdd_err("attr ota test failed");
5715 return -EINVAL;
5716 }
5717
5718 ota_enable = nla_get_u8(
5719 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5720
5721 hdd_info(" OTA test enable = %d", ota_enable);
5722 if (ota_enable != 1) {
5723 hdd_err("Invalid value, only enable test mode is supported!");
5724 return -EINVAL;
5725 }
5726
5727 current_roam_state =
5728 sme_get_current_roam_state(hal, adapter->sessionId);
5729 status = sme_stop_roaming(hal, adapter->sessionId,
5730 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305731 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005732 hdd_err("Enable/Disable roaming failed");
5733 return -EINVAL;
5734 }
5735
5736 status = sme_ps_enable_disable(hal, adapter->sessionId,
5737 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305738 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005739 hdd_err("Enable/Disable power save failed");
5740 /* restore previous roaming setting */
5741 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5742 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5743 status = sme_start_roaming(hal, adapter->sessionId,
5744 eCsrHddIssued);
5745 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5746 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5747 status = sme_stop_roaming(hal, adapter->sessionId,
5748 eCsrHddIssued);
5749
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305750 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005751 hdd_err("Restoring roaming state failed");
5752
5753 return -EINVAL;
5754 }
5755
5756
5757 return 0;
5758}
5759
5760/**
5761 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5762 * @wiphy: Pointer to wireless phy
5763 * @wdev: Pointer to wireless device
5764 * @data: Pointer to data
5765 * @data_len: Data length
5766 *
5767 * Return: 0 on success, negative errno on failure
5768 */
5769static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5770 struct wireless_dev *wdev,
5771 const void *data,
5772 int data_len)
5773{
5774 int ret = 0;
5775
5776 cds_ssr_protect(__func__);
5777 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5778 cds_ssr_unprotect(__func__);
5779
5780 return ret;
5781}
5782
Peng Xu4d67c8f2015-10-16 16:02:26 -07005783/**
5784 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5785 * @wiphy: Pointer to wireless phy
5786 * @wdev: Pointer to wireless device
5787 * @data: Pointer to data
5788 * @data_len: Data length
5789 *
5790 * Return: 0 on success, negative errno on failure
5791 */
5792static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5793 struct wireless_dev *wdev,
5794 const void *data,
5795 int data_len)
5796{
5797 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5798 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005799 hdd_adapter_t *adapter;
5800 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005801 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5802 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005803 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005804
Jeff Johnson1f61b612016-02-12 16:28:33 -08005805 ENTER_DEV(dev);
5806
Peng Xu4d67c8f2015-10-16 16:02:26 -07005807 ret = wlan_hdd_validate_context(hdd_ctx);
5808 if (ret)
5809 return ret;
5810
5811 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5812
5813 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5814 data, data_len, NULL)) {
5815 hdd_err("Invalid ATTR");
5816 return -EINVAL;
5817 }
5818
5819 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5820 hdd_err("attr tx power scale failed");
5821 return -EINVAL;
5822 }
5823
5824 scale_value = nla_get_u8(tb
5825 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5826
5827 if (scale_value > MAX_TXPOWER_SCALE) {
5828 hdd_err("Invalid tx power scale level");
5829 return -EINVAL;
5830 }
5831
Peng Xu62c8c432016-05-09 15:23:02 -07005832 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005833
Peng Xu62c8c432016-05-09 15:23:02 -07005834 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005835 hdd_err("Set tx power scale failed");
5836 return -EINVAL;
5837 }
5838
5839 return 0;
5840}
5841
5842/**
5843 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5844 * @wiphy: Pointer to wireless phy
5845 * @wdev: Pointer to wireless device
5846 * @data: Pointer to data
5847 * @data_len: Data length
5848 *
5849 * Return: 0 on success, negative errno on failure
5850 */
5851static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5852 struct wireless_dev *wdev,
5853 const void *data,
5854 int data_len)
5855{
Peng Xu62c8c432016-05-09 15:23:02 -07005856 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005857
5858 cds_ssr_protect(__func__);
5859 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5860 data, data_len);
5861 cds_ssr_unprotect(__func__);
5862
5863 return ret;
5864}
5865
5866/**
5867 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5868 * @wiphy: Pointer to wireless phy
5869 * @wdev: Pointer to wireless device
5870 * @data: Pointer to data
5871 * @data_len: Data length
5872 *
5873 * Return: 0 on success, negative errno on failure
5874 */
5875static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5876 struct wireless_dev *wdev,
5877 const void *data,
5878 int data_len)
5879{
5880 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5881 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005882 hdd_adapter_t *adapter;
5883 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005884 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5885 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005886 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005887
Jeff Johnson1f61b612016-02-12 16:28:33 -08005888 ENTER_DEV(dev);
5889
Peng Xu4d67c8f2015-10-16 16:02:26 -07005890 ret = wlan_hdd_validate_context(hdd_ctx);
5891 if (ret)
5892 return ret;
5893
5894 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5895
5896 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5897 data, data_len, NULL)) {
5898 hdd_err("Invalid ATTR");
5899 return -EINVAL;
5900 }
5901
5902 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5903 hdd_err("attr tx power decrease db value failed");
5904 return -EINVAL;
5905 }
5906
5907 scale_value = nla_get_u8(tb
5908 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5909
Peng Xu62c8c432016-05-09 15:23:02 -07005910 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5911 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005912
Peng Xu62c8c432016-05-09 15:23:02 -07005913 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005914 hdd_err("Set tx power decrease db failed");
5915 return -EINVAL;
5916 }
5917
5918 return 0;
5919}
5920
5921/**
5922 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5923 * @wiphy: Pointer to wireless phy
5924 * @wdev: Pointer to wireless device
5925 * @data: Pointer to data
5926 * @data_len: Data length
5927 *
5928 * Return: 0 on success, negative errno on failure
5929 */
5930static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5931 struct wireless_dev *wdev,
5932 const void *data,
5933 int data_len)
5934{
Peng Xu62c8c432016-05-09 15:23:02 -07005935 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005936
5937 cds_ssr_protect(__func__);
5938 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5939 data, data_len);
5940 cds_ssr_unprotect(__func__);
5941
5942 return ret;
5943}
Peng Xu8fdaa492016-06-22 10:20:47 -07005944
5945/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305946 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5947 * @wiphy: Pointer to wireless phy
5948 * @wdev: Pointer to wireless device
5949 * @data: Pointer to data
5950 * @data_len: Data length
5951 *
5952 * Processes the conditional channel switch request and invokes the helper
5953 * APIs to process the channel switch request.
5954 *
5955 * Return: 0 on success, negative errno on failure
5956 */
5957static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5958 struct wireless_dev *wdev,
5959 const void *data,
5960 int data_len)
5961{
5962 int ret;
5963 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5964 struct net_device *dev = wdev->netdev;
5965 hdd_adapter_t *adapter;
5966 struct nlattr
5967 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5968 uint32_t freq_len, i;
5969 uint32_t *freq;
5970 uint8_t chans[QDF_MAX_NUM_CHAN];
5971
5972 ENTER_DEV(dev);
5973
5974 ret = wlan_hdd_validate_context(hdd_ctx);
5975 if (ret)
5976 return ret;
5977
5978 if (!hdd_ctx->config->enableDFSMasterCap) {
5979 hdd_err("DFS master capability is not present in the driver");
5980 return -EINVAL;
5981 }
5982
5983 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5984 hdd_err("Command not allowed in FTM mode");
5985 return -EPERM;
5986 }
5987
5988 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5989 if (adapter->device_mode != QDF_SAP_MODE) {
5990 hdd_err("Invalid device mode %d", adapter->device_mode);
5991 return -EINVAL;
5992 }
5993
5994 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
5995 data, data_len, NULL)) {
5996 hdd_err("Invalid ATTR");
5997 return -EINVAL;
5998 }
5999
6000 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6001 hdd_err("Frequency list is missing");
6002 return -EINVAL;
6003 }
6004
6005 freq_len = nla_len(
6006 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6007 sizeof(uint32_t);
6008
6009 if (freq_len > QDF_MAX_NUM_CHAN) {
6010 hdd_err("insufficient space to hold channels");
6011 return -ENOMEM;
6012 }
6013
6014 hdd_debug("freq_len=%d", freq_len);
6015
6016 freq = nla_data(
6017 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6018
6019
6020 for (i = 0; i < freq_len; i++) {
6021 if (freq[i] == 0)
6022 chans[i] = 0;
6023 else
6024 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6025
6026 hdd_debug("freq[%d]=%d", i, freq[i]);
6027 }
6028
6029 /*
6030 * The input frequency list from user space is designed to be a
6031 * priority based frequency list. This is only to accommodate any
6032 * future request. But, current requirement is only to perform CAC
6033 * on a single channel. So, the first entry from the list is picked.
6034 *
6035 * If channel is zero, any channel in the available outdoor regulatory
6036 * domain will be selected.
6037 */
6038 ret = wlan_hdd_request_pre_cac(chans[0]);
6039 if (ret) {
6040 hdd_err("pre cac request failed with reason:%d", ret);
6041 return ret;
6042 }
6043
6044 return 0;
6045}
6046
6047/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006048 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6049 * @wiphy: Pointer to wireless phy
6050 * @wdev: Pointer to wireless device
6051 * @data: Pointer to data
6052 * @data_len: Data length
6053 *
6054 * This function is to process the p2p listen offload start vendor
6055 * command. It parses the input parameters and invoke WMA API to
6056 * send the command to firmware.
6057 *
6058 * Return: 0 on success, negative errno on failure
6059 */
6060static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6061 struct wireless_dev *wdev,
6062 const void *data,
6063 int data_len)
6064{
6065 int ret;
6066 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6067 struct net_device *dev = wdev->netdev;
6068 hdd_adapter_t *adapter;
6069 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6070 struct sir_p2p_lo_start params;
6071 QDF_STATUS status;
6072
6073 ENTER_DEV(dev);
6074
6075 ret = wlan_hdd_validate_context(hdd_ctx);
6076 if (ret)
6077 return ret;
6078
6079 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6080 hdd_err("Command not allowed in FTM mode");
6081 return -EPERM;
6082 }
6083
6084 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6085 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6086 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6087 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6088 hdd_err("Invalid device mode %d", adapter->device_mode);
6089 return -EINVAL;
6090 }
6091
6092 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6093 data, data_len, NULL)) {
6094 hdd_err("Invalid ATTR");
6095 return -EINVAL;
6096 }
6097
6098 memset(&params, 0, sizeof(params));
6099
6100 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6101 params.ctl_flags = 1; /* set to default value */
6102 else
6103 params.ctl_flags = nla_get_u32(tb
6104 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6105
6106 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6107 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6108 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6109 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6110 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6111 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6112 hdd_err("Attribute parsing failed");
6113 return -EINVAL;
6114 }
6115
6116 params.vdev_id = adapter->sessionId;
6117 params.freq = nla_get_u32(tb
6118 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6119 if ((params.freq != 2412) && (params.freq != 2437) &&
6120 (params.freq != 2462)) {
6121 hdd_err("Invalid listening channel: %d", params.freq);
6122 return -EINVAL;
6123 }
6124
6125 params.period = nla_get_u32(tb
6126 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6127 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6128 hdd_err("Invalid period: %d", params.period);
6129 return -EINVAL;
6130 }
6131
6132 params.interval = nla_get_u32(tb
6133 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6134 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6135 hdd_err("Invalid interval: %d", params.interval);
6136 return -EINVAL;
6137 }
6138
6139 params.count = nla_get_u32(tb
6140 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
6141 if (!((params.count > 0) && (params.count < UINT_MAX))) {
6142 hdd_err("Invalid count: %d", params.count);
6143 return -EINVAL;
6144 }
6145
6146 params.device_types = nla_data(tb
6147 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6148 if (params.device_types == NULL) {
6149 hdd_err("Invalid device types");
6150 return -EINVAL;
6151 }
6152
6153 params.dev_types_len = nla_len(tb
6154 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6155 if (params.dev_types_len < 8) {
6156 hdd_err("Invalid device type length: %d", params.dev_types_len);
6157 return -EINVAL;
6158 }
6159
6160 params.probe_resp_tmplt = nla_data(tb
6161 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6162 if (params.probe_resp_tmplt == NULL) {
6163 hdd_err("Invalid probe response template");
6164 return -EINVAL;
6165 }
6166
6167 params.probe_resp_len = nla_len(tb
6168 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6169 if (params.probe_resp_len == 0) {
6170 hdd_err("Invalid probe resp template length: %d",
6171 params.probe_resp_len);
6172 return -EINVAL;
6173 }
6174
6175 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6176 params.freq, params.period, params.interval, params.count);
6177
6178 status = wma_p2p_lo_start(&params);
6179
6180 if (!QDF_IS_STATUS_SUCCESS(status)) {
6181 hdd_err("P2P LO start failed");
6182 return -EINVAL;
6183 }
6184
6185 return 0;
6186}
6187
6188
6189/**
6190 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6191 * @wiphy: Pointer to wireless phy
6192 * @wdev: Pointer to wireless device
6193 * @data: Pointer to data
6194 * @data_len: Data length
6195 *
6196 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6197 * to process p2p listen offload start vendor command.
6198 *
6199 * Return: 0 on success, negative errno on failure
6200 */
6201static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6202 struct wireless_dev *wdev,
6203 const void *data,
6204 int data_len)
6205{
6206 int ret = 0;
6207
6208 cds_ssr_protect(__func__);
6209 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6210 data, data_len);
6211 cds_ssr_unprotect(__func__);
6212
6213 return ret;
6214}
6215
6216/**
6217 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6218 * @wiphy: Pointer to wireless phy
6219 * @wdev: Pointer to wireless device
6220 * @data: Pointer to data
6221 * @data_len: Data length
6222 *
6223 * This function is to process the p2p listen offload stop vendor
6224 * command. It invokes WMA API to send command to firmware.
6225 *
6226 * Return: 0 on success, negative errno on failure
6227 */
6228static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6229 struct wireless_dev *wdev,
6230 const void *data,
6231 int data_len)
6232{
6233 QDF_STATUS status;
6234 hdd_adapter_t *adapter;
6235 struct net_device *dev = wdev->netdev;
6236
6237 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6238 hdd_err("Command not allowed in FTM mode");
6239 return -EPERM;
6240 }
6241
6242 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6243 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6244 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6245 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6246 hdd_err("Invalid device mode");
6247 return -EINVAL;
6248 }
6249
6250 status = wma_p2p_lo_stop(adapter->sessionId);
6251
6252 if (!QDF_IS_STATUS_SUCCESS(status)) {
6253 hdd_err("P2P LO stop failed");
6254 return -EINVAL;
6255 }
6256
6257 return 0;
6258}
6259
6260/**
6261 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6262 * @wiphy: Pointer to wireless phy
6263 * @wdev: Pointer to wireless device
6264 * @data: Pointer to data
6265 * @data_len: Data length
6266 *
6267 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6268 * to process p2p listen offload stop vendor command.
6269 *
6270 * Return: 0 on success, negative errno on failure
6271 */
6272static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6273 struct wireless_dev *wdev,
6274 const void *data,
6275 int data_len)
6276{
6277 int ret = 0;
6278
6279 cds_ssr_protect(__func__);
6280 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6281 data, data_len);
6282 cds_ssr_unprotect(__func__);
6283
6284 return ret;
6285}
6286
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306287/**
6288 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6289 * @wiphy: Pointer to wireless phy
6290 * @wdev: Pointer to wireless device
6291 * @data: Pointer to data
6292 * @data_len: Data length
6293 *
6294 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6295 * to process the conditional channel switch request.
6296 *
6297 * Return: 0 on success, negative errno on failure
6298 */
6299static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6300 struct wireless_dev *wdev,
6301 const void *data,
6302 int data_len)
6303{
6304 int ret;
6305
6306 cds_ssr_protect(__func__);
6307 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6308 data, data_len);
6309 cds_ssr_unprotect(__func__);
6310
6311 return ret;
6312}
6313
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306314/*
6315 * define short names for the global vendor params
6316 * used by __wlan_hdd_cfg80211_bpf_offload()
6317 */
6318#define BPF_INVALID \
6319 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6320#define BPF_SET_RESET \
6321 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6322#define BPF_VERSION \
6323 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6324#define BPF_FILTER_ID \
6325 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6326#define BPF_PACKET_SIZE \
6327 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6328#define BPF_CURRENT_OFFSET \
6329 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6330#define BPF_PROGRAM \
6331 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6332#define BPF_MAX \
6333 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006334
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306335static const struct nla_policy
6336wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6337 [BPF_SET_RESET] = {.type = NLA_U32},
6338 [BPF_VERSION] = {.type = NLA_U32},
6339 [BPF_FILTER_ID] = {.type = NLA_U32},
6340 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6341 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6342 [BPF_PROGRAM] = {.type = NLA_U8},
6343};
6344
6345/**
6346 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6347 * @hdd_context: hdd_context
6348 * @bpf_get_offload: struct for get offload
6349 *
6350 * This function receives the response/data from the lower layer and
6351 * checks to see if the thread is still waiting then post the results to
6352 * upper layer, if the request has timed out then ignore.
6353 *
6354 * Return: None
6355 */
6356void hdd_get_bpf_offload_cb(void *hdd_context,
6357 struct sir_bpf_get_offload *data)
6358{
6359 hdd_context_t *hdd_ctx = hdd_context;
6360 struct hdd_bpf_context *context;
6361
6362 ENTER();
6363
6364 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006365 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306366 data);
6367 return;
6368 }
6369
6370 spin_lock(&hdd_context_lock);
6371
6372 context = &bpf_context;
6373 /* The caller presumably timed out so there is nothing we can do */
6374 if (context->magic != BPF_CONTEXT_MAGIC) {
6375 spin_unlock(&hdd_context_lock);
6376 return;
6377 }
6378
6379 /* context is valid so caller is still waiting */
6380 /* paranoia: invalidate the magic */
6381 context->magic = 0;
6382
6383 context->capability_response = *data;
6384 complete(&context->completion);
6385
6386 spin_unlock(&hdd_context_lock);
6387
6388 return;
6389}
6390
6391/**
6392 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6393 * @hdd_context: hdd_context
6394 * @bpf_get_offload: struct for get offload
6395 *
6396 * Return: 0 on success, error number otherwise.
6397 */
6398static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6399 struct sir_bpf_get_offload *bpf_get_offload)
6400{
6401 struct sk_buff *skb;
6402 uint32_t nl_buf_len;
6403
6404 ENTER();
6405
6406 nl_buf_len = NLMSG_HDRLEN;
6407 nl_buf_len +=
6408 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6409 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6410
6411 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6412 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006413 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306414 return -ENOMEM;
6415 }
6416
Jeff Johnson77848112016-06-29 14:52:06 -07006417 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306418 bpf_get_offload->bpf_version,
6419 bpf_get_offload->max_bytes_for_bpf_inst);
6420
6421 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6422 bpf_get_offload->max_bytes_for_bpf_inst) ||
6423 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006424 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306425 goto nla_put_failure;
6426 }
6427
6428 cfg80211_vendor_cmd_reply(skb);
6429 EXIT();
6430 return 0;
6431
6432nla_put_failure:
6433 kfree_skb(skb);
6434 return -EINVAL;
6435}
6436
6437/**
6438 * hdd_get_bpf_offload - Get BPF offload Capabilities
6439 * @hdd_ctx: Hdd context
6440 *
6441 * Return: 0 on success, errno on failure
6442 */
6443static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6444{
6445 unsigned long rc;
Houston Hoffman59c097f2016-11-09 15:50:25 -08006446 static struct hdd_bpf_context *context;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306447 QDF_STATUS status;
6448 int ret;
6449
6450 ENTER();
6451
6452 spin_lock(&hdd_context_lock);
6453 context = &bpf_context;
6454 context->magic = BPF_CONTEXT_MAGIC;
6455 INIT_COMPLETION(context->completion);
6456 spin_unlock(&hdd_context_lock);
6457
6458 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6459 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006460 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306461 return -EINVAL;
6462 }
6463 /* request was sent -- wait for the response */
6464 rc = wait_for_completion_timeout(&context->completion,
6465 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6466 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006467 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306468 spin_lock(&hdd_context_lock);
6469 context->magic = 0;
6470 spin_unlock(&hdd_context_lock);
6471
6472 return -ETIMEDOUT;
6473 }
6474 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6475 &bpf_context.capability_response);
6476 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006477 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306478
6479 EXIT();
6480 return ret;
6481}
6482
6483/**
6484 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6485 * @hdd_ctx: Hdd context
6486 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306487 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306488 *
6489 * Return: 0 on success; errno on failure
6490 */
6491static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6492 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306493 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306494{
6495 struct sir_bpf_set_offload *bpf_set_offload;
6496 QDF_STATUS status;
6497 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306498 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306499
6500 ENTER();
6501
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306502 if (adapter->device_mode == QDF_STA_MODE ||
6503 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6504 if (!hdd_conn_is_connected(
6505 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6506 hdd_err("Not in Connected state!");
6507 return -ENOTSUPP;
6508 }
6509 }
6510
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306511 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6512 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006513 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306514 return -ENOMEM;
6515 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306516
6517 /* Parse and fetch bpf packet size */
6518 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006519 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306520 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306521 goto fail;
6522 }
6523 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6524
6525 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006526 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306527 goto post_sme;
6528 }
6529
6530 /* Parse and fetch bpf program */
6531 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006532 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306533 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306534 goto fail;
6535 }
6536
6537 prog_len = nla_len(tb[BPF_PROGRAM]);
6538 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306539
6540 if (bpf_set_offload->program == NULL) {
6541 hdd_err("qdf_mem_malloc failed for bpf offload program");
6542 ret = -ENOMEM;
6543 goto fail;
6544 }
6545
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306546 bpf_set_offload->current_length = prog_len;
6547 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306548 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306549
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306550 hdd_info("BPF set instructions");
6551 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6552 bpf_set_offload->program, prog_len);
6553
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306554 /* Parse and fetch filter Id */
6555 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006556 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306557 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306558 goto fail;
6559 }
6560 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6561
6562 /* Parse and fetch current offset */
6563 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006564 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306565 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306566 goto fail;
6567 }
6568 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6569
6570post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006571 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 +05306572 bpf_set_offload->session_id,
6573 bpf_set_offload->version,
6574 bpf_set_offload->filter_id,
6575 bpf_set_offload->total_length,
6576 bpf_set_offload->current_length,
6577 bpf_set_offload->current_offset);
6578
6579 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6580 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006581 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306582 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306583 goto fail;
6584 }
6585 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306586
6587fail:
6588 if (bpf_set_offload->current_length)
6589 qdf_mem_free(bpf_set_offload->program);
6590 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306591 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306592}
6593
6594/**
6595 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6596 * @wiphy: wiphy structure pointer
6597 * @wdev: Wireless device structure pointer
6598 * @data: Pointer to the data received
6599 * @data_len: Length of @data
6600 *
6601 * Return: 0 on success; errno on failure
6602 */
6603static int
6604__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6605 struct wireless_dev *wdev,
6606 const void *data, int data_len)
6607{
6608 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6609 struct net_device *dev = wdev->netdev;
6610 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6611 struct nlattr *tb[BPF_MAX + 1];
6612 int ret_val, packet_filter_subcmd;
6613
6614 ENTER();
6615
6616 ret_val = wlan_hdd_validate_context(hdd_ctx);
6617 if (ret_val)
6618 return ret_val;
6619
6620 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006621 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306622 return -EINVAL;
6623 }
6624
6625 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006626 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306627 return -ENOTSUPP;
6628 }
6629
6630 if (nla_parse(tb, BPF_MAX, data, data_len,
6631 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006632 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306633 return -EINVAL;
6634 }
6635
6636 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006637 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306638 return -EINVAL;
6639 }
6640
6641 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6642
6643 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6644 return hdd_get_bpf_offload(hdd_ctx);
6645 else
6646 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306647 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306648}
6649
6650/**
6651 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6652 * @wiphy: wiphy structure pointer
6653 * @wdev: Wireless device structure pointer
6654 * @data: Pointer to the data received
6655 * @data_len: Length of @data
6656 *
6657 * Return: 0 on success; errno on failure
6658 */
6659
6660static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6661 struct wireless_dev *wdev,
6662 const void *data, int data_len)
6663{
6664 int ret;
6665
6666 cds_ssr_protect(__func__);
6667 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6668 cds_ssr_unprotect(__func__);
6669
6670 return ret;
6671}
6672
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306673/**
6674 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6675 * @pre_cac_adapter: AP adapter used for pre cac
6676 * @status: Status (true or false)
6677 * @handle: Global handle
6678 *
6679 * Sets the status of pre cac i.e., whether the pre cac is active or not
6680 *
6681 * Return: Zero on success, non-zero on failure
6682 */
6683static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6684 bool status, tHalHandle handle)
6685{
6686 QDF_STATUS ret;
6687
6688 ret = wlan_sap_set_pre_cac_status(
6689 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6690 if (QDF_IS_STATUS_ERROR(ret))
6691 return -EINVAL;
6692
6693 return 0;
6694}
6695
6696/**
6697 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6698 * @ap_adapter: AP adapter
6699 * @chan_before_pre_cac: Channel
6700 *
6701 * Saves the channel which the AP was beaconing on before moving to the pre
6702 * cac channel. If radar is detected on the pre cac channel, this saved
6703 * channel will be used for AP operations.
6704 *
6705 * Return: Zero on success, non-zero on failure
6706 */
6707static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6708 uint8_t chan_before_pre_cac)
6709{
6710 QDF_STATUS ret;
6711
6712 ret = wlan_sap_set_chan_before_pre_cac(
6713 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6714 if (QDF_IS_STATUS_ERROR(ret))
6715 return -EINVAL;
6716
6717 return 0;
6718}
6719
6720/**
6721 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6722 * @ap_adapter: AP adapter
6723 * @nol: Non-occupancy list
6724 * @nol_len: Length of NOL
6725 *
6726 * Get the NOL for SAP
6727 *
6728 * Return: Zero on success, non-zero on failure
6729 */
6730static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6731 uint32_t *nol_len)
6732{
6733 QDF_STATUS ret;
6734
6735 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6736 nol, nol_len);
6737 if (QDF_IS_STATUS_ERROR(ret))
6738 return -EINVAL;
6739
6740 return 0;
6741}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306742
6743/**
6744 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6745 * @hdd_ctx: HDD context
6746 * @ap_adapter: AP adapter
6747 * @channel: Channel requested by userspace
6748 * @pre_cac_chan: Pointer to the pre CAC channel
6749 *
6750 * Validates the channel provided by userspace. If user provided channel 0,
6751 * a valid outdoor channel must be selected from the regulatory channel.
6752 *
6753 * Return: Zero on success and non zero value on error
6754 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006755static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6756 hdd_adapter_t *ap_adapter,
6757 uint8_t channel,
6758 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306759{
6760 uint32_t i, j;
6761 QDF_STATUS status;
6762 int ret;
6763 uint8_t nol[QDF_MAX_NUM_CHAN];
6764 uint32_t nol_len = 0, weight_len = 0;
6765 bool found;
6766 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6767 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6768 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6769
6770 if (0 == channel) {
6771 /* Channel is not obtained from PCL because PCL may not have
6772 * the entire channel list. For example: if SAP is up on
6773 * channel 6 and PCL is queried for the next SAP interface,
6774 * if SCC is preferred, the PCL will contain only the channel
6775 * 6. But, we are in need of a DFS channel. So, going with the
6776 * first channel from the valid channel list.
6777 */
6778 status = cds_get_valid_chans(channel_list, &len);
6779 if (QDF_IS_STATUS_ERROR(status)) {
6780 hdd_err("Failed to get channel list");
6781 return -EINVAL;
6782 }
6783 cds_update_with_safe_channel_list(channel_list, &len,
6784 pcl_weights, weight_len);
6785 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6786 for (i = 0; i < len; i++) {
6787 found = false;
6788 for (j = 0; j < nol_len; j++) {
6789 if (channel_list[i] == nol[j]) {
6790 found = true;
6791 break;
6792 }
6793 }
6794 if (found)
6795 continue;
6796 if (CDS_IS_DFS_CH(channel_list[i])) {
6797 *pre_cac_chan = channel_list[i];
6798 break;
6799 }
6800 }
6801 if (*pre_cac_chan == 0) {
6802 hdd_err("unable to find outdoor channel");
6803 return -EINVAL;
6804 }
6805 } else {
6806 /* Only when driver selects a channel, check is done for
6807 * unnsafe and NOL channels. When user provides a fixed channel
6808 * the user is expected to take care of this.
6809 */
6810 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6811 !CDS_IS_DFS_CH(channel)) {
6812 hdd_err("Invalid channel for pre cac:%d", channel);
6813 return -EINVAL;
6814 } else {
6815 *pre_cac_chan = channel;
6816 }
6817 }
6818 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6819 return 0;
6820}
6821
6822/**
6823 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6824 * @channel: Channel option provided by userspace
6825 *
6826 * Sets the driver to the required hardware mode and start an adapater for
6827 * pre CAC which will mimic an AP.
6828 *
6829 * Return: Zero on success, non-zero value on error
6830 */
6831int wlan_hdd_request_pre_cac(uint8_t channel)
6832{
Krunal Sonib37bb352016-12-20 14:12:21 -08006833 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306834 hdd_context_t *hdd_ctx;
6835 int ret;
6836 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6837 hdd_ap_ctx_t *hdd_ap_ctx;
6838 QDF_STATUS status;
6839 struct wiphy *wiphy;
6840 struct net_device *dev;
6841 struct cfg80211_chan_def chandef;
6842 enum nl80211_channel_type channel_type;
6843 uint32_t freq;
6844 struct ieee80211_channel *chan;
6845 tHalHandle handle;
6846 bool val;
6847
6848 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6849 if (0 != wlan_hdd_validate_context(hdd_ctx))
6850 return -EINVAL;
6851
6852 if (cds_get_connection_count() > 1) {
6853 hdd_err("pre cac not allowed in concurrency");
6854 return -EINVAL;
6855 }
6856
6857 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6858 if (!ap_adapter) {
6859 hdd_err("unable to get SAP adapter");
6860 return -EINVAL;
6861 }
6862
6863 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6864 if (!handle) {
6865 hdd_err("Invalid handle");
6866 return -EINVAL;
6867 }
6868
6869 val = wlan_sap_is_pre_cac_active(handle);
6870 if (val) {
6871 hdd_err("pre cac is already in progress");
6872 return -EINVAL;
6873 }
6874
6875 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6876 if (!hdd_ap_ctx) {
6877 hdd_err("SAP context is NULL");
6878 return -EINVAL;
6879 }
6880
6881 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6882 hdd_err("SAP is already on DFS channel:%d",
6883 hdd_ap_ctx->operatingChannel);
6884 return -EINVAL;
6885 }
6886
6887 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6888 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6889 hdd_ap_ctx->operatingChannel);
6890 return -EINVAL;
6891 }
6892
Krunal Sonib37bb352016-12-20 14:12:21 -08006893 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6894 if (!mac_addr) {
6895 hdd_err("can't add virtual intf: Not getting valid mac addr");
6896 return -EINVAL;
6897 }
6898
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306899 hdd_info("channel:%d", channel);
6900
6901 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6902 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08006903 if (ret != 0) {
6904 hdd_err("can't validate pre-cac channel");
6905 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306906 }
6907
6908 hdd_debug("starting pre cac SAP adapter");
6909
6910 /* Starting a SAP adapter:
6911 * Instead of opening an adapter, we could just do a SME open session
6912 * for AP type. But, start BSS would still need an adapter.
6913 * So, this option is not taken.
6914 *
6915 * hdd open adapter is going to register this precac interface with
6916 * user space. This interface though exposed to user space will be in
6917 * DOWN state. Consideration was done to avoid this registration to the
6918 * user space. But, as part of SAP operations multiple events are sent
6919 * to user space. Some of these events received from unregistered
6920 * interface was causing crashes. So, retaining the registration.
6921 *
6922 * So, this interface would remain registered and will remain in DOWN
6923 * state for the CAC duration. We will add notes in the feature
6924 * announcement to not use this temporary interface for any activity
6925 * from user space.
6926 */
6927 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08006928 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306929 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306930 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08006931 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306932 }
6933
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306934 /*
6935 * This interface is internally created by the driver. So, no interface
6936 * up comes for this interface from user space and hence starting
6937 * the adapter internally.
6938 */
6939 if (hdd_start_adapter(pre_cac_adapter)) {
6940 hdd_err("error starting the pre cac adapter");
6941 goto close_pre_cac_adapter;
6942 }
6943
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306944 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6945
6946 wiphy = hdd_ctx->wiphy;
6947 dev = pre_cac_adapter->dev;
6948
6949 /* Since this is only a dummy interface lets us use the IEs from the
6950 * other active SAP interface. In regular scenarios, these IEs would
6951 * come from the user space entity
6952 */
6953 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6954 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6955 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6956 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306957 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306958 }
6959 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6960 ap_adapter->sessionCtx.ap.beacon,
6961 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6962 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6963 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6964 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6965 ap_adapter->sessionCtx.ap.sapConfig.authType;
6966
6967 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6968 * to operate on the same bandwidth as that of the 2.4GHz operations.
6969 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6970 */
6971 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6972 case CH_WIDTH_20MHZ:
6973 channel_type = NL80211_CHAN_HT20;
6974 break;
6975 case CH_WIDTH_40MHZ:
6976 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6977 ap_adapter->sessionCtx.ap.sapConfig.channel)
6978 channel_type = NL80211_CHAN_HT40PLUS;
6979 else
6980 channel_type = NL80211_CHAN_HT40MINUS;
6981 break;
6982 default:
6983 channel_type = NL80211_CHAN_NO_HT;
6984 break;
6985 }
6986
6987 freq = cds_chan_to_freq(pre_cac_chan);
6988 chan = __ieee80211_get_channel(wiphy, freq);
6989 if (!chan) {
6990 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306991 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306992 }
6993
6994 cfg80211_chandef_create(&chandef, chan, channel_type);
6995
6996 hdd_debug("orig width:%d channel_type:%d freq:%d",
6997 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
6998 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08006999 /*
7000 * Doing update after opening and starting pre-cac adapter will make
7001 * sure that driver won't do hardware mode change if there are any
7002 * initial hick-ups or issues in pre-cac adapter's configuration.
7003 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7004 * connection update should result in DBS mode
7005 */
7006 status = cds_update_and_wait_for_connection_update(
7007 ap_adapter->sessionId,
7008 pre_cac_chan,
7009 SIR_UPDATE_REASON_PRE_CAC);
7010 if (QDF_IS_STATUS_ERROR(status)) {
7011 hdd_err("error in moving to DBS mode");
7012 goto stop_close_pre_cac_adapter;
7013 }
7014
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307015
7016 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7017 if (0 != ret) {
7018 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307019 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307020 }
7021
7022 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7023 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007024 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307025 if (QDF_IS_STATUS_ERROR(status)) {
7026 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307027 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307028 }
7029
7030 /*
7031 * The pre cac status is set here. But, it would not be reset explicitly
7032 * anywhere, since after the pre cac success/failure, the pre cac
7033 * adapter itself would be removed.
7034 */
7035 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7036 if (0 != ret) {
7037 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307038 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307039 }
7040
7041 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7042 hdd_ap_ctx->operatingChannel);
7043 if (0 != ret) {
7044 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307045 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307046 }
7047
7048 ap_adapter->pre_cac_chan = pre_cac_chan;
7049
7050 return 0;
7051
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307052stop_close_pre_cac_adapter:
7053 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307054 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7055 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307056close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307057 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007058release_intf_addr_and_return_failure:
7059 /*
7060 * Release the interface address as the adapter
7061 * failed to start, if you don't release then next
7062 * adapter which is trying to come wouldn't get valid
7063 * mac address. Remember we have limited pool of mac addresses
7064 */
7065 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307066 return -EINVAL;
7067}
7068
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307069/**
7070 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7071 *
7072 * Return: None
7073 */
7074void hdd_init_bpf_completion(void)
7075{
7076 init_completion(&bpf_context.completion);
7077}
7078
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307079static const struct nla_policy
7080wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7081 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7082};
7083
Agrawal Ashish65634612016-08-18 13:24:32 +05307084static const struct nla_policy
7085wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7086 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7087 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7088};
7089
7090/**
7091 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7092 * @wiphy: Pointer to wireless phy
7093 * @wdev: Pointer to wireless device
7094 * @data: Pointer to data
7095 * @data_len: Length of @data
7096 *
7097 * This function parses the incoming NL vendor command data attributes and
7098 * updates the SAP context about channel_hint and DFS mode.
7099 * If channel_hint is set, SAP will choose that channel
7100 * as operating channel.
7101 *
7102 * If DFS mode is enabled, driver will include DFS channels
7103 * in ACS else driver will skip DFS channels.
7104 *
7105 * Return: 0 on success, negative errno on failure
7106 */
7107static int
7108__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7109 struct wireless_dev *wdev,
7110 const void *data, int data_len)
7111{
7112 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7113 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7114 int ret;
7115 struct acs_dfs_policy *acs_policy;
7116 int mode = DFS_MODE_NONE;
7117 int channel_hint = 0;
7118
7119 ENTER_DEV(wdev->netdev);
7120
7121 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7122 hdd_err("Command not allowed in FTM mode");
7123 return -EINVAL;
7124 }
7125
7126 ret = wlan_hdd_validate_context(hdd_ctx);
7127 if (0 != ret)
7128 return ret;
7129
7130 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7131 data, data_len,
7132 wlan_hdd_set_acs_dfs_config_policy)) {
7133 hdd_err("invalid attr");
7134 return -EINVAL;
7135 }
7136
7137 acs_policy = &hdd_ctx->acs_policy;
7138 /*
7139 * SCM sends this attribute to restrict SAP from choosing
7140 * DFS channels from ACS.
7141 */
7142 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7143 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7144
7145 if (!IS_DFS_MODE_VALID(mode)) {
7146 hdd_err("attr acs dfs mode is not valid");
7147 return -EINVAL;
7148 }
7149 acs_policy->acs_dfs_mode = mode;
7150
7151 /*
7152 * SCM sends this attribute to provide an active channel,
7153 * to skip redundant ACS between drivers, and save driver start up time
7154 */
7155 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7156 channel_hint = nla_get_u8(
7157 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7158
7159 if (!IS_CHANNEL_VALID(channel_hint)) {
7160 hdd_err("acs channel is not valid");
7161 return -EINVAL;
7162 }
7163 acs_policy->acs_channel = channel_hint;
7164
7165 return 0;
7166}
7167
7168/**
7169 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7170 * @wiphy: wiphy structure pointer
7171 * @wdev: Wireless device structure pointer
7172 * @data: Pointer to the data received
7173 * @data_len: Length of @data
7174 *
7175 * This function parses the incoming NL vendor command data attributes and
7176 * updates the SAP context about channel_hint and DFS mode.
7177 *
7178 * Return: 0 on success; errno on failure
7179 */
7180static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7181 struct wireless_dev *wdev,
7182 const void *data, int data_len)
7183{
7184 int ret;
7185
7186 cds_ssr_protect(__func__);
7187 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7188 cds_ssr_unprotect(__func__);
7189
7190 return ret;
7191}
7192
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307193/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307194 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7195 * @mode : cfg80211 dfs mode
7196 *
7197 * Return: return csr sta roam dfs mode else return NONE
7198 */
7199static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7200 enum dfs_mode mode)
7201{
7202 switch (mode) {
7203 case DFS_MODE_ENABLE:
7204 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7205 break;
7206 case DFS_MODE_DISABLE:
7207 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7208 break;
7209 case DFS_MODE_DEPRIORITIZE:
7210 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7211 break;
7212 default:
7213 hdd_err("STA Roam policy dfs mode is NONE");
7214 return CSR_STA_ROAM_POLICY_NONE;
7215 }
7216}
7217
7218static const struct nla_policy
7219wlan_hdd_set_sta_roam_config_policy[
7220QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7221 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7222 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7223};
7224
7225/**
7226 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7227 * for station connection or roaming.
7228 * @wiphy: Pointer to wireless phy
7229 * @wdev: Pointer to wireless device
7230 * @data: Pointer to data
7231 * @data_len: Length of @data
7232 *
7233 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7234 * channels needs to be skipped in scanning or not.
7235 * If dfs_mode is disabled, driver will not scan DFS channels.
7236 * If skip_unsafe_channels is set, driver will skip unsafe channels
7237 * in Scanning.
7238 *
7239 * Return: 0 on success, negative errno on failure
7240 */
7241static int
7242__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7243 struct wireless_dev *wdev,
7244 const void *data, int data_len)
7245{
7246 struct net_device *dev = wdev->netdev;
7247 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7248 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7249 struct nlattr *tb[
7250 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7251 int ret;
7252 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7253 enum dfs_mode mode = DFS_MODE_NONE;
7254 bool skip_unsafe_channels = false;
7255 QDF_STATUS status;
7256
7257 ENTER_DEV(dev);
7258
7259 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7260 hdd_err("Command not allowed in FTM mode");
7261 return -EINVAL;
7262 }
7263
7264 ret = wlan_hdd_validate_context(hdd_ctx);
7265 if (0 != ret)
7266 return ret;
7267 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7268 data, data_len,
7269 wlan_hdd_set_sta_roam_config_policy)) {
7270 hdd_err("invalid attr");
7271 return -EINVAL;
7272 }
7273 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7274 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7275 if (!IS_DFS_MODE_VALID(mode)) {
7276 hdd_err("attr sta roam dfs mode policy is not valid");
7277 return -EINVAL;
7278 }
7279
7280 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7281
7282 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7283 skip_unsafe_channels = nla_get_u8(
7284 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7285
7286 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7287 skip_unsafe_channels, adapter->sessionId);
7288
7289 if (!QDF_IS_STATUS_SUCCESS(status)) {
7290 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7291 return -EINVAL;
7292 }
7293 return 0;
7294}
7295
7296/**
7297 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7298 * connection and roaming for station.
7299 * @wiphy: wiphy structure pointer
7300 * @wdev: Wireless device structure pointer
7301 * @data: Pointer to the data received
7302 * @data_len: Length of @data
7303 *
7304 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7305 * channels needs to be skipped in scanning or not.
7306 * If dfs_mode is disabled, driver will not scan DFS channels.
7307 * If skip_unsafe_channels is set, driver will skip unsafe channels
7308 * in Scanning.
7309 * Return: 0 on success; errno on failure
7310 */
7311static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7312 struct wireless_dev *wdev,
7313 const void *data, int data_len)
7314{
7315 int ret;
7316
7317 cds_ssr_protect(__func__);
7318 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7319 cds_ssr_unprotect(__func__);
7320
7321 return ret;
7322}
7323
Agrawal Ashish467dde42016-09-08 18:44:22 +05307324#ifdef FEATURE_WLAN_CH_AVOID
7325/**
7326 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7327 * is on unsafe channel.
7328 * @wiphy: wiphy structure pointer
7329 * @wdev: Wireless device structure pointer
7330 * @data: Pointer to the data received
7331 * @data_len: Length of @data
7332 *
7333 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7334 * on any of unsafe channels.
7335 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7336 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7337 *
7338 * Return: 0 on success; errno on failure
7339 */
7340static int
7341__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7342 struct wireless_dev *wdev,
7343 const void *data, int data_len)
7344{
7345 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7346 int ret;
7347 uint16_t unsafe_channel_count;
7348 int unsafe_channel_index;
7349 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7350
7351 ENTER_DEV(wdev->netdev);
7352
7353 if (!qdf_ctx) {
7354 cds_err("qdf_ctx is NULL");
7355 return -EINVAL;
7356 }
7357
7358 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7359 hdd_err("Command not allowed in FTM mode");
7360 return -EINVAL;
7361 }
7362
7363 ret = wlan_hdd_validate_context(hdd_ctx);
7364 if (0 != ret)
7365 return ret;
7366 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7367 &(hdd_ctx->unsafe_channel_count),
7368 sizeof(hdd_ctx->unsafe_channel_list));
7369
7370 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7371 (uint16_t)NUM_CHANNELS);
7372 for (unsafe_channel_index = 0;
7373 unsafe_channel_index < unsafe_channel_count;
7374 unsafe_channel_index++) {
7375 hdd_info("Channel %d is not safe",
7376 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7377 }
7378 hdd_unsafe_channel_restart_sap(hdd_ctx);
7379 return 0;
7380}
7381
7382/**
7383 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7384 * is on unsafe channel.
7385 * @wiphy: wiphy structure pointer
7386 * @wdev: Wireless device structure pointer
7387 * @data: Pointer to the data received
7388 * @data_len: Length of @data
7389 *
7390 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7391 * on any of unsafe channels.
7392 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7393 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7394 *
7395 * Return: 0 on success; errno on failure
7396 */
7397static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7398 struct wireless_dev *wdev,
7399 const void *data, int data_len)
7400{
7401 int ret;
7402
7403 cds_ssr_protect(__func__);
7404 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7405 cds_ssr_unprotect(__func__);
7406
7407 return ret;
7408}
7409
7410#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307411/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307412 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7413 * SAP is on unsafe channel.
7414 * @wiphy: wiphy structure pointer
7415 * @wdev: Wireless device structure pointer
7416 * @data: Pointer to the data received
7417 * @data_len: Length of @data
7418 *
7419 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7420 * driver.
7421 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7422 * will initiate restart of sap.
7423 *
7424 * Return: 0 on success; errno on failure
7425 */
7426static int
7427__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7428 struct wireless_dev *wdev,
7429 const void *data, int data_len)
7430{
7431 struct net_device *ndev = wdev->netdev;
7432 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7433 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7434 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7435 uint8_t config_channel = 0;
7436 hdd_ap_ctx_t *ap_ctx;
7437 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307438 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307439
7440 ENTER();
7441
7442 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007443 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307444 return -EINVAL;
7445 }
7446
7447 ret = wlan_hdd_validate_context(hdd_ctx);
7448 if (0 != ret)
7449 return -EINVAL;
7450
7451 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7452 data, data_len,
7453 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007454 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307455 return -EINVAL;
7456 }
7457
7458 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7459 if (!test_bit(SOFTAP_BSS_STARTED,
7460 &hostapd_adapter->event_flags)) {
7461 hdd_err("SAP is not started yet. Restart sap will be invalid");
7462 return -EINVAL;
7463 }
7464
7465 config_channel =
7466 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7467
7468 if (!((IS_24G_CH(config_channel)) ||
7469 (IS_5G_CH(config_channel)))) {
7470 hdd_err("Channel %d is not valid to restart SAP",
7471 config_channel);
7472 return -ENOTSUPP;
7473 }
7474
7475 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7476 ap_ctx->sapConfig.channel = config_channel;
7477 ap_ctx->sapConfig.ch_params.ch_width =
7478 ap_ctx->sapConfig.ch_width_orig;
7479
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007480 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307481 ap_ctx->sapConfig.sec_ch,
7482 &ap_ctx->sapConfig.ch_params);
7483
7484 cds_restart_sap(hostapd_adapter);
7485 }
7486
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307487 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7488 uint32_t freq_len, i;
7489 uint32_t *freq;
7490 uint8_t chans[QDF_MAX_NUM_CHAN];
7491
7492 hdd_debug("setting mandatory freq/chan list");
7493
7494 freq_len = nla_len(
7495 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7496 sizeof(uint32_t);
7497
7498 if (freq_len > QDF_MAX_NUM_CHAN) {
7499 hdd_err("insufficient space to hold channels");
7500 return -ENOMEM;
7501 }
7502
7503 freq = nla_data(
7504 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7505
7506 hdd_debug("freq_len=%d", freq_len);
7507
7508 for (i = 0; i < freq_len; i++) {
7509 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7510 hdd_debug("freq[%d]=%d", i, freq[i]);
7511 }
7512
7513 status = cds_set_sap_mandatory_channels(chans, freq_len);
7514 if (QDF_IS_STATUS_ERROR(status))
7515 return -EINVAL;
7516 }
7517
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307518 return 0;
7519}
7520
7521/**
7522 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7523 * @wiphy: wiphy structure pointer
7524 * @wdev: Wireless device structure pointer
7525 * @data: Pointer to the data received
7526 * @data_len: Length of @data
7527 *
7528 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7529 * driver.
7530 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7531 * will initiate restart of sap.
7532 *
7533 * Return: 0 on success; errno on failure
7534 */
7535static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7536 struct wireless_dev *wdev,
7537 const void *data, int data_len)
7538{
7539 int ret;
7540
7541 cds_ssr_protect(__func__);
7542 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7543 wdev, data, data_len);
7544 cds_ssr_unprotect(__func__);
7545
7546 return ret;
7547}
7548
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307549#undef BPF_INVALID
7550#undef BPF_SET_RESET
7551#undef BPF_VERSION
7552#undef BPF_ID
7553#undef BPF_PACKET_SIZE
7554#undef BPF_CURRENT_OFFSET
7555#undef BPF_PROGRAM
7556#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307557
7558/**
7559 * define short names for the global vendor params
7560 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7561 */
7562#define PARAM_TOTAL_CMD_EVENT_WAKE \
7563 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7564#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7565 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7566#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7567 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7568#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7569 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7570#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7571 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7572#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7573 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7574#define PARAM_TOTAL_RX_DATA_WAKE \
7575 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7576#define PARAM_RX_UNICAST_CNT \
7577 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7578#define PARAM_RX_MULTICAST_CNT \
7579 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7580#define PARAM_RX_BROADCAST_CNT \
7581 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7582#define PARAM_ICMP_PKT \
7583 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7584#define PARAM_ICMP6_PKT \
7585 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7586#define PARAM_ICMP6_RA \
7587 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7588#define PARAM_ICMP6_NA \
7589 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7590#define PARAM_ICMP6_NS \
7591 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7592#define PARAM_ICMP4_RX_MULTICAST_CNT \
7593 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7594#define PARAM_ICMP6_RX_MULTICAST_CNT \
7595 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7596#define PARAM_OTHER_RX_MULTICAST_CNT \
7597 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
7598
7599
7600/**
7601 * hdd_send_wakelock_stats() - API to send wakelock stats
7602 * @ctx: context to be passed to callback
7603 * @data: data passed to callback
7604 *
7605 * This function is used to send wake lock stats to HAL layer
7606 *
7607 * Return: 0 on success, error number otherwise.
7608 */
7609static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7610 const struct sir_wake_lock_stats *data)
7611{
7612 struct sk_buff *skb;
7613 uint32_t nl_buf_len;
7614 uint32_t total_rx_data_wake, rx_multicast_cnt;
7615 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307616 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307617
7618 ENTER();
7619
7620 nl_buf_len = NLMSG_HDRLEN;
7621 nl_buf_len +=
7622 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7623 (NLMSG_HDRLEN + sizeof(uint32_t));
7624
7625 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7626
7627 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007628 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307629 return -ENOMEM;
7630 }
7631
Jeff Johnson64943bd2016-08-23 13:14:06 -07007632 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307633 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007634 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307635 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007636 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307637 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007638 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307639 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007640 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307641 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007642 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307643 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007644 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307645 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007646 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7647 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307648 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307649
7650 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307651 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307652
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307653 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307654 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307655
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307656 rx_multicast_cnt =
7657 data->wow_ipv4_mcast_wake_up_count +
7658 ipv6_rx_multicast_addr_cnt;
7659
7660 total_rx_data_wake =
7661 data->wow_ucast_wake_up_count +
7662 data->wow_bcast_wake_up_count +
7663 rx_multicast_cnt;
7664
7665 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7666 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7667 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7668 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7669 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7670 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7671 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7672 total_rx_data_wake) ||
7673 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7674 data->wow_ucast_wake_up_count) ||
7675 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7676 rx_multicast_cnt) ||
7677 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7678 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307679 nla_put_u32(skb, PARAM_ICMP_PKT,
7680 data->wow_icmpv4_count) ||
7681 nla_put_u32(skb, PARAM_ICMP6_PKT,
7682 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307683 nla_put_u32(skb, PARAM_ICMP6_RA,
7684 data->wow_ipv6_mcast_ra_stats) ||
7685 nla_put_u32(skb, PARAM_ICMP6_NA,
7686 data->wow_ipv6_mcast_na_stats) ||
7687 nla_put_u32(skb, PARAM_ICMP6_NS,
7688 data->wow_ipv6_mcast_ns_stats) ||
7689 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7690 data->wow_ipv4_mcast_wake_up_count) ||
7691 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7692 ipv6_rx_multicast_addr_cnt) ||
7693 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007694 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307695 goto nla_put_failure;
7696 }
7697
7698 cfg80211_vendor_cmd_reply(skb);
7699
7700 EXIT();
7701 return 0;
7702
7703nla_put_failure:
7704 kfree_skb(skb);
7705 return -EINVAL;
7706}
7707
7708/**
7709 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7710 * @wiphy: wiphy pointer
7711 * @wdev: pointer to struct wireless_dev
7712 * @data: pointer to incoming NL vendor data
7713 * @data_len: length of @data
7714 *
7715 * This function parses the incoming NL vendor command data attributes and
7716 * invokes the SME Api and blocks on a completion variable.
7717 * WMA copies required data and invokes callback
7718 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7719 *
7720 * Return: 0 on success; error number otherwise.
7721 */
7722static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7723 struct wireless_dev *wdev,
7724 const void *data,
7725 int data_len)
7726{
7727 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7728 int status, ret;
7729 struct sir_wake_lock_stats wake_lock_stats;
7730 QDF_STATUS qdf_status;
7731
7732 ENTER();
7733
7734 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007735 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307736 return -EINVAL;
7737 }
7738
7739 status = wlan_hdd_validate_context(hdd_ctx);
7740 if (0 != status)
7741 return -EINVAL;
7742
7743 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7744 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007745 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307746 return -EINVAL;
7747 }
7748
7749 ret = hdd_send_wakelock_stats(hdd_ctx,
7750 &wake_lock_stats);
7751 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007752 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307753
7754 EXIT();
7755 return ret;
7756}
7757
7758/**
7759 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7760 * @wiphy: wiphy pointer
7761 * @wdev: pointer to struct wireless_dev
7762 * @data: pointer to incoming NL vendor data
7763 * @data_len: length of @data
7764 *
7765 * This function parses the incoming NL vendor command data attributes and
7766 * invokes the SME Api and blocks on a completion variable.
7767 * WMA copies required data and invokes callback
7768 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7769 *
7770 * Return: 0 on success; error number otherwise.
7771 */
7772static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7773 struct wireless_dev *wdev,
7774 const void *data, int data_len)
7775{
7776 int ret;
7777
7778 cds_ssr_protect(__func__);
7779 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7780 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007781 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307782
7783 return ret;
7784}
7785
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307786/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307787 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7788 * @wiphy: wiphy structure pointer
7789 * @wdev: Wireless device structure pointer
7790 * @data: Pointer to the data received
7791 * @data_len: Length of @data
7792 *
7793 * This function reads wmi max bus size and fill in the skb with
7794 * NL attributes and send up the NL event.
7795 * Return: 0 on success; errno on failure
7796 */
7797static int
7798__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7799 struct wireless_dev *wdev,
7800 const void *data, int data_len)
7801{
7802 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7803 int ret_val;
7804 struct sk_buff *skb;
7805 uint32_t nl_buf_len;
7806
7807 ENTER();
7808
7809 ret_val = wlan_hdd_validate_context(hdd_ctx);
7810 if (ret_val)
7811 return ret_val;
7812
7813 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7814 hdd_err("Command not allowed in FTM mode");
7815 return -EINVAL;
7816 }
7817
7818 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7819
7820 nl_buf_len = NLMSG_HDRLEN;
7821 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7822
7823 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7824 if (!skb) {
7825 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7826 return -ENOMEM;
7827 }
7828
7829 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7830 hdd_ctx->wmi_max_len)) {
7831 hdd_err("nla put failure");
7832 goto nla_put_failure;
7833 }
7834
7835 cfg80211_vendor_cmd_reply(skb);
7836
7837 EXIT();
7838
7839 return 0;
7840
7841nla_put_failure:
7842 kfree_skb(skb);
7843 return -EINVAL;
7844}
7845
7846/**
7847 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7848 * @wiphy: wiphy structure pointer
7849 * @wdev: Wireless device structure pointer
7850 * @data: Pointer to the data received
7851 * @data_len: Length of @data
7852 *
7853 * Return: 0 on success; errno on failure
7854 */
7855static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7856 struct wireless_dev *wdev,
7857 const void *data, int data_len)
7858{
7859 int ret;
7860
7861 cds_ssr_protect(__func__);
7862 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7863 cds_ssr_unprotect(__func__);
7864
7865 return ret;
7866}
7867
7868/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307869 *__wlan_hdd_cfg80211_setband() - set band
7870 * @wiphy: Pointer to wireless phy
7871 * @wdev: Pointer to wireless device
7872 * @data: Pointer to data
7873 * @data_len: Length of @data
7874 *
7875 * Return: 0 on success, negative errno on failure
7876 */
7877static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7878 struct wireless_dev *wdev,
7879 const void *data, int data_len)
7880{
7881 struct net_device *dev = wdev->netdev;
7882 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7883 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7884 int ret;
7885 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7886 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7887
7888 ENTER();
7889
7890 ret = wlan_hdd_validate_context(hdd_ctx);
7891 if (ret)
7892 return ret;
7893
7894 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7895 hdd_err(FL("Invalid ATTR"));
7896 return -EINVAL;
7897 }
7898
7899 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7900 hdd_err(FL("attr SETBAND_VALUE failed"));
7901 return -EINVAL;
7902 }
7903
7904 ret = hdd_set_band(dev,
7905 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7906
7907 EXIT();
7908 return ret;
7909}
7910
7911/**
7912 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7913 * @wiphy: wiphy structure pointer
7914 * @wdev: Wireless device structure pointer
7915 * @data: Pointer to the data received
7916 * @data_len: Length of @data
7917 *
7918 * Return: 0 on success; errno on failure
7919 */
7920static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7921 struct wireless_dev *wdev,
7922 const void *data, int data_len)
7923{
7924 int ret;
7925
7926 cds_ssr_protect(__func__);
7927 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7928 cds_ssr_unprotect(__func__);
7929
7930 return ret;
7931}
7932
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307933static const struct
7934nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7935 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7936 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7937 .len = QDF_MAC_ADDR_SIZE},
7938};
7939
7940/**
7941 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7942 * @wiphy: Pointer to wireless phy
7943 * @wdev: Pointer to wireless device
7944 * @data: Pointer to data
7945 * @data_len: Length of @data
7946 *
7947 * This function is used to enable/disable roaming using vendor commands
7948 *
7949 * Return: 0 on success, negative errno on failure
7950 */
7951static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7952 struct wireless_dev *wdev,
7953 const void *data, int data_len)
7954{
7955 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7956 struct net_device *dev = wdev->netdev;
7957 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7958 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7959 uint32_t is_fast_roam_enabled;
7960 int ret;
7961
7962 ENTER_DEV(dev);
7963
7964 ret = wlan_hdd_validate_context(hdd_ctx);
7965 if (0 != ret)
7966 return ret;
7967
7968 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7969 hdd_err("Command not allowed in FTM mode");
7970 return -EINVAL;
7971 }
7972
7973 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
7974 qca_wlan_vendor_attr);
7975 if (ret) {
7976 hdd_err("Invalid ATTR");
7977 return -EINVAL;
7978 }
7979
7980 /* Parse and fetch Enable flag */
7981 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
7982 hdd_err("attr enable failed");
7983 return -EINVAL;
7984 }
7985
7986 is_fast_roam_enabled = nla_get_u32(
7987 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
7988 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
7989
7990 /* Update roaming */
7991 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
7992 is_fast_roam_enabled);
7993 if (ret)
7994 hdd_err("sme_config_fast_roaming failed");
7995 EXIT();
7996 return ret;
7997}
7998
7999/**
8000 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8001 * @wiphy: Pointer to wireless phy
8002 * @wdev: Pointer to wireless device
8003 * @data: Pointer to data
8004 * @data_len: Length of @data
8005 *
8006 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
8007 *
8008 * Return: 0 on success, negative errno on failure
8009 */
8010static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8011 struct wireless_dev *wdev,
8012 const void *data, int data_len)
8013{
8014 int ret;
8015
8016 cds_ssr_protect(__func__);
8017 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
8018 cds_ssr_unprotect(__func__);
8019
8020 return ret;
8021}
8022
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008023const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
8024 {
8025 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8026 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
8027 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05308028 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008029 .doit = is_driver_dfs_capable
8030 },
8031
8032#ifdef WLAN_FEATURE_NAN
8033 {
8034 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8035 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
8036 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8037 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8038 .doit = wlan_hdd_cfg80211_nan_request
8039 },
8040#endif
8041
8042#ifdef WLAN_FEATURE_STATS_EXT
8043 {
8044 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8045 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
8046 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8047 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8048 .doit = wlan_hdd_cfg80211_stats_ext_request
8049 },
8050#endif
8051#ifdef FEATURE_WLAN_EXTSCAN
8052 {
8053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
8055 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8056 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8057 .doit = wlan_hdd_cfg80211_extscan_start
8058 },
8059 {
8060 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8061 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
8062 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8063 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8064 .doit = wlan_hdd_cfg80211_extscan_stop
8065 },
8066 {
8067 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8068 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8069 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8070 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8071 },
8072 {
8073 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8074 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8075 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8076 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8077 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8078 },
8079 {
8080 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8081 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8082 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8083 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8084 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8085 },
8086 {
8087 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8088 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8089 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8090 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8091 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8092 },
8093 {
8094 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8095 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8096 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8097 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8098 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8099 },
8100 {
8101 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8102 .info.subcmd =
8103 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8104 .flags =
8105 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8106 WIPHY_VENDOR_CMD_NEED_RUNNING,
8107 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8108 },
8109 {
8110 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8111 .info.subcmd =
8112 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8113 .flags =
8114 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8115 WIPHY_VENDOR_CMD_NEED_RUNNING,
8116 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8117 },
8118 {
8119 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8120 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8121 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8122 WIPHY_VENDOR_CMD_NEED_NETDEV |
8123 WIPHY_VENDOR_CMD_NEED_RUNNING,
8124 .doit = wlan_hdd_cfg80211_set_epno_list
8125 },
8126#endif /* FEATURE_WLAN_EXTSCAN */
8127
8128#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8129 {
8130 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8131 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8132 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8133 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8134 .doit = wlan_hdd_cfg80211_ll_stats_clear
8135 },
8136
8137 {
8138 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8139 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8140 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8141 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8142 .doit = wlan_hdd_cfg80211_ll_stats_set
8143 },
8144
8145 {
8146 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8147 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8148 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8149 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8150 .doit = wlan_hdd_cfg80211_ll_stats_get
8151 },
8152#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8153#ifdef FEATURE_WLAN_TDLS
8154 {
8155 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8156 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8157 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8158 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8159 .doit = wlan_hdd_cfg80211_exttdls_enable
8160 },
8161 {
8162 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8163 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8164 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8165 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8166 .doit = wlan_hdd_cfg80211_exttdls_disable
8167 },
8168 {
8169 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8170 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8171 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8172 .doit = wlan_hdd_cfg80211_exttdls_get_status
8173 },
8174#endif
8175 {
8176 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8177 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8178 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8179 .doit = wlan_hdd_cfg80211_get_supported_features
8180 },
8181 {
8182 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8183 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8184 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8185 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8186 },
8187 {
8188 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8189 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8190 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308191 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008192 },
8193 {
8194 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8195 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8196 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8197 WIPHY_VENDOR_CMD_NEED_NETDEV,
8198 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8199 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008200 {
8201 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8202 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8203 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8204 WIPHY_VENDOR_CMD_NEED_NETDEV,
8205 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8206 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008207 {
8208 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308209 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8210 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8211 WIPHY_VENDOR_CMD_NEED_NETDEV |
8212 WIPHY_VENDOR_CMD_NEED_RUNNING,
8213 .doit = hdd_cfg80211_get_station_cmd
8214 },
8215 {
8216 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008217 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8218 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8219 WIPHY_VENDOR_CMD_NEED_NETDEV |
8220 WIPHY_VENDOR_CMD_NEED_RUNNING,
8221 .doit = wlan_hdd_cfg80211_do_acs
8222 },
8223
8224 {
8225 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8226 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8227 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8228 WIPHY_VENDOR_CMD_NEED_NETDEV,
8229 .doit = wlan_hdd_cfg80211_get_features
8230 },
8231#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8232 {
8233 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8234 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8235 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8236 WIPHY_VENDOR_CMD_NEED_NETDEV |
8237 WIPHY_VENDOR_CMD_NEED_RUNNING,
8238 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8239 },
8240#endif
8241#ifdef FEATURE_WLAN_EXTSCAN
8242 {
8243 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8244 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8245 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8246 WIPHY_VENDOR_CMD_NEED_NETDEV |
8247 WIPHY_VENDOR_CMD_NEED_RUNNING,
8248 .doit = wlan_hdd_cfg80211_set_passpoint_list
8249 },
8250 {
8251 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8252 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8253 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8254 WIPHY_VENDOR_CMD_NEED_NETDEV |
8255 WIPHY_VENDOR_CMD_NEED_RUNNING,
8256 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8257 },
8258 {
8259 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8260 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8261 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8262 WIPHY_VENDOR_CMD_NEED_NETDEV |
8263 WIPHY_VENDOR_CMD_NEED_RUNNING,
8264 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8265 },
8266 {
8267 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8268 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8269 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8270 WIPHY_VENDOR_CMD_NEED_NETDEV |
8271 WIPHY_VENDOR_CMD_NEED_RUNNING,
8272 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8273 },
8274#endif /* FEATURE_WLAN_EXTSCAN */
8275 {
8276 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8277 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8278 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8279 WIPHY_VENDOR_CMD_NEED_NETDEV,
8280 .doit = wlan_hdd_cfg80211_get_wifi_info
8281 },
8282 {
8283 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8284 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8285 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8286 WIPHY_VENDOR_CMD_NEED_NETDEV |
8287 WIPHY_VENDOR_CMD_NEED_RUNNING,
8288 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8289 },
8290 {
8291 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8292 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8293 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8294 WIPHY_VENDOR_CMD_NEED_NETDEV,
8295 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8296 },
8297 {
8298 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8299 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8300 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8301 WIPHY_VENDOR_CMD_NEED_NETDEV,
8302 .doit = wlan_hdd_cfg80211_wifi_logger_start
8303 },
8304 {
8305 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8306 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8307 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8308 WIPHY_VENDOR_CMD_NEED_NETDEV,
8309 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8310 },
8311 {
8312 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8313 .info.subcmd =
8314 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8315 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8316 WIPHY_VENDOR_CMD_NEED_NETDEV |
8317 WIPHY_VENDOR_CMD_NEED_RUNNING,
8318 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8319 },
8320 {
8321 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8322 .info.subcmd =
8323 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8324 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8325 WIPHY_VENDOR_CMD_NEED_NETDEV |
8326 WIPHY_VENDOR_CMD_NEED_RUNNING,
8327 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8328 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008329#ifdef WLAN_FEATURE_TSF
8330 {
8331 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8332 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8333 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8334 WIPHY_VENDOR_CMD_NEED_NETDEV |
8335 WIPHY_VENDOR_CMD_NEED_RUNNING,
8336 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8337 },
8338#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008339#ifdef FEATURE_WLAN_TDLS
8340 {
8341 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8342 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8343 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8344 WIPHY_VENDOR_CMD_NEED_NETDEV |
8345 WIPHY_VENDOR_CMD_NEED_RUNNING,
8346 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8347 },
8348#endif
8349#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8350 {
8351 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8352 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8353 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8354 WIPHY_VENDOR_CMD_NEED_NETDEV |
8355 WIPHY_VENDOR_CMD_NEED_RUNNING,
8356 .doit = wlan_hdd_cfg80211_offloaded_packets
8357 },
8358#endif
8359 {
8360 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8361 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8362 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8363 WIPHY_VENDOR_CMD_NEED_NETDEV |
8364 WIPHY_VENDOR_CMD_NEED_RUNNING,
8365 .doit = wlan_hdd_cfg80211_monitor_rssi
8366 },
8367 {
8368 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308369 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8370 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8371 WIPHY_VENDOR_CMD_NEED_NETDEV |
8372 WIPHY_VENDOR_CMD_NEED_RUNNING,
8373 .doit = wlan_hdd_cfg80211_set_ns_offload
8374 },
8375 {
8376 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008377 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8378 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8379 WIPHY_VENDOR_CMD_NEED_NETDEV |
8380 WIPHY_VENDOR_CMD_NEED_RUNNING,
8381 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8382 },
8383#ifdef WLAN_FEATURE_MEMDUMP
8384 {
8385 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8386 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8387 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8388 WIPHY_VENDOR_CMD_NEED_NETDEV |
8389 WIPHY_VENDOR_CMD_NEED_RUNNING,
8390 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8391 },
8392#endif /* WLAN_FEATURE_MEMDUMP */
8393 {
8394 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8395 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8396 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8397 WIPHY_VENDOR_CMD_NEED_NETDEV |
8398 WIPHY_VENDOR_CMD_NEED_RUNNING,
8399 .doit = wlan_hdd_cfg80211_vendor_scan
8400 },
8401
8402 /* OCB commands */
8403 {
8404 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8405 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8406 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8407 WIPHY_VENDOR_CMD_NEED_NETDEV |
8408 WIPHY_VENDOR_CMD_NEED_RUNNING,
8409 .doit = wlan_hdd_cfg80211_ocb_set_config
8410 },
8411 {
8412 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8413 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8414 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8415 WIPHY_VENDOR_CMD_NEED_NETDEV |
8416 WIPHY_VENDOR_CMD_NEED_RUNNING,
8417 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8418 },
8419 {
8420 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8421 .info.subcmd =
8422 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8423 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8424 WIPHY_VENDOR_CMD_NEED_NETDEV |
8425 WIPHY_VENDOR_CMD_NEED_RUNNING,
8426 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8427 },
8428 {
8429 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8430 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8431 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8432 WIPHY_VENDOR_CMD_NEED_NETDEV |
8433 WIPHY_VENDOR_CMD_NEED_RUNNING,
8434 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8435 },
8436 {
8437 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8438 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8439 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8440 WIPHY_VENDOR_CMD_NEED_NETDEV |
8441 WIPHY_VENDOR_CMD_NEED_RUNNING,
8442 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8443 },
8444 {
8445 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8446 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8447 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8448 WIPHY_VENDOR_CMD_NEED_NETDEV |
8449 WIPHY_VENDOR_CMD_NEED_RUNNING,
8450 .doit = wlan_hdd_cfg80211_dcc_get_stats
8451 },
8452 {
8453 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8454 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8455 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8456 WIPHY_VENDOR_CMD_NEED_NETDEV |
8457 WIPHY_VENDOR_CMD_NEED_RUNNING,
8458 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8459 },
8460 {
8461 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8462 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8464 WIPHY_VENDOR_CMD_NEED_NETDEV |
8465 WIPHY_VENDOR_CMD_NEED_RUNNING,
8466 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8467 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308468 {
8469 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8470 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8471 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8472 WIPHY_VENDOR_CMD_NEED_NETDEV |
8473 WIPHY_VENDOR_CMD_NEED_RUNNING,
8474 .doit = wlan_hdd_cfg80211_get_link_properties
8475 },
Peng Xu278d0122015-09-24 16:34:17 -07008476 {
Peng Xud2220962016-07-11 17:59:17 -07008477 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008478 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8479 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8480 WIPHY_VENDOR_CMD_NEED_NETDEV |
8481 WIPHY_VENDOR_CMD_NEED_RUNNING,
8482 .doit = wlan_hdd_cfg80211_set_ota_test
8483 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008484#ifdef FEATURE_LFR_SUBNET_DETECTION
8485 {
8486 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8487 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8488 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8489 WIPHY_VENDOR_CMD_NEED_NETDEV |
8490 WIPHY_VENDOR_CMD_NEED_RUNNING,
8491 .doit = wlan_hdd_cfg80211_set_gateway_params
8492 },
8493#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008494 {
Peng Xud2220962016-07-11 17:59:17 -07008495 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008496 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8497 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8498 WIPHY_VENDOR_CMD_NEED_NETDEV |
8499 WIPHY_VENDOR_CMD_NEED_RUNNING,
8500 .doit = wlan_hdd_cfg80211_txpower_scale
8501 },
8502 {
8503 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8504 .info.subcmd =
8505 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8506 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8507 WIPHY_VENDOR_CMD_NEED_NETDEV |
8508 WIPHY_VENDOR_CMD_NEED_RUNNING,
8509 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8510 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308511 {
8512 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8513 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8514 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8515 WIPHY_VENDOR_CMD_NEED_NETDEV |
8516 WIPHY_VENDOR_CMD_NEED_RUNNING,
8517 .doit = wlan_hdd_cfg80211_bpf_offload
8518 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308519 {
8520 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308521 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8522 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8523 WIPHY_VENDOR_CMD_NEED_NETDEV |
8524 WIPHY_VENDOR_CMD_NEED_RUNNING,
8525 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8526 },
8527 {
8528 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308529 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8530 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8531 WIPHY_VENDOR_CMD_NEED_NETDEV |
8532 WIPHY_VENDOR_CMD_NEED_RUNNING,
8533 .doit = wlan_hdd_cfg80211_sta_roam_policy
8534 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308535#ifdef FEATURE_WLAN_CH_AVOID
8536 {
8537 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8538 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8539 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8540 WIPHY_VENDOR_CMD_NEED_NETDEV |
8541 WIPHY_VENDOR_CMD_NEED_RUNNING,
8542 .doit = wlan_hdd_cfg80211_avoid_freq
8543 },
8544#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308545 {
8546 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308547 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8548 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8549 WIPHY_VENDOR_CMD_NEED_NETDEV |
8550 WIPHY_VENDOR_CMD_NEED_RUNNING,
8551 .doit = wlan_hdd_cfg80211_sap_configuration_set
8552 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008553 {
Peng Xu4225c152016-07-14 21:18:14 -07008554 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008555 .info.subcmd =
8556 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8557 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8558 WIPHY_VENDOR_CMD_NEED_NETDEV |
8559 WIPHY_VENDOR_CMD_NEED_RUNNING,
8560 .doit = wlan_hdd_cfg80211_p2p_lo_start
8561 },
8562 {
8563 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8564 .info.subcmd =
8565 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8566 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8567 WIPHY_VENDOR_CMD_NEED_NETDEV |
8568 WIPHY_VENDOR_CMD_NEED_RUNNING,
8569 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8570 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308571 {
8572 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8573 .info.subcmd =
8574 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8575 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8576 WIPHY_VENDOR_CMD_NEED_NETDEV |
8577 WIPHY_VENDOR_CMD_NEED_RUNNING,
8578 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8579 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008580#ifdef WLAN_FEATURE_NAN_DATAPATH
8581 {
8582 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8583 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8584 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8585 WIPHY_VENDOR_CMD_NEED_NETDEV |
8586 WIPHY_VENDOR_CMD_NEED_RUNNING,
8587 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8588 },
8589#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308590 {
8591 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8592 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8593 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8594 WIPHY_VENDOR_CMD_NEED_NETDEV |
8595 WIPHY_VENDOR_CMD_NEED_RUNNING,
8596 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8597 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308598 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308599 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8600 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8601 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8602 WIPHY_VENDOR_CMD_NEED_NETDEV |
8603 WIPHY_VENDOR_CMD_NEED_RUNNING,
8604 .doit = wlan_hdd_cfg80211_get_bus_size
8605 },
8606 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308607 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8608 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8609 WIPHY_VENDOR_CMD_NEED_NETDEV |
8610 WIPHY_VENDOR_CMD_NEED_RUNNING,
8611 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308612 },
8613 {
8614 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8615 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8616 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8617 WIPHY_VENDOR_CMD_NEED_NETDEV |
8618 WIPHY_VENDOR_CMD_NEED_RUNNING,
8619 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308620 },
8621#ifdef WLAN_FEATURE_DISA
8622 {
8623 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8624 .info.subcmd =
8625 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8626 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8627 WIPHY_VENDOR_CMD_NEED_NETDEV |
8628 WIPHY_VENDOR_CMD_NEED_RUNNING,
8629 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8630 },
8631#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07008632#ifdef FEATURE_WLAN_TDLS
8633 {
8634 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8635 .info.subcmd =
8636 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
8637 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8638 WIPHY_VENDOR_CMD_NEED_NETDEV |
8639 WIPHY_VENDOR_CMD_NEED_RUNNING,
8640 .doit = wlan_hdd_cfg80211_configure_tdls_mode
8641 }
8642#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008643};
8644
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008645/**
8646 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8647 * @priv_size: Size of the hdd context.
8648 *
8649 * Allocate wiphy context and hdd context.
8650 *
8651 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008652 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008653hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008654{
8655 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008656 hdd_context_t *hdd_ctx;
8657
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008658 ENTER();
8659
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008660 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8661
8662 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008663 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008664 return NULL;
8665 }
8666
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008667 hdd_ctx = wiphy_priv(wiphy);
8668
8669 hdd_ctx->wiphy = wiphy;
8670
8671 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008672}
8673
8674/*
8675 * FUNCTION: wlan_hdd_cfg80211_update_band
8676 * This function is called from the supplicant through a
8677 * private ioctl to change the band value
8678 */
8679int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8680{
8681 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008682 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008683
8684 ENTER();
8685
Dustin Browna30892e2016-10-12 17:28:36 -07008686 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008687
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008688 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008689 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008690
8691 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8692 struct ieee80211_supported_band *band = wiphy->bands[i];
8693
8694 channelEnabledState =
8695 cds_get_channel_state(band->channels[j].
8696 hw_value);
8697
Dustin Browna30892e2016-10-12 17:28:36 -07008698 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008699 /* 5G only */
8700#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8701 /* Enable Social channels for P2P */
8702 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8703 (band->channels[j].center_freq)
8704 && CHANNEL_STATE_ENABLE ==
8705 channelEnabledState)
8706 band->channels[j].flags &=
8707 ~IEEE80211_CHAN_DISABLED;
8708 else
8709#endif
8710 band->channels[j].flags |=
8711 IEEE80211_CHAN_DISABLED;
8712 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008713 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008714 eCSR_BAND_24 == eBand) {
8715 /* 2G only */
8716 band->channels[j].flags |=
8717 IEEE80211_CHAN_DISABLED;
8718 continue;
8719 }
8720
Amar Singhal6842e8f2016-02-23 16:30:32 -08008721 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008722 band->channels[j].flags &=
8723 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008724 }
8725 }
8726 return 0;
8727}
8728
8729/*
8730 * FUNCTION: wlan_hdd_cfg80211_init
8731 * This function is called by hdd_wlan_startup()
8732 * during initialization.
8733 * This function is used to initialize and register wiphy structure.
8734 */
8735int wlan_hdd_cfg80211_init(struct device *dev,
8736 struct wiphy *wiphy, struct hdd_config *pCfg)
8737{
8738 int i, j;
8739 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8740
8741 ENTER();
8742
8743 /* Now bind the underlying wlan device with wiphy */
8744 set_wiphy_dev(wiphy, dev);
8745
8746 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8747
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008748#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8749 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008750 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008751#else
8752 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008753 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008754#endif
8755
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008756 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8757 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8758 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8759#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8760 | WIPHY_FLAG_4ADDR_STATION
8761#endif
8762 | WIPHY_FLAG_OFFCHAN_TX;
8763
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008764#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8765 wiphy->wowlan = &wowlan_support_cfg80211_init;
8766#else
8767 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8768 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8769 wiphy->wowlan.pattern_min_len = 1;
8770 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8771#endif
8772
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008773 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008774#ifdef FEATURE_WLAN_ESE
8775 || pCfg->isEseIniFeatureEnabled
8776#endif
8777 ) {
8778 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8779 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008780#ifdef FEATURE_WLAN_TDLS
8781 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8782 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8783#endif
8784
8785 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8786
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008787#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8788 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8789#endif
8790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008791#ifdef FEATURE_WLAN_SCAN_PNO
8792 if (pCfg->configPNOScanSupport) {
8793 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8794 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8795 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8796 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008797#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8798 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8799#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008800 }
8801#endif /*FEATURE_WLAN_SCAN_PNO */
8802
8803#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308804 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008805#endif
8806
8807 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8808 driver can still register regulatory callback and
8809 it will get regulatory settings in wiphy->band[], but
8810 driver need to determine what to do with both
8811 regulatory settings */
8812
8813 wiphy->reg_notifier = hdd_reg_notifier;
8814
8815#if defined QCA_WIFI_FTM
8816}
8817#endif
8818
8819 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8820
8821 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8822
8823 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8824
Arun Khandavallifae92942016-08-01 13:31:08 +05308825 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8826 | BIT(NL80211_IFTYPE_ADHOC)
8827 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8828 | BIT(NL80211_IFTYPE_P2P_GO)
8829 | BIT(NL80211_IFTYPE_AP)
8830 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008831
Arun Khandavallifae92942016-08-01 13:31:08 +05308832 if (pCfg->advertiseConcurrentOperation) {
8833 if (pCfg->enableMCC) {
8834 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008835
Arun Khandavallifae92942016-08-01 13:31:08 +05308836 for (i = 0;
8837 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8838 i++) {
8839 if (!pCfg->allowMCCGODiffBI)
8840 wlan_hdd_iface_combination[i].
8841 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008842 }
8843 }
8844 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308845 ARRAY_SIZE(wlan_hdd_iface_combination);
8846 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008847 }
8848
8849 /* Before registering we need to update the ht capabilitied based
8850 * on ini values*/
8851 if (!pCfg->ShortGI20MhzEnable) {
8852 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8853 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008854 }
8855
8856 if (!pCfg->ShortGI40MhzEnable) {
8857 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8858 }
8859
8860 if (!pCfg->nChannelBondingMode5GHz) {
8861 wlan_hdd_band_5_ghz.ht_cap.cap &=
8862 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8863 }
8864
Abhishek Singhf512bf32016-05-04 16:47:46 +05308865 /*
8866 * In case of static linked driver at the time of driver unload,
8867 * module exit doesn't happens. Module cleanup helps in cleaning
8868 * of static memory.
8869 * If driver load happens statically, at the time of driver unload,
8870 * wiphy flags don't get reset because of static memory.
8871 * It's better not to store channel in static memory.
8872 */
Dustin Browna30892e2016-10-12 17:28:36 -07008873 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
8874 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308875 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008876 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308877 hdd_err("Not enough memory to allocate channels");
8878 return -ENOMEM;
8879 }
Dustin Browna30892e2016-10-12 17:28:36 -07008880 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308881 &hdd_channels_2_4_ghz[0],
8882 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308883 if ((hdd_is_5g_supported(pHddCtx)) &&
8884 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8885 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8886 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8887 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -07008888 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
8889 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308890 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008891 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308892 hdd_err("Not enough memory to allocate channels");
8893 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -07008894 bands[NL80211_BAND_2GHZ]->channels);
8895 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308896 return -ENOMEM;
8897 }
Dustin Browna30892e2016-10-12 17:28:36 -07008898 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308899 &hdd_channels_5_ghz[0],
8900 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008901 }
8902
Dustin Browna30892e2016-10-12 17:28:36 -07008903 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008904
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008905 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008906 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008907
8908 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8909 struct ieee80211_supported_band *band = wiphy->bands[i];
8910
Dustin Browna30892e2016-10-12 17:28:36 -07008911 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008912 eCSR_BAND_5G == pCfg->nBandCapability) {
8913 /* 5G only */
8914#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8915 /* Enable social channels for P2P */
8916 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8917 (band->channels[j].center_freq))
8918 band->channels[j].flags &=
8919 ~IEEE80211_CHAN_DISABLED;
8920 else
8921#endif
8922 band->channels[j].flags |=
8923 IEEE80211_CHAN_DISABLED;
8924 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008925 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008926 eCSR_BAND_24 == pCfg->nBandCapability) {
8927 /* 2G only */
8928 band->channels[j].flags |=
8929 IEEE80211_CHAN_DISABLED;
8930 continue;
8931 }
8932 }
8933 }
8934 /*Initialise the supported cipher suite details */
8935 wiphy->cipher_suites = hdd_cipher_suites;
8936 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8937
8938 /*signal strength in mBm (100*dBm) */
8939 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8940 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8941
Anurag Chouhan6d760662016-02-20 16:05:43 +05308942 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008943 wiphy->n_vendor_commands =
8944 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8945 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8946
8947 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8948 wiphy->n_vendor_events =
8949 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8950 }
8951
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008952 if (pCfg->enableDFSMasterCap) {
8953 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8954 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008955
8956 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8957
8958#ifdef QCA_HT_2040_COEX
8959 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8960#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +05308961 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308962 hdd_add_channel_switch_support(&wiphy->flags);
8963
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008964 EXIT();
8965 return 0;
8966}
8967
Abhishek Singhf512bf32016-05-04 16:47:46 +05308968/**
Yingying Tang80e15f32016-09-27 18:23:01 +08008969 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
8970 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +05308971 *
8972 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308973 * memory allocated in wlan_hdd_cfg80211_init also
8974 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308975 *
8976 * Return: void
8977 */
8978void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8979{
8980 int i;
8981
Dustin Browna30892e2016-10-12 17:28:36 -07008982 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308983 if (NULL != wiphy->bands[i] &&
8984 (NULL != wiphy->bands[i]->channels)) {
8985 qdf_mem_free(wiphy->bands[i]->channels);
8986 wiphy->bands[i]->channels = NULL;
8987 }
8988 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308989 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05308990}
8991
Yingying Tang80e15f32016-09-27 18:23:01 +08008992/**
8993 * wlan_hdd_update_band_cap() - update capabilities for supported bands
8994 * @hdd_ctx: HDD context
8995 *
8996 * this function will update capabilities for supported bands
8997 *
8998 * Return: void
8999 */
9000static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
9001{
9002 uint32_t val32;
9003 uint16_t val16;
9004 tSirMacHTCapabilityInfo *ht_cap_info;
9005 QDF_STATUS status;
9006
9007 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
9008 if (QDF_STATUS_SUCCESS != status) {
9009 hdd_err("could not get HT capability info");
9010 val32 = 0;
9011 }
9012 val16 = (uint16_t)val32;
9013 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
9014
9015 if (ht_cap_info->txSTBC == true) {
9016 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
9017 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
9018 IEEE80211_HT_CAP_TX_STBC;
9019 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
9020 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
9021 IEEE80211_HT_CAP_TX_STBC;
9022 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009023
9024 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
9025 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
9026 vht_cap.vht_supported = 0;
9027 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
9028 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
9029 vht_cap.vht_supported = 0;
9030 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
9031 }
Yingying Tang80e15f32016-09-27 18:23:01 +08009032}
9033
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009034/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309035 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009036 * initialization. In wlan_hdd_cfg80211_init, only the
9037 * default values will be initialized. The final initialization
9038 * of all required members can be done here.
9039 */
Yingying Tang80e15f32016-09-27 18:23:01 +08009040void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009041{
Yingying Tang80e15f32016-09-27 18:23:01 +08009042 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
9043
9044 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009045}
9046
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009047/**
9048 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
9049 * @cfg: hdd cfg
9050 *
9051 * this function update 11n mode in hdd cfg
9052 *
9053 * Return: void
9054 */
9055void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
9056{
9057 if (sme_is_feature_supported_by_fw(DOT11AC)) {
9058 hdd_notice("support 11ac");
9059 } else {
9060 hdd_notice("not support 11ac");
9061 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
9062 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
9063 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
9064 cfg->sap_p2p_11ac_override = 0;
9065 }
9066 }
9067}
9068
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009069/* In this function we are registering wiphy. */
9070int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
9071{
9072 ENTER();
9073 /* Register our wiphy dev with cfg80211 */
9074 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009075 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009076 return -EIO;
9077 }
9078
9079 EXIT();
9080 return 0;
9081}
9082
9083/*
9084 HDD function to update wiphy capability based on target offload status.
9085
9086 wlan_hdd_cfg80211_init() does initialization of all wiphy related
9087 capability even before downloading firmware to the target. In discrete
9088 case, host will get know certain offload capability (say sched_scan
9089 caps) only after downloading firmware to the target and target boots up.
9090 This function is used to override setting done in wlan_hdd_cfg80211_init()
9091 based on target capability.
9092 */
9093void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
9094{
9095#ifdef FEATURE_WLAN_SCAN_PNO
9096 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9097 struct hdd_config *pCfg = pHddCtx->config;
9098
9099 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
9100 * control comes here. Here just we need to clear it if firmware doesn't
9101 * have PNO support. */
9102 if (!pCfg->PnoOffload) {
9103 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9104 wiphy->max_sched_scan_ssids = 0;
9105 wiphy->max_match_sets = 0;
9106 wiphy->max_sched_scan_ie_len = 0;
9107 }
9108#endif
9109}
9110
9111/* This function registers for all frame which supplicant is interested in */
9112void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
9113{
9114 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9115 /* Register for all P2P action, public action etc frames */
9116 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9117
9118 ENTER();
9119
Abhishek Singh7996eb72015-12-30 17:24:02 +05309120 /* Register frame indication call back */
9121 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
9122
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05309123 /* Register for p2p ack indication */
9124 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
9125
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009126 /* Right now we are registering these frame when driver is getting
9127 initialized. Once we will move to 2.6.37 kernel, in which we have
9128 frame register ops, we will move this code as a part of that */
9129 /* GAS Initial Request */
9130 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9131 (uint8_t *) GAS_INITIAL_REQ,
9132 GAS_INITIAL_REQ_SIZE);
9133
9134 /* GAS Initial Response */
9135 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9136 (uint8_t *) GAS_INITIAL_RSP,
9137 GAS_INITIAL_RSP_SIZE);
9138
9139 /* GAS Comeback Request */
9140 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9141 (uint8_t *) GAS_COMEBACK_REQ,
9142 GAS_COMEBACK_REQ_SIZE);
9143
9144 /* GAS Comeback Response */
9145 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9146 (uint8_t *) GAS_COMEBACK_RSP,
9147 GAS_COMEBACK_RSP_SIZE);
9148
9149 /* P2P Public Action */
9150 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9151 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9152 P2P_PUBLIC_ACTION_FRAME_SIZE);
9153
9154 /* P2P Action */
9155 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9156 (uint8_t *) P2P_ACTION_FRAME,
9157 P2P_ACTION_FRAME_SIZE);
9158
9159 /* WNM BSS Transition Request frame */
9160 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9161 (uint8_t *) WNM_BSS_ACTION_FRAME,
9162 WNM_BSS_ACTION_FRAME_SIZE);
9163
9164 /* WNM-Notification */
9165 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9166 (uint8_t *) WNM_NOTIFICATION_FRAME,
9167 WNM_NOTIFICATION_FRAME_SIZE);
9168}
9169
9170void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9171{
9172 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9173 /* Register for all P2P action, public action etc frames */
9174 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9175
9176 ENTER();
9177
9178 /* Right now we are registering these frame when driver is getting
9179 initialized. Once we will move to 2.6.37 kernel, in which we have
9180 frame register ops, we will move this code as a part of that */
9181 /* GAS Initial Request */
9182
9183 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9184 (uint8_t *) GAS_INITIAL_REQ,
9185 GAS_INITIAL_REQ_SIZE);
9186
9187 /* GAS Initial Response */
9188 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9189 (uint8_t *) GAS_INITIAL_RSP,
9190 GAS_INITIAL_RSP_SIZE);
9191
9192 /* GAS Comeback Request */
9193 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9194 (uint8_t *) GAS_COMEBACK_REQ,
9195 GAS_COMEBACK_REQ_SIZE);
9196
9197 /* GAS Comeback Response */
9198 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9199 (uint8_t *) GAS_COMEBACK_RSP,
9200 GAS_COMEBACK_RSP_SIZE);
9201
9202 /* P2P Public Action */
9203 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9204 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9205 P2P_PUBLIC_ACTION_FRAME_SIZE);
9206
9207 /* P2P Action */
9208 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9209 (uint8_t *) P2P_ACTION_FRAME,
9210 P2P_ACTION_FRAME_SIZE);
9211
9212 /* WNM-Notification */
9213 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9214 (uint8_t *) WNM_NOTIFICATION_FRAME,
9215 WNM_NOTIFICATION_FRAME_SIZE);
9216}
9217
9218#ifdef FEATURE_WLAN_WAPI
9219void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9220 const uint8_t *mac_addr, const uint8_t *key,
9221 int key_Len)
9222{
9223 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9224 tCsrRoamSetKey setKey;
9225 bool isConnected = true;
9226 int status = 0;
9227 uint32_t roamId = 0xFF;
9228 uint8_t *pKeyPtr = NULL;
9229 int n = 0;
9230
Jeff Johnson46b40792016-06-29 14:03:14 -07009231 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009232 hdd_device_mode_to_string(pAdapter->device_mode),
9233 pAdapter->device_mode);
9234
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309235 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009236 setKey.keyId = key_index; /* Store Key ID */
9237 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9238 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9239 setKey.paeRole = 0; /* the PAE role */
9240 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309241 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009242 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309243 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009244 }
9245 setKey.keyLength = key_Len;
9246 pKeyPtr = setKey.Key;
9247 memcpy(pKeyPtr, key, key_Len);
9248
Jeff Johnson46b40792016-06-29 14:03:14 -07009249 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009250 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009251 hdd_notice("WAPI KEY Data[%d]:%02x ",
9252 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009253
9254 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9255 if (isConnected) {
9256 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9257 pAdapter->sessionId, &setKey, &roamId);
9258 }
9259 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009260 hdd_err("sme_roam_set_key returned ERROR status= %d",
9261 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009262 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9263 }
9264}
9265#endif /* FEATURE_WLAN_WAPI */
9266
9267uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9268 uint8_t eid)
9269{
9270 int left = length;
9271 uint8_t *ptr = (uint8_t *)ies_ptr;
9272 uint8_t elem_id, elem_len;
9273
9274 while (left >= 2) {
9275 elem_id = ptr[0];
9276 elem_len = ptr[1];
9277 left -= 2;
9278 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009279 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009280 eid, elem_len, left);
9281 return NULL;
9282 }
9283 if (elem_id == eid) {
9284 return ptr;
9285 }
9286
9287 left -= elem_len;
9288 ptr += (elem_len + 2);
9289 }
9290 return NULL;
9291}
9292
9293/*
9294 * FUNCTION: wlan_hdd_validate_operation_channel
9295 * called by wlan_hdd_cfg80211_start_bss() and
9296 * wlan_hdd_set_channel()
9297 * This function validates whether given channel is part of valid
9298 * channel list.
9299 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309300QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009301 int channel)
9302{
9303
9304 uint32_t num_ch = 0;
9305 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9306 u32 indx = 0;
9307 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9308 uint8_t fValidChannel = false, count = 0;
9309 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9310
9311 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9312
9313 if (hdd_pConfig_ini->sapAllowAllChannel) {
9314 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009315 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009316 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009317 fValidChannel = true;
9318 break;
9319 }
9320 }
9321 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009322 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309323 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009324 }
9325 } else {
9326 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9327 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009328 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309329 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009330 }
9331 for (indx = 0; indx < num_ch; indx++) {
9332 if (channel == valid_ch[indx]) {
9333 break;
9334 }
9335 }
9336
9337 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009338 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309339 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009340 }
9341 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309342 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009343
9344}
9345
9346#ifdef DHCP_SERVER_OFFLOAD
9347static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9348{
9349 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9350 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9351 uint8_t numEntries = 0;
9352 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9353 uint8_t num;
9354 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309355 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009356 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009357 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009358 return;
9359 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009360 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9361 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9362 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9363 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9364 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9365 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009366 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009367 goto end;
9368 }
9369 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009370 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009371 goto end;
9372 }
9373 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009374 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009375 goto end;
9376 }
9377 for (num = 0; num < numEntries; num++) {
9378 temp = srv_ip[num];
9379 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9380 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309381 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009382 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009383 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009384 goto end;
9385 }
Jeff Johnson77848112016-06-29 14:52:06 -07009386 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009387end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309388 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009389 return;
9390}
9391#endif /* DHCP_SERVER_OFFLOAD */
9392
9393static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9394 struct net_device *dev,
9395 struct bss_parameters *params)
9396{
9397 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9398 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9399 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309400 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009401
9402 ENTER();
9403
Anurag Chouhan6d760662016-02-20 16:05:43 +05309404 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009405 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009406 return -EINVAL;
9407 }
9408
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309409 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9410 hdd_err("invalid session id: %d", pAdapter->sessionId);
9411 return -EINVAL;
9412 }
9413
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309414 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009415 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9416 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009417 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009418 hdd_device_mode_to_string(pAdapter->device_mode),
9419 pAdapter->device_mode, params->ap_isolate);
9420
9421 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9422 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309423 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009424 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009425
Krunal Sonib4326f22016-03-10 13:05:51 -08009426 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9427 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009428 return -EOPNOTSUPP;
9429 }
9430
9431 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9432 * want to update this parameter */
9433 if (-1 != params->ap_isolate) {
9434 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9435 !!params->ap_isolate;
9436
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309437 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009438 pAdapter->sessionId,
9439 pAdapter->sessionCtx.
9440 ap.
9441 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309442 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009443 ret = -EINVAL;
9444 }
9445 }
9446
9447 EXIT();
9448 return ret;
9449}
9450
Krunal Soni8c37e322016-02-03 16:08:37 -08009451/**
9452 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9453 * @ndev: pointer to net device provided by supplicant
9454 * @type: type of the interface, upper layer wanted to change
9455 *
9456 * Upper layer provides the new interface mode that needs to be changed
9457 * for given net device
9458 *
9459 * Return: success or failure in terms of integer value
9460 */
9461static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009462 enum nl80211_iftype type)
9463{
Krunal Soni8c37e322016-02-03 16:08:37 -08009464 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9465 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9466 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009467 hdd_wext_state_t *wext;
9468 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309469 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009470
9471 ENTER();
9472
Krunal Soni8c37e322016-02-03 16:08:37 -08009473 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009474 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009475 return 0;
9476 }
9477
9478 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009479 hdd_stop_adapter(hdd_ctx, adapter, true);
9480 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009481 wdev->iftype = type;
9482 /*Check for sub-string p2p to confirm its a p2p interface */
9483 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009484 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009485 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009486 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009487 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009488 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009489 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009490 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009491 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009492 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009493 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009494 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9495 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009496 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9497 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009498 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009499 adapter->scan_info.scanAddIE.length;
9500 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309501 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009502 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9503 wext->roamProfile.phyMode =
9504 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9505 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009506 EXIT();
9507 return status;
9508}
9509
9510static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9511 struct net_device *dev,
9512 struct bss_parameters *params)
9513{
9514 int ret;
9515
9516 cds_ssr_protect(__func__);
9517 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9518 cds_ssr_unprotect(__func__);
9519
9520 return ret;
9521}
9522
9523/* FUNCTION: wlan_hdd_change_country_code_cd
9524 * to wait for contry code completion
9525 */
9526void *wlan_hdd_change_country_code_cb(void *pAdapter)
9527{
9528 hdd_adapter_t *call_back_pAdapter = pAdapter;
9529 complete(&call_back_pAdapter->change_country_code);
9530 return NULL;
9531}
9532
Rajeev Kumar98edb772016-01-19 12:42:19 -08009533/**
9534 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9535 * @wiphy: Pointer to the wiphy structure
9536 * @ndev: Pointer to the net device
9537 * @type: Interface type
9538 * @flags: Flags for change interface
9539 * @params: Pointer to change interface parameters
9540 *
9541 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009542 */
9543static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9544 struct net_device *ndev,
9545 enum nl80211_iftype type,
9546 u32 *flags,
9547 struct vif_params *params)
9548{
9549 struct wireless_dev *wdev;
9550 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9551 hdd_context_t *pHddCtx;
9552 tCsrRoamProfile *pRoamProfile = NULL;
9553 eCsrRoamBssType LastBSSType;
9554 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309555 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009556 int status;
9557
9558 ENTER();
9559
Anurag Chouhan6d760662016-02-20 16:05:43 +05309560 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009561 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009562 return -EINVAL;
9563 }
9564
9565 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9566 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309567 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009568 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009569
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309570 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009571 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9572 pAdapter->sessionId, type));
9573
Jeff Johnson77848112016-06-29 14:52:06 -07009574 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009575 pAdapter->device_mode, type);
9576
Arun Khandavallifae92942016-08-01 13:31:08 +05309577 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9578 if (status) {
9579 hdd_err("Failed to start modules");
9580 return -EINVAL;
9581 }
9582
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009583 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009584 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9585 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009586 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009587 return -EINVAL;
9588 }
9589
9590 pConfig = pHddCtx->config;
9591 wdev = ndev->ieee80211_ptr;
9592
9593 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009594 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009595
9596 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9597
Krunal Sonib4326f22016-03-10 13:05:51 -08009598 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9599 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9600 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9601 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009602 hdd_wext_state_t *pWextState =
9603 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9604
9605 pRoamProfile = &pWextState->roamProfile;
9606 LastBSSType = pRoamProfile->BSSType;
9607
9608 switch (type) {
9609 case NL80211_IFTYPE_STATION:
9610 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009611 case NL80211_IFTYPE_ADHOC:
9612 if (type == NL80211_IFTYPE_ADHOC) {
9613 wlan_hdd_tdls_exit(pAdapter);
9614 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009615 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009616 }
9617 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9618 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309619 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009620 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309621 if (hdd_start_adapter(pAdapter)) {
9622 hdd_err("Failed to start adapter :%d",
9623 pAdapter->device_mode);
9624 return -EINVAL;
9625 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009626 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009627 case NL80211_IFTYPE_AP:
9628 case NL80211_IFTYPE_P2P_GO:
9629 {
Jeff Johnson77848112016-06-29 14:52:06 -07009630 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009631 (type ==
9632 NL80211_IFTYPE_AP) ? "SoftAP" :
9633 "P2pGo");
9634
9635 /* Cancel any remain on channel for GO mode */
9636 if (NL80211_IFTYPE_P2P_GO == type) {
9637 wlan_hdd_cancel_existing_remain_on_channel
9638 (pAdapter);
9639 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009640
Arun Khandavallifae92942016-08-01 13:31:08 +05309641 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009642 /* De-init the adapter */
9643 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9644 memset(&pAdapter->sessionCtx, 0,
9645 sizeof(pAdapter->sessionCtx));
9646 pAdapter->device_mode =
9647 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009648 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9649 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009650
9651 /*
9652 * Fw will take care incase of concurrency
9653 */
9654
Krunal Sonib4326f22016-03-10 13:05:51 -08009655 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009656 && (pConfig->apRandomBssidEnabled)) {
9657 /* To meet Android requirements create a randomized
9658 MAC address of the form 02:1A:11:Fx:xx:xx */
9659 get_random_bytes(&ndev->dev_addr[3], 3);
9660 ndev->dev_addr[0] = 0x02;
9661 ndev->dev_addr[1] = 0x1A;
9662 ndev->dev_addr[2] = 0x11;
9663 ndev->dev_addr[3] |= 0xF0;
9664 memcpy(pAdapter->macAddressCurrent.
9665 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309666 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009667 pr_info("wlan: Generated HotSpot BSSID "
9668 MAC_ADDRESS_STR "\n",
9669 MAC_ADDR_ARRAY(ndev->dev_addr));
9670 }
9671
9672 hdd_set_ap_ops(pAdapter->dev);
9673
Arun Khandavallifae92942016-08-01 13:31:08 +05309674 if (hdd_start_adapter(pAdapter)) {
9675 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009676 return -EINVAL;
9677 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009678 /* Interface type changed update in wiphy structure */
9679 if (wdev) {
9680 wdev->iftype = type;
9681 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009682 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009683 return -EINVAL;
9684 }
9685 goto done;
9686 }
9687
9688 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009689 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009690 type);
9691 return -EOPNOTSUPP;
9692 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009693 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9694 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009695 switch (type) {
9696 case NL80211_IFTYPE_STATION:
9697 case NL80211_IFTYPE_P2P_CLIENT:
9698 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009699 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9700 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309701 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009702 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309703 if (hdd_start_adapter(pAdapter)) {
9704 hdd_err("Failed to start adapter :%d",
9705 pAdapter->device_mode);
9706 return -EINVAL;
9707 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009708 goto done;
9709
9710 case NL80211_IFTYPE_AP:
9711 case NL80211_IFTYPE_P2P_GO:
9712 wdev->iftype = type;
9713 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009714 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009715 goto done;
9716
9717 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009718 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009719 type);
9720 return -EOPNOTSUPP;
9721 }
9722 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009723 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009724 pAdapter->device_mode);
9725 return -EOPNOTSUPP;
9726 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009727done:
9728 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009729 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009730
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009731 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009732
9733 EXIT();
9734 return 0;
9735}
9736
Rajeev Kumar98edb772016-01-19 12:42:19 -08009737/**
9738 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9739 * @wiphy: Pointer to the wiphy structure
9740 * @ndev: Pointer to the net device
9741 * @type: Interface type
9742 * @flags: Flags for change interface
9743 * @params: Pointer to change interface parameters
9744 *
9745 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009746 */
9747static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9748 struct net_device *ndev,
9749 enum nl80211_iftype type,
9750 u32 *flags,
9751 struct vif_params *params)
9752{
9753 int ret;
9754
9755 cds_ssr_protect(__func__);
9756 ret =
9757 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9758 cds_ssr_unprotect(__func__);
9759
9760 return ret;
9761}
9762
9763#ifdef FEATURE_WLAN_TDLS
9764static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9765 int index, uint8_t match)
9766{
9767 int i;
9768 for (i = 0; i < index; i++) {
9769 if (arr[i] == match)
9770 return true;
9771 }
9772 return false;
9773}
9774#endif
9775
9776/**
9777 * __wlan_hdd_change_station() - change station
9778 * @wiphy: Pointer to the wiphy structure
9779 * @dev: Pointer to the net device.
9780 * @mac: bssid
9781 * @params: Pointer to station parameters
9782 *
9783 * Return: 0 for success, error number on failure.
9784 */
9785#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9786static int __wlan_hdd_change_station(struct wiphy *wiphy,
9787 struct net_device *dev,
9788 const uint8_t *mac,
9789 struct station_parameters *params)
9790#else
9791static int __wlan_hdd_change_station(struct wiphy *wiphy,
9792 struct net_device *dev,
9793 uint8_t *mac,
9794 struct station_parameters *params)
9795#endif
9796{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309797 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009798 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9799 hdd_context_t *pHddCtx;
9800 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309801 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009802#ifdef FEATURE_WLAN_TDLS
9803 tCsrStaParams StaParams = { 0 };
9804 uint8_t isBufSta = 0;
9805 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309806 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009807#endif
9808 int ret;
9809
9810 ENTER();
9811
Anurag Chouhan6d760662016-02-20 16:05:43 +05309812 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009813 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009814 return -EINVAL;
9815 }
9816
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309817 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009818 TRACE_CODE_HDD_CHANGE_STATION,
9819 pAdapter->sessionId, params->listen_interval));
9820
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309821 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9822 hdd_err("invalid session id: %d", pAdapter->sessionId);
9823 return -EINVAL;
9824 }
9825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009826 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9827 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309828 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009829 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009830
9831 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9832
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309833 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009834
Krunal Sonib4326f22016-03-10 13:05:51 -08009835 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9836 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009837 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9838 status =
9839 hdd_softap_change_sta_state(pAdapter,
9840 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009841 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009842
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309843 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009844 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009845 return -EINVAL;
9846 }
9847 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009848 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9849 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009850#ifdef FEATURE_WLAN_TDLS
9851 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009852
9853 if (cds_is_sub_20_mhz_enabled()) {
9854 hdd_err("TDLS not allowed with sub 20 MHz");
9855 return -EINVAL;
9856 }
9857
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009858 StaParams.capability = params->capability;
9859 StaParams.uapsd_queues = params->uapsd_queues;
9860 StaParams.max_sp = params->max_sp;
9861
9862 /* Convert (first channel , number of channels) tuple to
9863 * the total list of channels. This goes with the assumption
9864 * that if the first channel is < 14, then the next channels
9865 * are an incremental of 1 else an incremental of 4 till the number
9866 * of channels.
9867 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009868 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009869 if (0 != params->supported_channels_len) {
9870 int i = 0, j = 0, k = 0, no_of_channels = 0;
9871 int num_unique_channels;
9872 int next;
9873 for (i = 0;
9874 i < params->supported_channels_len
9875 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9876 int wifi_chan_index;
9877 if (!wlan_hdd_is_duplicate_channel
9878 (StaParams.supported_channels, j,
9879 params->supported_channels[i])) {
9880 StaParams.
9881 supported_channels[j] =
9882 params->
9883 supported_channels[i];
9884 } else {
9885 continue;
9886 }
9887 wifi_chan_index =
9888 ((StaParams.supported_channels[j] <=
9889 HDD_CHANNEL_14) ? 1 : 4);
9890 no_of_channels =
9891 params->supported_channels[i + 1];
9892
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009893 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 -08009894 StaParams.
9895 supported_channels[j],
9896 wifi_chan_index,
9897 no_of_channels);
9898 for (k = 1; k <= no_of_channels &&
9899 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9900 k++) {
9901 next =
9902 StaParams.
9903 supported_channels[j] +
9904 wifi_chan_index;
9905 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9906 StaParams.
9907 supported_channels[j
9908 +
9909 1]
9910 = next;
9911 } else {
9912 continue;
9913 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009914 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009915 j + 1,
9916 StaParams.
9917 supported_channels[j +
9918 1]);
9919 j += 1;
9920 }
9921 }
9922 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009923 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009924 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009925 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009926 StaParams.
9927 supported_channels[i]);
9928 }
9929 if (MAX_CHANNEL < num_unique_channels)
9930 num_unique_channels = MAX_CHANNEL;
9931 StaParams.supported_channels_len =
9932 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009933 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009934 StaParams.supported_channels_len);
9935 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309936 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009937 params->supported_oper_classes,
9938 params->supported_oper_classes_len);
9939 StaParams.supported_oper_classes_len =
9940 params->supported_oper_classes_len;
9941
9942 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309943 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009944 params->ext_capab,
9945 sizeof(StaParams.extn_capability));
9946
9947 if (NULL != params->ht_capa) {
9948 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309949 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009950 sizeof(tSirHTCap));
9951 }
9952
9953 StaParams.supported_rates_len =
9954 params->supported_rates_len;
9955
9956 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9957 * The supported_rates array , for all the structures propogating till Add Sta
9958 * to the firmware has to be modified , if the supplicant (ieee80211) is
9959 * modified to send more rates.
9960 */
9961
9962 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
9963 */
9964 if (StaParams.supported_rates_len >
9965 SIR_MAC_MAX_SUPP_RATES)
9966 StaParams.supported_rates_len =
9967 SIR_MAC_MAX_SUPP_RATES;
9968
9969 if (0 != StaParams.supported_rates_len) {
9970 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309971 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009972 params->supported_rates,
9973 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009974 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009975 StaParams.supported_rates_len);
9976 for (i = 0; i < StaParams.supported_rates_len;
9977 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009978 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009979 StaParams.supported_rates[i]);
9980 }
9981
9982 if (NULL != params->vht_capa) {
9983 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309984 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009985 params->vht_capa,
9986 sizeof(tSirVHTCap));
9987 }
9988
9989 if (0 != params->ext_capab_len) {
9990 /*Define A Macro : TODO Sunil */
9991 if ((1 << 4) & StaParams.extn_capability[3]) {
9992 isBufSta = 1;
9993 }
9994 /* TDLS Channel Switching Support */
9995 if ((1 << 6) & StaParams.extn_capability[3]) {
9996 isOffChannelSupported = 1;
9997 }
9998 }
9999
Nitesh Shah99934ac2016-09-05 15:54:08 +053010000 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053010001 (params->ht_capa || params->vht_capa ||
10002 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053010003 is_qos_wmm_sta = true;
10004
10005 hdd_notice("%s: TDLS Peer is QOS capable"
10006 " is_qos_wmm_sta= %d HTcapPresent = %d",
10007 __func__, is_qos_wmm_sta,
10008 StaParams.htcap_present);
10009
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010010 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053010011 &StaParams,
10012 isBufSta,
10013 isOffChannelSupported,
10014 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010015 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010016 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010017 return -EINVAL;
10018 }
10019
10020 status =
10021 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
10022 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010023 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010024 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010025 return -EINVAL;
10026 }
10027 }
10028#endif
10029 }
10030 EXIT();
10031 return ret;
10032}
10033
10034/**
10035 * wlan_hdd_change_station() - cfg80211 change station handler function
10036 * @wiphy: Pointer to the wiphy structure
10037 * @dev: Pointer to the net device.
10038 * @mac: bssid
10039 * @params: Pointer to station parameters
10040 *
10041 * This is the cfg80211 change station handler function which invokes
10042 * the internal function @__wlan_hdd_change_station with
10043 * SSR protection.
10044 *
10045 * Return: 0 for success, error number on failure.
10046 */
10047#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
10048static int wlan_hdd_change_station(struct wiphy *wiphy,
10049 struct net_device *dev,
10050 const u8 *mac,
10051 struct station_parameters *params)
10052#else
10053static int wlan_hdd_change_station(struct wiphy *wiphy,
10054 struct net_device *dev,
10055 u8 *mac,
10056 struct station_parameters *params)
10057#endif
10058{
10059 int ret;
10060
10061 cds_ssr_protect(__func__);
10062 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
10063 cds_ssr_unprotect(__func__);
10064
10065 return ret;
10066}
10067
10068/*
10069 * FUNCTION: __wlan_hdd_cfg80211_add_key
10070 * This function is used to initialize the key information
10071 */
10072static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10073 struct net_device *ndev,
10074 u8 key_index, bool pairwise,
10075 const u8 *mac_addr,
10076 struct key_params *params)
10077{
10078 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10079 tCsrRoamSetKey setKey;
10080 int status;
10081 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010082 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010083 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010084 hdd_context_t *pHddCtx;
10085 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10086
10087 ENTER();
10088
Anurag Chouhan6d760662016-02-20 16:05:43 +053010089 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010090 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010091 return -EINVAL;
10092 }
10093
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010094 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10095 hdd_err("invalid session id: %d", pAdapter->sessionId);
10096 return -EINVAL;
10097 }
10098
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010099 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010100 TRACE_CODE_HDD_CFG80211_ADD_KEY,
10101 pAdapter->sessionId, params->key_len));
10102 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10103 status = wlan_hdd_validate_context(pHddCtx);
10104
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010105 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010106 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010107
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010108 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010109 hdd_device_mode_to_string(pAdapter->device_mode),
10110 pAdapter->device_mode);
10111
10112 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010113 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010114
10115 return -EINVAL;
10116 }
10117
10118 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010119 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010120
10121 return -EINVAL;
10122 }
10123
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010124 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010125
10126 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010127 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010128 setKey.keyId = key_index;
10129 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010130 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010131
10132 switch (params->cipher) {
10133 case WLAN_CIPHER_SUITE_WEP40:
10134 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10135 break;
10136
10137 case WLAN_CIPHER_SUITE_WEP104:
10138 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
10139 break;
10140
10141 case WLAN_CIPHER_SUITE_TKIP:
10142 {
10143 u8 *pKey = &setKey.Key[0];
10144 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
10145
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010146 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010147
10148 /*Supplicant sends the 32bytes key in this order
10149
10150 |--------------|----------|----------|
10151 | Tk1 |TX-MIC | RX Mic |
10152 |||--------------|----------|----------|
10153 <---16bytes---><--8bytes--><--8bytes-->
10154
10155 */
10156 /*Sme expects the 32 bytes key to be in the below order
10157
10158 |--------------|----------|----------|
10159 | Tk1 |RX-MIC | TX Mic |
10160 |||--------------|----------|----------|
10161 <---16bytes---><--8bytes--><--8bytes-->
10162 */
10163 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010164 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010165
10166 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010167 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010168
10169 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010170 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010171
10172 break;
10173 }
10174
10175 case WLAN_CIPHER_SUITE_CCMP:
10176 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10177 break;
10178
10179#ifdef FEATURE_WLAN_WAPI
10180 case WLAN_CIPHER_SUITE_SMS4:
10181 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010182 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010183 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10184 mac_addr, params->key,
10185 params->key_len);
10186 return 0;
10187 }
10188#endif
10189
10190#ifdef FEATURE_WLAN_ESE
10191 case WLAN_CIPHER_SUITE_KRK:
10192 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10193 break;
10194#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10195 case WLAN_CIPHER_SUITE_BTK:
10196 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10197 break;
10198#endif
10199#endif
10200
10201#ifdef WLAN_FEATURE_11W
10202 case WLAN_CIPHER_SUITE_AES_CMAC:
10203 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10204 break;
10205#endif
10206
10207 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010208 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010209 return -EOPNOTSUPP;
10210 }
10211
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010212 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010213
10214 if (!pairwise) {
10215 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010216 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010217 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010218 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010219 } else {
10220 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010221 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010222 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010223 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010224 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010225 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010226 /* if a key is already installed, block all subsequent ones */
10227 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010228 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010229 return 0;
10230 }
10231
10232 setKey.keyDirection = eSIR_TX_RX;
10233 /*Set the group key */
10234 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10235 pAdapter->sessionId, &setKey, &roamId);
10236
10237 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010238 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010239 return -EINVAL;
10240 }
10241 /*Save the keys here and call sme_roam_set_key for setting
10242 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010243 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010244 &setKey, sizeof(tCsrRoamSetKey));
10245
10246 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10247 return status;
10248 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010249 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10250 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010251 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10252 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010253 status = wlansap_set_key_sta(
10254 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010255 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010256 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010257 __LINE__, status);
10258 }
10259 }
10260
10261 /* Save the key in ap ctx for use on START_BASS and restart */
10262 if (pairwise ||
10263 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10264 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010265 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010266 sizeof(tCsrRoamSetKey));
10267 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010268 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010269 sizeof(tCsrRoamSetKey));
10270
Krunal Sonib4326f22016-03-10 13:05:51 -080010271 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10272 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010273 hdd_wext_state_t *pWextState =
10274 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10275 hdd_station_ctx_t *pHddStaCtx =
10276 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10277
10278 if (!pairwise) {
10279 /* set group key */
10280 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010281 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010282 __func__, __LINE__);
10283 hdd_perform_roam_set_key_complete(pAdapter);
10284 }
10285 }
10286
10287 pWextState->roamProfile.Keys.KeyLength[key_index] =
10288 (u8) params->key_len;
10289
10290 pWextState->roamProfile.Keys.defaultIndex = key_index;
10291
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010292 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010293 KeyMaterial[key_index][0], params->key,
10294 params->key_len);
10295
10296 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10297
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010298 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010299 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10300 setKey.keyDirection);
10301
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010302 /* The supplicant may attempt to set the PTK once pre-authentication
10303 is done. Save the key in the UMAC and include it in the ADD BSS
10304 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010305 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010306 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010307 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010308 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010309 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010310 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010311 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010312 return -EINVAL;
10313 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010314
10315 /* issue set key request to SME */
10316 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10317 pAdapter->sessionId, &setKey, &roamId);
10318
10319 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010320 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010321 pHddStaCtx->roam_info.roamingState =
10322 HDD_ROAM_STATE_NONE;
10323 return -EINVAL;
10324 }
10325
10326 /* in case of IBSS as there was no information available about WEP keys during
10327 * IBSS join, group key intialized with NULL key, so re-initialize group key
10328 * with correct value*/
10329 if ((eCSR_BSS_TYPE_START_IBSS ==
10330 pWextState->roamProfile.BSSType)
10331 &&
10332 !((IW_AUTH_KEY_MGMT_802_1X ==
10333 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10334 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10335 pHddStaCtx->conn_info.authType)
10336 )
10337 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10338 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10339 )
10340 ) {
10341 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010342 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010343
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010344 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010345 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10346 setKey.keyDirection);
10347
10348 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10349 pAdapter->sessionId, &setKey,
10350 &roamId);
10351
10352 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010353 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010354 pHddStaCtx->roam_info.roamingState =
10355 HDD_ROAM_STATE_NONE;
10356 return -EINVAL;
10357 }
10358 }
10359 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010360 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010361 return 0;
10362}
10363
10364static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10365 struct net_device *ndev,
10366 u8 key_index, bool pairwise,
10367 const u8 *mac_addr,
10368 struct key_params *params)
10369{
10370 int ret;
10371 cds_ssr_protect(__func__);
10372 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10373 mac_addr, params);
10374 cds_ssr_unprotect(__func__);
10375
10376 return ret;
10377}
10378
10379/*
10380 * FUNCTION: __wlan_hdd_cfg80211_get_key
10381 * This function is used to get the key information
10382 */
10383static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10384 struct net_device *ndev,
10385 u8 key_index, bool pairwise,
10386 const u8 *mac_addr, void *cookie,
10387 void (*callback)(void *cookie,
10388 struct key_params *)
10389 )
10390{
10391 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10392 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10393 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10394 struct key_params params;
10395
10396 ENTER();
10397
Anurag Chouhan6d760662016-02-20 16:05:43 +053010398 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010399 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010400 return -EINVAL;
10401 }
10402
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010403 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010404 hdd_device_mode_to_string(pAdapter->device_mode),
10405 pAdapter->device_mode);
10406
10407 memset(&params, 0, sizeof(params));
10408
10409 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010410 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010411 key_index);
10412 return -EINVAL;
10413 }
10414
10415 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10416 case eCSR_ENCRYPT_TYPE_NONE:
10417 params.cipher = IW_AUTH_CIPHER_NONE;
10418 break;
10419
10420 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10421 case eCSR_ENCRYPT_TYPE_WEP40:
10422 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10423 break;
10424
10425 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10426 case eCSR_ENCRYPT_TYPE_WEP104:
10427 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10428 break;
10429
10430 case eCSR_ENCRYPT_TYPE_TKIP:
10431 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10432 break;
10433
10434 case eCSR_ENCRYPT_TYPE_AES:
10435 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10436 break;
10437
10438 default:
10439 params.cipher = IW_AUTH_CIPHER_NONE;
10440 break;
10441 }
10442
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010443 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010444 TRACE_CODE_HDD_CFG80211_GET_KEY,
10445 pAdapter->sessionId, params.cipher));
10446
10447 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10448 params.seq_len = 0;
10449 params.seq = NULL;
10450 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10451 callback(cookie, &params);
10452
10453 EXIT();
10454 return 0;
10455}
10456
10457static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10458 struct net_device *ndev,
10459 u8 key_index, bool pairwise,
10460 const u8 *mac_addr, void *cookie,
10461 void (*callback)(void *cookie,
10462 struct key_params *)
10463 )
10464{
10465 int ret;
10466
10467 cds_ssr_protect(__func__);
10468 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10469 mac_addr, cookie, callback);
10470 cds_ssr_unprotect(__func__);
10471
10472 return ret;
10473}
10474
10475/**
10476 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10477 * @wiphy: wiphy interface context
10478 * @ndev: pointer to net device
10479 * @key_index: Key index used in 802.11 frames
10480 * @unicast: true if it is unicast key
10481 * @multicast: true if it is multicast key
10482 *
10483 * This function is required for cfg80211_ops API.
10484 * It is used to delete the key information
10485 * Underlying hardware implementation does not have API to delete the
10486 * encryption key. It is automatically deleted when the peer is
10487 * removed. Hence this function currently does nothing.
10488 * Future implementation may interprete delete key operation to
10489 * replacing the key with a random junk value, effectively making it
10490 * useless.
10491 *
10492 * Return: status code, always 0.
10493 */
10494
10495static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10496 struct net_device *ndev,
10497 u8 key_index,
10498 bool pairwise, const u8 *mac_addr)
10499{
10500 EXIT();
10501 return 0;
10502}
10503
10504/**
10505 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10506 * @wiphy: Pointer to wiphy structure.
10507 * @dev: Pointer to net_device structure.
10508 * @key_index: key index
10509 * @pairwise: pairwise
10510 * @mac_addr: mac address
10511 *
10512 * This is the cfg80211 delete key handler function which invokes
10513 * the internal function @__wlan_hdd_cfg80211_del_key with
10514 * SSR protection.
10515 *
10516 * Return: 0 for success, error number on failure.
10517 */
10518static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10519 struct net_device *dev,
10520 u8 key_index,
10521 bool pairwise, const u8 *mac_addr)
10522{
10523 int ret;
10524
10525 cds_ssr_protect(__func__);
10526 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10527 pairwise, mac_addr);
10528 cds_ssr_unprotect(__func__);
10529
10530 return ret;
10531}
10532
10533/*
10534 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10535 * This function is used to set the default tx key index
10536 */
10537static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10538 struct net_device *ndev,
10539 u8 key_index,
10540 bool unicast, bool multicast)
10541{
10542 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10543 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10544 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10545 hdd_context_t *pHddCtx;
10546 int status;
10547
10548 ENTER();
10549
Anurag Chouhan6d760662016-02-20 16:05:43 +053010550 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010551 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010552 return -EINVAL;
10553 }
10554
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010555 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10556 hdd_err("invalid session id: %d", pAdapter->sessionId);
10557 return -EINVAL;
10558 }
10559
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010560 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010561 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10562 pAdapter->sessionId, key_index));
10563
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010564 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010565 hdd_device_mode_to_string(pAdapter->device_mode),
10566 pAdapter->device_mode, key_index);
10567
10568 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010569 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010570 return -EINVAL;
10571 }
10572
10573 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10574 status = wlan_hdd_validate_context(pHddCtx);
10575
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010576 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010577 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010578
Krunal Sonib4326f22016-03-10 13:05:51 -080010579 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10580 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010581 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10582 pHddStaCtx->conn_info.ucEncryptionType) &&
10583 (eCSR_ENCRYPT_TYPE_AES !=
10584 pHddStaCtx->conn_info.ucEncryptionType)) {
10585 /* If default key index is not same as previous one,
10586 * then update the default key index */
10587
10588 tCsrRoamSetKey setKey;
10589 uint32_t roamId = 0xFF;
10590 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10591
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010592 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010593
10594 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010595 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010596 setKey.keyId = key_index;
10597 setKey.keyLength = Keys->KeyLength[key_index];
10598
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010599 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010600 &Keys->KeyMaterial[key_index][0],
10601 Keys->KeyLength[key_index]);
10602
10603 setKey.keyDirection = eSIR_TX_RX;
10604
Anurag Chouhanc5548422016-02-24 18:33:27 +053010605 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010606 &pHddStaCtx->conn_info.bssId);
10607
10608 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10609 pWextState->roamProfile.EncryptionType.
10610 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10611 /* In the case of dynamic wep supplicant hardcodes DWEP type
10612 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10613 * WEP-40 encryption. In this canse the key length is 5 but the
10614 * encryption type is 104 hence checking the key langht(5) and
10615 * encryption type(104) and switching encryption type to 40*/
10616 pWextState->roamProfile.EncryptionType.
10617 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10618 pWextState->roamProfile.mcEncryptionType.
10619 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10620 }
10621
10622 setKey.encType =
10623 pWextState->roamProfile.EncryptionType.
10624 encryptionType[0];
10625
10626 /* Issue set key request */
10627 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10628 pAdapter->sessionId, &setKey,
10629 &roamId);
10630
10631 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010632 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010633 status);
10634 return -EINVAL;
10635 }
10636 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010637 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010638 /* In SoftAp mode setting key direction for default mode */
10639 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10640 pWextState->roamProfile.EncryptionType.encryptionType[0])
10641 && (eCSR_ENCRYPT_TYPE_AES !=
10642 pWextState->roamProfile.EncryptionType.
10643 encryptionType[0])) {
10644 /* Saving key direction for default key index to TX default */
10645 hdd_ap_ctx_t *pAPCtx =
10646 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10647 pAPCtx->wepKey[key_index].keyDirection =
10648 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010649 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010650 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010651 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010652 }
10653 }
10654
10655 EXIT();
10656 return status;
10657}
10658
10659static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10660 struct net_device *ndev,
10661 u8 key_index,
10662 bool unicast, bool multicast)
10663{
10664 int ret;
10665 cds_ssr_protect(__func__);
10666 ret =
10667 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10668 multicast);
10669 cds_ssr_unprotect(__func__);
10670
10671 return ret;
10672}
10673
Abhishek Singhc9941602016-08-09 16:06:22 +053010674/*
10675 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10676 * @wiphy: wiphy pointer
10677 * @channel: channel of the BSS
10678 * @bssid: Bssid of BSS
10679 * @ssid: Ssid of the BSS
10680 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010681 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010682 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010683 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010684#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010685static
Abhishek Singhc9941602016-08-09 16:06:22 +053010686struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10687 struct ieee80211_channel *channel, const u8 *bssid,
10688 const u8 *ssid, size_t ssid_len)
10689{
10690 return cfg80211_get_bss(wiphy, channel, bssid,
10691 ssid,
10692 ssid_len,
10693 WLAN_CAPABILITY_ESS,
10694 WLAN_CAPABILITY_ESS);
10695}
10696#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010697static
Abhishek Singhc9941602016-08-09 16:06:22 +053010698struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10699 struct ieee80211_channel *channel, const u8 *bssid,
10700 const u8 *ssid, size_t ssid_len)
10701{
10702 return cfg80211_get_bss(wiphy, channel, bssid,
10703 ssid,
10704 ssid_len,
10705 IEEE80211_BSS_TYPE_ESS,
10706 IEEE80211_PRIVACY_ANY);
10707}
10708#endif
10709
10710
10711/*
10712 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10713 * interface that BSS might have been lost.
10714 * @pAdapter: adaptor
10715 * @bssid: bssid which might have been lost
10716 *
10717 * Return: bss which is unlinked from kernel cache
10718 */
10719struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10720 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010721{
10722 struct net_device *dev = pAdapter->dev;
10723 struct wireless_dev *wdev = dev->ieee80211_ptr;
10724 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010725 struct cfg80211_bss *bss = NULL;
10726
Abhishek Singhc9941602016-08-09 16:06:22 +053010727 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10728 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010729 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010730 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010731 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010732 hdd_info("cfg80211_unlink_bss called for BSSID "
10733 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010734 cfg80211_unlink_bss(wiphy, bss);
10735 }
10736 return bss;
10737}
10738
Abhishek Singhc9941602016-08-09 16:06:22 +053010739
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010740/**
10741 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10742 * @pAdapter: Pointer to adapter
10743 * @bss_desc: Pointer to bss descriptor
10744 *
10745 * This function is used to inform the BSS details to nl80211 interface.
10746 *
10747 * Return: struct cfg80211_bss pointer
10748 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010749struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10750 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010751{
10752 /*
10753 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10754 * already exists in bss data base of cfg80211 for that particular BSS
10755 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10756 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10757 * As of now there is no possibility to get the mgmt(probe response)
10758 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10759 * and passing to cfg80211_inform_bss_frame.
10760 */
10761 struct net_device *dev = pAdapter->dev;
10762 struct wireless_dev *wdev = dev->ieee80211_ptr;
10763 struct wiphy *wiphy = wdev->wiphy;
10764 int chan_no = bss_desc->channelId;
10765#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10766 qcom_ie_age *qie_age = NULL;
10767 int ie_length =
10768 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10769#else
10770 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10771#endif
10772 const char *ie =
10773 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10774 unsigned int freq;
10775 struct ieee80211_channel *chan;
10776 struct ieee80211_mgmt *mgmt = NULL;
10777 struct cfg80211_bss *bss_status = NULL;
10778 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10779 int rssi = 0;
10780 hdd_context_t *pHddCtx;
10781 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010782 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010783 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010784
10785 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10786 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010787 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010788 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010789
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010790 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010791 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10792 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010793 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010794 return NULL;
10795 }
10796
10797 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10798
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010799 /* Android does not want the timestamp from the frame.
10800 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010801 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010802 mgmt->u.probe_resp.timestamp =
10803 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010804
10805 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10806 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10807
10808#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10809 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10810 /* Assuming this is the last IE, copy at the end */
10811 ie_length -= sizeof(qcom_ie_age);
10812 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10813 qie_age->element_id = QCOM_VENDOR_IE_ID;
10814 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10815 qie_age->oui_1 = QCOM_OUI1;
10816 qie_age->oui_2 = QCOM_OUI2;
10817 qie_age->oui_3 = QCOM_OUI3;
10818 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053010819 /*
10820 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
10821 * all bss related timestamp is in units of ms. Due to this when scan
10822 * results are sent to lowi the scan age is high.To address this,
10823 * send age in units of 1/10 ms.
10824 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010825 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053010826 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010827 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010828 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10829 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010830 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10831 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010832#endif
10833
10834 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10835 if (bss_desc->fProbeRsp) {
10836 mgmt->frame_control |=
10837 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10838 } else {
10839 mgmt->frame_control |=
10840 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10841 }
10842
10843 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070010844 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010845 freq =
10846 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010847 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010848 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070010849 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010850 freq =
10851 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010852 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010853 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010854 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010855 kfree(mgmt);
10856 return NULL;
10857 }
10858
10859 chan = __ieee80211_get_channel(wiphy, freq);
10860 /* When the band is changed on the fly using the GUI, three things are done
10861 * 1. scan abort
10862 * 2. flush scan results from cache
10863 * 3. update the band with the new band user specified (refer to the
10864 * hdd_set_band_helper function) as part of the scan abort, message will be
10865 * queued to PE and we proceed with flushing and changinh the band.
10866 * PE will stop the scanning further and report back the results what ever
10867 * it had till now by calling the call back function.
10868 * if the time between update band and scandone call back is sufficient
10869 * enough the band change reflects in SME, SME validates the channels
10870 * and discards the channels correponding to previous band and calls back
10871 * with zero bss results. but if the time between band update and scan done
10872 * callback is very small then band change will not reflect in SME and SME
10873 * reports to HDD all the channels correponding to previous band.this is due
10874 * to race condition.but those channels are invalid to the new band and so
10875 * this function __ieee80211_get_channel will return NULL.Each time we
10876 * report scan result with this pointer null warning kernel trace is printed.
10877 * if the scan results contain large number of APs continuosly kernel
10878 * warning trace is printed and it will lead to apps watch dog bark.
10879 * So drop the bss and continue to next bss.
10880 */
10881 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010882 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10883 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010884 kfree(mgmt);
10885 return NULL;
10886 }
10887
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010888 /* Based on .ini configuration, raw rssi can be reported for bss.
10889 * Raw rssi is typically used for estimating power.
10890 */
10891
10892 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10893 bss_desc->rssi;
10894
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010895 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010896 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010897
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053010898 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010899 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010900 (int)(rssi / 100),
10901 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010902
10903 bss_status =
10904 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10905 GFP_KERNEL);
10906 kfree(mgmt);
10907 return bss_status;
10908}
10909
10910/**
10911 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10912 * @pAdapter: Pointer to adapter
10913 * @pRoamInfo: Pointer to roam info
10914 *
10915 * This function is used to update the BSS data base of CFG8011
10916 *
10917 * Return: struct cfg80211_bss pointer
10918 */
10919struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10920 tCsrRoamInfo *pRoamInfo)
10921{
10922 tCsrRoamConnectedProfile roamProfile;
10923 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10924 struct cfg80211_bss *bss = NULL;
10925
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010926 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10927 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10928
10929 if (NULL != roamProfile.pBssDesc) {
10930 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10931 roamProfile.pBssDesc);
10932
10933 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010934 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010935
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010936 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010937 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010938 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010939 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010940 return bss;
10941}
10942/**
10943 * wlan_hdd_cfg80211_update_bss() - update bss
10944 * @wiphy: Pointer to wiphy
10945 * @pAdapter: Pointer to adapter
10946 * @scan_time: scan request timestamp
10947 *
10948 * Return: zero if success, non-zero otherwise
10949 */
10950int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10951 hdd_adapter_t *pAdapter,
10952 uint32_t scan_time)
10953{
10954 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10955 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010956 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010957 tScanResultHandle pResult;
10958 struct cfg80211_bss *bss_status = NULL;
10959 hdd_context_t *pHddCtx;
10960 int ret;
10961
10962 ENTER();
10963
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010964 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10965 hdd_err("invalid session id: %d", pAdapter->sessionId);
10966 return -EINVAL;
10967 }
10968
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010969 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010970 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10971 NO_SESSION, pAdapter->sessionId));
10972
10973 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10974 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010975 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010976 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010977
10978 /* start getting scan results and populate cgf80211 BSS database */
10979 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
10980
10981 /* no scan results */
10982 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010983 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053010984 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010985 }
10986
10987 pScanResult = sme_scan_result_get_first(hHal, pResult);
10988
10989 while (pScanResult) {
10990 /*
10991 * - cfg80211_inform_bss() is not updating ie field of bss
10992 * entry if entry already exists in bss data base of cfg80211
10993 * for that particular BSS ID. Using cfg80211_inform_bss_frame
10994 * to update thebss entry instead of cfg80211_inform_bss,
10995 * But this call expects mgmt packet as input. As of now
10996 * there is no possibility to get the mgmt(probe response)
10997 * frame from PE, converting bss_desc to
10998 * ieee80211_mgmt(probe response) and passing to c
10999 * fg80211_inform_bss_frame.
11000 * - Update BSS only if beacon timestamp is later than
11001 * scan request timestamp.
11002 */
11003 if ((scan_time == 0) ||
11004 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053011005 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011006 bss_status =
11007 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11008 &pScanResult->BssDescriptor);
11009
11010 if (NULL == bss_status) {
11011 hdd_info("NULL returned by cfg80211_inform_bss_frame");
11012 } else {
11013 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011014 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011015 bss_status);
11016 }
11017 } else {
11018 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
11019 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
11020 }
11021 pScanResult = sme_scan_result_get_next(hHal, pResult);
11022 }
11023
11024 sme_scan_result_purge(hHal, pResult);
11025 /*
11026 * For SAP mode, scan is invoked by hostapd during SAP start
11027 * if hostapd is restarted, we need to flush previous scan
11028 * result so that it will reflect environment change
11029 */
Krunal Sonib4326f22016-03-10 13:05:51 -080011030 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011031#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
11032 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
11033#endif
11034 )
11035 sme_scan_flush_result(hHal);
11036
11037 EXIT();
11038 return 0;
11039}
11040
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011041/**
11042 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
11043 * @pAdapter: Pointer to adapter
11044 * @pRoamInfo: Pointer to roam info
11045 * @index: Index
11046 * @preauth: Preauth flag
11047 *
11048 * This function is used to notify the supplicant of a new PMKSA candidate.
11049 *
11050 * Return: 0 for success, non-zero for failure
11051 */
11052int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
11053 tCsrRoamInfo *pRoamInfo,
11054 int index, bool preauth)
11055{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011056 struct net_device *dev = pAdapter->dev;
11057 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
11058
11059 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011060 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011061
11062 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011063 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011064 return -EINVAL;
11065 }
11066
11067 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011068 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011069 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
11070 cfg80211_pmksa_candidate_notify(dev, index,
11071 pRoamInfo->bssid.bytes,
11072 preauth, GFP_KERNEL);
11073 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011074 return 0;
11075}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011076
11077#ifdef FEATURE_WLAN_LFR_METRICS
11078/**
11079 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
11080 * @pAdapter: Pointer to adapter
11081 * @pRoamInfo: Pointer to roam info
11082 *
11083 * 802.11r/LFR metrics reporting function to report preauth initiation
11084 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011085 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011086 */
11087#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011088QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011089 tCsrRoamInfo *pRoamInfo)
11090{
11091 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11092 union iwreq_data wrqu;
11093
11094 ENTER();
11095
11096 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011097 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011098 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011099 }
11100
11101 /* create the event */
11102 memset(&wrqu, 0, sizeof(wrqu));
11103 memset(metrics_notification, 0, sizeof(metrics_notification));
11104
11105 wrqu.data.pointer = metrics_notification;
11106 wrqu.data.length = scnprintf(metrics_notification,
11107 sizeof(metrics_notification),
11108 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
11109 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11110
11111 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11112 metrics_notification);
11113
11114 EXIT();
11115
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011116 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011117}
11118
11119/**
11120 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11121 * @pAdapter: Pointer to adapter
11122 * @pRoamInfo: Pointer to roam info
11123 * @preauth_status: Preauth status
11124 *
11125 * 802.11r/LFR metrics reporting function to report handover initiation
11126 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011127 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011128 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011129QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011130wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
11131 tCsrRoamInfo *pRoamInfo,
11132 bool preauth_status)
11133{
11134 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11135 union iwreq_data wrqu;
11136
11137 ENTER();
11138
11139 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011140 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011141 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011142 }
11143
11144 /* create the event */
11145 memset(&wrqu, 0, sizeof(wrqu));
11146 memset(metrics_notification, 0, sizeof(metrics_notification));
11147
11148 scnprintf(metrics_notification, sizeof(metrics_notification),
11149 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
11150 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11151
11152 if (1 == preauth_status)
11153 strlcat(metrics_notification, " true",
11154 sizeof(metrics_notification));
11155 else
11156 strlcat(metrics_notification, " false",
11157 sizeof(metrics_notification));
11158
11159 wrqu.data.pointer = metrics_notification;
11160 wrqu.data.length = strlen(metrics_notification);
11161
11162 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11163 metrics_notification);
11164
11165 EXIT();
11166
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011167 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011168}
11169
11170/**
11171 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11172 * @pAdapter: Pointer to adapter
11173 * @pRoamInfo: Pointer to roam info
11174 *
11175 * 802.11r/LFR metrics reporting function to report handover initiation
11176 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011177 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011178 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011179QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011180 tCsrRoamInfo *pRoamInfo)
11181{
11182 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11183 union iwreq_data wrqu;
11184
11185 ENTER();
11186
11187 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011188 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011189 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011190 }
11191
11192 /* create the event */
11193 memset(&wrqu, 0, sizeof(wrqu));
11194 memset(metrics_notification, 0, sizeof(metrics_notification));
11195
11196 wrqu.data.pointer = metrics_notification;
11197 wrqu.data.length = scnprintf(metrics_notification,
11198 sizeof(metrics_notification),
11199 "QCOM: LFR_PREAUTH_HANDOVER "
11200 MAC_ADDRESS_STR,
11201 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11202
11203 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11204 metrics_notification);
11205
11206 EXIT();
11207
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011208 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011209}
11210#endif
11211
11212/**
11213 * hdd_select_cbmode() - select channel bonding mode
11214 * @pAdapter: Pointer to adapter
11215 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011216 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011217 *
11218 * Return: none
11219 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011220void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11221 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011222{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011223 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011224 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011225 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011226
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011227 /*
11228 * CDS api expects secondary channel for calculating
11229 * the channel params
11230 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011231 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011232 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11233 if (operationChannel >= 1 && operationChannel <= 5)
11234 sec_ch = operationChannel + 4;
11235 else if (operationChannel >= 6 && operationChannel <= 13)
11236 sec_ch = operationChannel - 4;
11237 }
11238
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011239 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011240 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011241
11242 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011243 eHddDot11Mode hdd_dot11_mode;
11244 uint8_t iniDot11Mode =
11245 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11246
11247 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11248 switch (iniDot11Mode) {
11249 case eHDD_DOT11_MODE_AUTO:
11250 case eHDD_DOT11_MODE_11ac:
11251 case eHDD_DOT11_MODE_11ac_ONLY:
11252 if (sme_is_feature_supported_by_fw(DOT11AC))
11253 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11254 else
11255 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11256 break;
11257 case eHDD_DOT11_MODE_11n:
11258 case eHDD_DOT11_MODE_11n_ONLY:
11259 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11260 break;
11261 default:
11262 hdd_dot11_mode = iniDot11Mode;
11263 break;
11264 }
11265 ch_info->channel_width = ch_params->ch_width;
11266 ch_info->phy_mode =
11267 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011268 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011269 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011270 hdd_info("ch_info width %d, phymode %d channel %d",
11271 ch_info->channel_width, ch_info->phy_mode,
11272 ch_info->channel);
11273 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011274}
11275
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011276/**
11277 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11278 * @adapter: STA adapter
11279 * @roam_profile: STA roam profile
11280 *
11281 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11282 *
11283 * Return: false if sta-sap conc is not allowed, else return true
11284 */
11285static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11286 tCsrRoamProfile *roam_profile)
11287{
11288 hdd_context_t *hdd_ctx;
11289 hdd_adapter_t *ap_adapter;
11290 hdd_ap_ctx_t *hdd_ap_ctx;
11291 hdd_hostapd_state_t *hostapd_state;
11292 uint8_t channel = 0;
11293 QDF_STATUS status;
11294
11295 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11296 if (!hdd_ctx) {
11297 hdd_err("HDD context is NULL");
11298 return true;
11299 }
11300
11301 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11302 /* probably no sap running, no handling required */
11303 if (ap_adapter == NULL)
11304 return true;
11305
11306 /*
11307 * sap is not in started state, so it is fine to go ahead with sta.
11308 * if sap is currently doing CAC then don't allow sta to go further.
11309 */
11310 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11311 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11312 return true;
11313
11314 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11315 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11316 return false;
11317 }
11318
11319 /*
11320 * log and return error, if we allow STA to go through, we don't
11321 * know what is going to happen better stop sta connection
11322 */
11323 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11324 if (NULL == hdd_ap_ctx) {
11325 hdd_err("AP context not found");
11326 return false;
11327 }
11328
11329 /* sap is on non-dfs channel, nothing to handle */
11330 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11331 hdd_info("sap is on non-dfs channel, sta is allowed");
11332 return true;
11333 }
11334 /*
11335 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011336 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011337 */
11338 status = cds_get_channel_from_scan_result(adapter,
11339 roam_profile, &channel);
11340
Nitesh Shah59774522016-09-16 15:14:21 +053011341 /*
11342 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11343 * channels for roaming case.
11344 */
11345 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11346 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11347 return true;
11348 }
11349
11350 /*
11351 * If channel is 0 or DFS then better to call pcl and find out the
11352 * best channel. If channel is non-dfs 5 GHz then better move SAP
11353 * to STA's channel to make scc, so we have room for 3port MCC
11354 * scenario.
11355 */
11356 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011357 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11358 true);
11359
11360 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11361 qdf_event_reset(&hostapd_state->qdf_event);
11362 status = wlansap_set_channel_change_with_csa(
11363 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11364 hdd_ap_ctx->sapConfig.ch_width_orig);
11365
11366 if (QDF_STATUS_SUCCESS != status) {
11367 hdd_err("Set channel with CSA IE failed, can't allow STA");
11368 return false;
11369 }
11370
11371 /*
11372 * wait here for SAP to finish the channel switch. When channel
11373 * switch happens, SAP sends few beacons with CSA_IE. After
11374 * successfully Transmission of those beacons, it will move its
11375 * state from started to disconnected and move to new channel.
11376 * once it moves to new channel, sap again moves its state
11377 * machine from disconnected to started and set this event.
11378 * wait for 10 secs to finish this.
11379 */
11380 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11381 if (!QDF_IS_STATUS_SUCCESS(status)) {
11382 hdd_err("wait for qdf_event failed, STA not allowed!!");
11383 return false;
11384 }
11385
11386 return true;
11387}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011388
Krunal Soni31949422016-07-29 17:17:53 -070011389/**
11390 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011391 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011392 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011393 * @ssid_len: Length of ssid
11394 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011395 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011396 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011397 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011398 *
11399 * This function is used to start the association process
11400 *
11401 * Return: 0 for success, non-zero for failure
11402 */
Krunal Soni31949422016-07-29 17:17:53 -070011403static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011404 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011405 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011406 u8 operatingChannel,
11407 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011408{
11409 int status = 0;
11410 hdd_wext_state_t *pWextState;
11411 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011412 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011413 uint32_t roamId;
11414 tCsrRoamProfile *pRoamProfile;
11415 eCsrAuthType RSNAuthType;
11416 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011417 uint8_t channel = 0;
11418 struct sir_hw_mode_params hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011419
11420 ENTER();
11421
11422 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11423 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011424 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011425
11426 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011427 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011428 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011429
11430 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011431 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011432 return -EINVAL;
11433 }
11434
11435 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011436 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11437 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011438
11439 if (pRoamProfile) {
11440 hdd_station_ctx_t *pHddStaCtx;
11441 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11442
11443 if (HDD_WMM_USER_MODE_NO_QOS ==
11444 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11445 /*QoS not enabled in cfg file */
11446 pRoamProfile->uapsd_mask = 0;
11447 } else {
11448 /*QoS enabled, update uapsd mask from cfg file */
11449 pRoamProfile->uapsd_mask =
11450 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11451 }
11452
11453 pRoamProfile->SSIDs.numOfSSIDs = 1;
11454 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011455 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011456 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011457 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011458 ssid, ssid_len);
11459
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011460 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011461 if (bssid) {
11462 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011463 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011464 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011465 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011466 /*
11467 * Save BSSID in seperate variable as
11468 * pRoamProfile's BSSID is getting zeroed out in the
11469 * association process. In case of join failure
11470 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011471 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011472 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011473 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011474 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011475 } else if (bssid_hint) {
11476 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011477 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011478 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011479 /*
11480 * Save BSSID in a separate variable as
11481 * pRoamProfile's BSSID is getting zeroed out in the
11482 * association process. In case of join failure
11483 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011484 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011485 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011486 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011487 hdd_info("bssid_hint is given by upper layer %pM",
11488 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011489 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011490 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011491 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011492 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011493 }
11494
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011495 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011496 pRoamProfile->SSIDs.SSIDList->SSID.length,
11497 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11498 operatingChannel);
11499
11500 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11501 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011502 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011503 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11504 }
11505#ifdef FEATURE_WLAN_WAPI
11506 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011507 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011508 switch (pAdapter->wapi_info.wapiAuthMode) {
11509 case WAPI_AUTH_MODE_PSK:
11510 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011511 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011512 pAdapter->wapi_info.wapiAuthMode);
11513 pRoamProfile->AuthType.authType[0] =
11514 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11515 break;
11516 }
11517 case WAPI_AUTH_MODE_CERT:
11518 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011519 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011520 pAdapter->wapi_info.wapiAuthMode);
11521 pRoamProfile->AuthType.authType[0] =
11522 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11523 break;
11524 }
11525 } /* End of switch */
11526 if (pAdapter->wapi_info.wapiAuthMode ==
11527 WAPI_AUTH_MODE_PSK
11528 || pAdapter->wapi_info.wapiAuthMode ==
11529 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011530 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011531 pRoamProfile->AuthType.numEntries = 1;
11532 pRoamProfile->EncryptionType.numEntries = 1;
11533 pRoamProfile->EncryptionType.encryptionType[0] =
11534 eCSR_ENCRYPT_TYPE_WPI;
11535 pRoamProfile->mcEncryptionType.numEntries = 1;
11536 pRoamProfile->mcEncryptionType.
11537 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11538 }
11539 }
Krunal Soni31949422016-07-29 17:17:53 -070011540#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011541#ifdef WLAN_FEATURE_GTK_OFFLOAD
11542 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011543 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11544 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011545 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11546 sizeof(tSirGtkOffloadParams));
11547 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11548 GTK_OFFLOAD_DISABLE;
11549 }
11550#endif
11551 pRoamProfile->csrPersona = pAdapter->device_mode;
11552
11553 if (operatingChannel) {
11554 pRoamProfile->ChannelInfo.ChannelList =
11555 &operatingChannel;
11556 pRoamProfile->ChannelInfo.numOfChannels = 1;
11557 } else {
11558 pRoamProfile->ChannelInfo.ChannelList = NULL;
11559 pRoamProfile->ChannelInfo.numOfChannels = 0;
11560 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011561 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011562 && operatingChannel) {
11563 /*
11564 * Need to post the IBSS power save parameters
11565 * to WMA. WMA will configure this parameters
11566 * to firmware if power save is enabled by the
11567 * firmware.
11568 */
11569 status = hdd_set_ibss_power_save_params(pAdapter);
11570
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011571 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011572 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011573 return -EINVAL;
11574 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011575 pRoamProfile->ch_params.ch_width =
11576 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011577 /*
11578 * In IBSS mode while operating in 2.4 GHz,
11579 * the device supports only 20 MHz.
11580 */
11581 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11582 pRoamProfile->ch_params.ch_width =
11583 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011584 hdd_select_cbmode(pAdapter, operatingChannel,
11585 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011586 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011587 /*
11588 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11589 * or pmf=2 is an explicit configuration in the supplicant
11590 * configuration, drop the connection request.
11591 */
11592 if (pWextState->roamProfile.MFPEnabled &&
11593 !(pWextState->roamProfile.MFPRequired ||
11594 pWextState->roamProfile.MFPCapable)) {
11595 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11596 pWextState->roamProfile.MFPEnabled,
11597 pWextState->roamProfile.MFPRequired,
11598 pWextState->roamProfile.MFPCapable);
11599 return -EINVAL;
11600 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011601
Krunal Soni3091bcc2016-06-23 12:28:21 -070011602 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011603 hdd_err("Connection refused: conn in progress");
11604 return -EINVAL;
11605 }
11606
Krunal Soni31949422016-07-29 17:17:53 -070011607 /*
11608 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011609 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011610 * enhancements, the supplicant is not issuing the scan command
11611 * now. So the unicast frames which are sent from the host are
11612 * not having the additional IEs. If it is P2P CLIENT and there
11613 * is no additional IE present in roamProfile, then use the
11614 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011615 */
11616
Krunal Sonib4326f22016-03-10 13:05:51 -080011617 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011618 (!pRoamProfile->pAddIEScan)) {
11619 pRoamProfile->pAddIEScan =
11620 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11621 pRoamProfile->nAddIEScanLength =
11622 pAdapter->scan_info.scanAddIE.length;
11623 }
11624 /*
11625 * When policy manager is enabled from ini file, we shouldn't
11626 * check for other concurrency rules.
11627 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011628 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011629 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011630 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011631 pAdapter, pRoamProfile, &roamId))
11632 return 0;
11633 }
11634
Krunal Soni3091bcc2016-06-23 12:28:21 -070011635 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011636 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11637 pRoamProfile))) {
11638 hdd_err("sap-sta conc will fail, can't allow sta");
11639 hdd_conn_set_connection_state(pAdapter,
11640 eConnectionState_NotConnected);
11641 return -ENOMEM;
11642 }
11643
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011644 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011645 if (!sme_config) {
11646 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011647 hdd_conn_set_connection_state(pAdapter,
11648 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011649 return -ENOMEM;
11650 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011651 sme_get_config_param(pHddCtx->hHal, sme_config);
11652 /* These values are not sessionized. So, any change in these SME
11653 * configs on an older or parallel interface will affect the
11654 * cb mode. So, restoring the default INI params before starting
11655 * interfaces such as sta, cli etc.,
11656 */
11657 sme_config->csrConfig.channelBondingMode5GHz =
11658 pHddCtx->config->nChannelBondingMode5GHz;
11659 sme_config->csrConfig.channelBondingMode24GHz =
11660 pHddCtx->config->nChannelBondingMode24GHz;
11661 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011662 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011663 /*
11664 * Change conn_state to connecting before sme_roam_connect(),
11665 * because sme_roam_connect() has a direct path to call
11666 * hdd_sme_roam_callback(), which will change the conn_state
11667 * If direct path, conn_state will be accordingly changed to
11668 * NotConnected or Associated by either
11669 * hdd_association_completion_handler() or
11670 * hdd_dis_connect_handler() in sme_RoamCallback()if
11671 * sme_RomConnect is to be queued,
11672 * Connecting state will remain until it is completed.
11673 *
11674 * If connection state is not changed, connection state will
11675 * remain in eConnectionState_NotConnected state.
11676 * In hdd_association_completion_handler, "hddDisconInProgress"
11677 * is set to true if conn state is
11678 * eConnectionState_NotConnected.
11679 * If "hddDisconInProgress" is set to true then cfg80211 layer
11680 * is not informed of connect result indication which
11681 * is an issue.
11682 */
11683 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011684 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011685 hdd_conn_set_connection_state(pAdapter,
11686 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011687
Komal Seelama89be8d2016-09-29 11:09:26 +053011688 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
11689 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011690 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11691 pAdapter->sessionId, pRoamProfile,
11692 &roamId);
11693
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011694 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011695 (QDF_STA_MODE == pAdapter->device_mode ||
11696 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011697 hdd_err("sme_roam_connect (session %d) failed with "
11698 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011699 pAdapter->sessionId, status);
11700 /* change back to NotAssociated */
11701 hdd_conn_set_connection_state(pAdapter,
11702 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053011703 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
11704 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011705 }
11706
11707 pRoamProfile->ChannelInfo.ChannelList = NULL;
11708 pRoamProfile->ChannelInfo.numOfChannels = 0;
11709
Nitesh Shah044fd672016-10-13 18:53:25 +053011710 if (!QDF_IS_STATUS_SUCCESS(
11711 wma_get_current_hw_mode(&hw_mode))) {
11712 hdd_err("wma_get_current_hw_mode failed");
11713 return status;
11714 }
11715
11716 if ((QDF_STA_MODE == pAdapter->device_mode)
11717 && hw_mode.dbs_cap) {
11718 cds_get_channel_from_scan_result(pAdapter,
11719 pRoamProfile, &channel);
11720 if (channel)
11721 cds_checkn_update_hw_mode_single_mac_mode
11722 (channel);
11723 }
11724
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011725 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011726 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011727 return -EINVAL;
11728 }
11729 EXIT();
11730 return status;
11731}
11732
11733/**
11734 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11735 * @pAdapter: Pointer to adapter
11736 * @auth_type: Auth type
11737 *
11738 * This function is used to set the authentication type (OPEN/SHARED).
11739 *
11740 * Return: 0 for success, non-zero for failure
11741 */
11742static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11743 enum nl80211_auth_type auth_type)
11744{
11745 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11746 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11747
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011748 /*set authentication type */
11749 switch (auth_type) {
11750 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011751 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011752 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11753 break;
11754
11755 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011756 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011757 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011758 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11759 break;
11760
11761 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011762 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011763 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11764 break;
11765#ifdef FEATURE_WLAN_ESE
11766 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011767 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011768 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11769 break;
11770#endif
11771
11772 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011773 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011774 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11775 return -EINVAL;
11776 }
11777
11778 pWextState->roamProfile.AuthType.authType[0] =
11779 pHddStaCtx->conn_info.authType;
11780 return 0;
11781}
11782
11783/**
11784 * wlan_hdd_set_akm_suite() - set key management type
11785 * @pAdapter: Pointer to adapter
11786 * @key_mgmt: Key management type
11787 *
11788 * This function is used to set the key mgmt type(PSK/8021x).
11789 *
11790 * Return: 0 for success, non-zero for failure
11791 */
11792static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11793{
11794 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11795
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011796#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11797#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11798 /*set key mgmt type */
11799 switch (key_mgmt) {
11800 case WLAN_AKM_SUITE_PSK:
11801 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011802 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011803 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011804 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11805 break;
11806
11807 case WLAN_AKM_SUITE_8021X_SHA256:
11808 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011809 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011810 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011811 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11812 break;
11813#ifdef FEATURE_WLAN_ESE
11814#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11815#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11816 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011817 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011818 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11819 break;
11820#endif
11821#ifndef WLAN_AKM_SUITE_OSEN
11822#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11823#endif
11824 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011825 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011826 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11827 break;
11828
11829 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011830 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011831 return -EINVAL;
11832
11833 }
11834 return 0;
11835}
11836
11837/**
11838 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11839 * @pAdapter: Pointer to adapter
11840 * @cipher: Cipher type
11841 * @ucast: Unicast flag
11842 *
11843 * This function is used to set the encryption type
11844 * (NONE/WEP40/WEP104/TKIP/CCMP).
11845 *
11846 * Return: 0 for success, non-zero for failure
11847 */
11848static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11849 u32 cipher, bool ucast)
11850{
11851 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11852 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11853 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11854
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011855 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011856 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011857 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11858 } else {
11859
11860 /*set encryption method */
11861 switch (cipher) {
11862 case IW_AUTH_CIPHER_NONE:
11863 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11864 break;
11865
11866 case WLAN_CIPHER_SUITE_WEP40:
11867 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11868 break;
11869
11870 case WLAN_CIPHER_SUITE_WEP104:
11871 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11872 break;
11873
11874 case WLAN_CIPHER_SUITE_TKIP:
11875 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11876 break;
11877
11878 case WLAN_CIPHER_SUITE_CCMP:
11879 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11880 break;
11881#ifdef FEATURE_WLAN_WAPI
11882 case WLAN_CIPHER_SUITE_SMS4:
11883 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11884 break;
11885#endif
11886
11887#ifdef FEATURE_WLAN_ESE
11888 case WLAN_CIPHER_SUITE_KRK:
11889 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11890 break;
11891#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11892 case WLAN_CIPHER_SUITE_BTK:
11893 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11894 break;
11895#endif
11896#endif
11897 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011898 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011899 return -EOPNOTSUPP;
11900 }
11901 }
11902
11903 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011904 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011905 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11906 pWextState->roamProfile.EncryptionType.numEntries = 1;
11907 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11908 encryptionType;
11909 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011910 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011911 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11912 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11913 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11914 encryptionType;
11915 }
11916
11917 return 0;
11918}
11919
11920/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011921 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11922 * @wext_state: Pointer to wext state
11923 * @gen_ie: Pointer to IE data
11924 * @len: length of IE data
11925 *
11926 * Return: 0 for success, non-zero for failure
11927 */
11928static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11929 const uint8_t *gen_ie, uint16_t len)
11930{
11931 uint16_t cur_add_ie_len =
11932 wext_state->assocAddIE.length;
11933
11934 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11935 (wext_state->assocAddIE.length + len)) {
11936 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11937 QDF_ASSERT(0);
11938 return -ENOMEM;
11939 }
11940 memcpy(wext_state->assocAddIE.addIEdata +
11941 cur_add_ie_len, gen_ie, len);
11942 wext_state->assocAddIE.length += len;
11943
11944 wext_state->roamProfile.pAddIEAssoc =
11945 wext_state->assocAddIE.addIEdata;
11946 wext_state->roamProfile.nAddIEAssocLength =
11947 wext_state->assocAddIE.length;
11948 return 0;
11949}
11950
11951/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011952 * wlan_hdd_cfg80211_set_ie() - set IEs
11953 * @pAdapter: Pointer to adapter
11954 * @ie: Pointer ot ie
11955 * @ie: IE length
11956 *
11957 * Return: 0 for success, non-zero for failure
11958 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011959static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011960 size_t ie_len)
11961{
11962 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11963 const uint8_t *genie = ie;
11964 uint16_t remLen = ie_len;
11965#ifdef FEATURE_WLAN_WAPI
11966 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
11967 u16 *tmp;
11968 uint16_t akmsuiteCount;
11969 int *akmlist;
11970#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011971 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011972
11973 /* clear previous assocAddIE */
11974 pWextState->assocAddIE.length = 0;
11975 pWextState->roamProfile.bWPSAssociation = false;
11976 pWextState->roamProfile.bOSENAssociation = false;
11977
11978 while (remLen >= 2) {
11979 uint16_t eLen = 0;
11980 uint8_t elementId;
11981 elementId = *genie++;
11982 eLen = *genie++;
11983 remLen -= 2;
11984
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011985 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011986
11987 switch (elementId) {
11988 case DOT11F_EID_WPA:
11989 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 -070011990 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011991 return -EINVAL;
11992 } else if (0 ==
11993 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
11994 uint16_t curAddIELen =
11995 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011996 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011997
11998 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11999 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012000 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012001 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012002 return -ENOMEM;
12003 }
12004 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12005 memcpy(pWextState->assocAddIE.addIEdata +
12006 curAddIELen, genie - 2, eLen + 2);
12007 pWextState->assocAddIE.length += eLen + 2;
12008
12009 pWextState->roamProfile.bWPSAssociation = true;
12010 pWextState->roamProfile.pAddIEAssoc =
12011 pWextState->assocAddIE.addIEdata;
12012 pWextState->roamProfile.nAddIEAssocLength =
12013 pWextState->assocAddIE.length;
12014 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012015 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012016 memset(pWextState->WPARSNIE, 0,
12017 MAX_WPA_RSN_IE_LEN);
12018 memcpy(pWextState->WPARSNIE, genie - 2,
12019 (eLen + 2));
12020 pWextState->roamProfile.pWPAReqIE =
12021 pWextState->WPARSNIE;
12022 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
12023 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
12024 P2P_OUI_TYPE_SIZE))) {
12025 uint16_t curAddIELen =
12026 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012027 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012028
12029 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12030 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012031 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012032 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012033 return -ENOMEM;
12034 }
12035 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12036 memcpy(pWextState->assocAddIE.addIEdata +
12037 curAddIELen, genie - 2, eLen + 2);
12038 pWextState->assocAddIE.length += eLen + 2;
12039
12040 pWextState->roamProfile.pAddIEAssoc =
12041 pWextState->assocAddIE.addIEdata;
12042 pWextState->roamProfile.nAddIEAssocLength =
12043 pWextState->assocAddIE.length;
12044 }
12045#ifdef WLAN_FEATURE_WFD
12046 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
12047 WFD_OUI_TYPE_SIZE)) &&
12048 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080012049 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012050 pAdapter->device_mode)) {
12051 uint16_t curAddIELen =
12052 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012053 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012054
12055 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12056 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012057 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012058 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012059 return -ENOMEM;
12060 }
12061 /* WFD IE is saved to Additional IE ; it should
12062 * be accumulated to handle WPS IE + P2P IE +
12063 * WFD IE */
12064 memcpy(pWextState->assocAddIE.addIEdata +
12065 curAddIELen, genie - 2, eLen + 2);
12066 pWextState->assocAddIE.length += eLen + 2;
12067
12068 pWextState->roamProfile.pAddIEAssoc =
12069 pWextState->assocAddIE.addIEdata;
12070 pWextState->roamProfile.nAddIEAssocLength =
12071 pWextState->assocAddIE.length;
12072 }
12073#endif
12074 /* Appending HS 2.0 Indication Element in Assiciation Request */
12075 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
12076 HS20_OUI_TYPE_SIZE))) {
12077 uint16_t curAddIELen =
12078 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012079 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012080
12081 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12082 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012083 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012084 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012085 return -ENOMEM;
12086 }
12087 memcpy(pWextState->assocAddIE.addIEdata +
12088 curAddIELen, genie - 2, eLen + 2);
12089 pWextState->assocAddIE.length += eLen + 2;
12090
12091 pWextState->roamProfile.pAddIEAssoc =
12092 pWextState->assocAddIE.addIEdata;
12093 pWextState->roamProfile.nAddIEAssocLength =
12094 pWextState->assocAddIE.length;
12095 }
12096 /* Appending OSEN Information Element in Assiciation Request */
12097 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
12098 OSEN_OUI_TYPE_SIZE))) {
12099 uint16_t curAddIELen =
12100 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012101 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012102
12103 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12104 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012105 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012106 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012107 return -ENOMEM;
12108 }
12109 memcpy(pWextState->assocAddIE.addIEdata +
12110 curAddIELen, genie - 2, eLen + 2);
12111 pWextState->assocAddIE.length += eLen + 2;
12112
12113 pWextState->roamProfile.bOSENAssociation = true;
12114 pWextState->roamProfile.pAddIEAssoc =
12115 pWextState->assocAddIE.addIEdata;
12116 pWextState->roamProfile.nAddIEAssocLength =
12117 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012118 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
12119 MBO_OUI_TYPE_SIZE))){
12120 hdd_info("Set MBO IE(len %d)", eLen + 2);
12121 status = wlan_hdd_add_assoc_ie(pWextState,
12122 genie - 2, eLen + 2);
12123 if (status)
12124 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012125 } else {
12126 uint16_t add_ie_len =
12127 pWextState->assocAddIE.length;
12128
12129 hdd_info("Set OSEN IE(len %d)", eLen + 2);
12130
12131 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12132 (pWextState->assocAddIE.length + eLen)) {
12133 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012134 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012135 return -ENOMEM;
12136 }
12137
12138 memcpy(pWextState->assocAddIE.addIEdata +
12139 add_ie_len, genie - 2, eLen + 2);
12140 pWextState->assocAddIE.length += eLen + 2;
12141
12142 pWextState->roamProfile.pAddIEAssoc =
12143 pWextState->assocAddIE.addIEdata;
12144 pWextState->roamProfile.nAddIEAssocLength =
12145 pWextState->assocAddIE.length;
12146 }
12147 break;
12148 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012149 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012150 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
12151 memcpy(pWextState->WPARSNIE, genie - 2,
12152 (eLen + 2));
12153 pWextState->roamProfile.pRSNReqIE =
12154 pWextState->WPARSNIE;
12155 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12156 break;
12157 /*
12158 * Appending Extended Capabilities with Interworking bit set
12159 * in Assoc Req.
12160 *
12161 * In assoc req this EXT Cap will only be taken into account if
12162 * interworkingService bit is set to 1. Currently
12163 * driver is only interested in interworkingService capability
12164 * from supplicant. If in future any other EXT Cap info is
12165 * required from supplicat, it needs to be handled while
12166 * sending Assoc Req in LIM.
12167 */
12168 case DOT11F_EID_EXTCAP:
12169 {
12170 uint16_t curAddIELen =
12171 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012172 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012173
12174 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12175 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012176 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012177 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012178 return -ENOMEM;
12179 }
12180 memcpy(pWextState->assocAddIE.addIEdata +
12181 curAddIELen, genie - 2, eLen + 2);
12182 pWextState->assocAddIE.length += eLen + 2;
12183
12184 pWextState->roamProfile.pAddIEAssoc =
12185 pWextState->assocAddIE.addIEdata;
12186 pWextState->roamProfile.nAddIEAssocLength =
12187 pWextState->assocAddIE.length;
12188 break;
12189 }
12190#ifdef FEATURE_WLAN_WAPI
12191 case WLAN_EID_WAPI:
12192 /* Setting WAPI Mode to ON=1 */
12193 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012194 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012195 tmp = (u16 *) ie;
12196 tmp = tmp + 2; /* Skip element Id and Len, Version */
12197 akmsuiteCount = WPA_GET_LE16(tmp);
12198 tmp = tmp + 1;
12199 akmlist = (int *)(tmp);
12200 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12201 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12202 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012203 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012204 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012205 return -EINVAL;
12206 }
12207
12208 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012209 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012210 pAdapter->wapi_info.wapiAuthMode =
12211 WAPI_AUTH_MODE_PSK;
12212 }
12213 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012214 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012215 pAdapter->wapi_info.wapiAuthMode =
12216 WAPI_AUTH_MODE_CERT;
12217 }
12218 break;
12219#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012220 case DOT11F_EID_SUPPOPERATINGCLASSES:
12221 {
12222 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12223 status = wlan_hdd_add_assoc_ie(pWextState,
12224 genie - 2, eLen + 2);
12225 if (status)
12226 return status;
12227 break;
12228 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012229 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012230 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012231 /* when Unknown IE is received we should break and continue
12232 * to the next IE in the buffer instead we were returning
12233 * so changing this to break */
12234 break;
12235 }
12236 genie += eLen;
12237 remLen -= eLen;
12238 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012239 return 0;
12240}
12241
12242/**
12243 * hdd_is_wpaie_present() - check for WPA ie
12244 * @ie: Pointer to ie
12245 * @ie_len: Ie length
12246 *
12247 * Parse the received IE to find the WPA IE
12248 *
12249 * Return: true if wpa ie is found else false
12250 */
12251static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12252{
12253 uint8_t eLen = 0;
12254 uint16_t remLen = ie_len;
12255 uint8_t elementId = 0;
12256
12257 while (remLen >= 2) {
12258 elementId = *ie++;
12259 eLen = *ie++;
12260 remLen -= 2;
12261 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012262 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012263 return false;
12264 }
12265 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12266 /* OUI - 0x00 0X50 0XF2
12267 * WPA Information Element - 0x01
12268 * WPA version - 0x01
12269 */
12270 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12271 return true;
12272 }
12273 ie += eLen;
12274 remLen -= eLen;
12275 }
12276 return false;
12277}
12278
12279/**
12280 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12281 * @pAdapter: Pointer to adapter
12282 * @req: Pointer to security parameters
12283 *
12284 * Return: 0 for success, non-zero for failure
12285 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012286static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12287 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012288{
12289 int status = 0;
12290 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12291 ENTER();
12292
12293 /*set wpa version */
12294 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12295
12296 if (req->crypto.wpa_versions) {
12297 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12298 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12299 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12300 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12301 }
12302 }
12303
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012304 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012305
12306 /*set authentication type */
12307 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12308
12309 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012310 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012311 return status;
12312 }
12313
12314 /*set key mgmt type */
12315 if (req->crypto.n_akm_suites) {
12316 status =
12317 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12318 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012319 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012320 return status;
12321 }
12322 }
12323
12324 /*set pairwise cipher type */
12325 if (req->crypto.n_ciphers_pairwise) {
12326 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12327 req->crypto.
12328 ciphers_pairwise[0],
12329 true);
12330 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012331 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012332 return status;
12333 }
12334 } else {
12335 /*Reset previous cipher suite to none */
12336 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12337 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012338 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012339 return status;
12340 }
12341 }
12342
12343 /*set group cipher type */
12344 status =
12345 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12346 false);
12347
12348 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012349 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012350 return status;
12351 }
12352#ifdef WLAN_FEATURE_11W
12353 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12354#endif
12355
12356 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12357 if (req->ie_len) {
12358 status =
12359 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12360 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012361 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012362 return status;
12363 }
12364 }
12365
12366 /*incase of WEP set default key information */
12367 if (req->key && req->key_len) {
12368 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12369 || (WLAN_CIPHER_SUITE_WEP104 ==
12370 req->crypto.ciphers_pairwise[0])
12371 ) {
12372 if (IW_AUTH_KEY_MGMT_802_1X
12373 ==
12374 (pWextState->
12375 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012376 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012377 return -EOPNOTSUPP;
12378 } else {
12379 u8 key_len = req->key_len;
12380 u8 key_idx = req->key_idx;
12381
12382 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12383 key_len)
12384 && (CSR_MAX_NUM_KEY > key_idx)
12385 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012386 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012387 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012388 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012389 Keys.
12390 KeyMaterial[key_idx][0],
12391 req->key, key_len);
12392 pWextState->roamProfile.Keys.
12393 KeyLength[key_idx] = (u8) key_len;
12394 pWextState->roamProfile.Keys.
12395 defaultIndex = (u8) key_idx;
12396 }
12397 }
12398 }
12399 }
12400
12401 return status;
12402}
12403
12404/**
12405 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12406 * @pAdapter: Pointer to adapter
12407 *
12408 * This function is used to disconnect from previous connection
12409 *
12410 * Return: 0 for success, non-zero for failure
12411 */
12412static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12413{
12414 unsigned long rc;
12415 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012416 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012417
12418 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12419
Jeff Johnson9edf9572016-10-03 15:24:49 -070012420 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012421 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12422 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12423 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012424 hdd_conn_set_connection_state(pAdapter,
12425 eConnectionState_Disconnecting);
12426 /* Issue disconnect to CSR */
12427 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012428
12429 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12430 pAdapter->sessionId,
12431 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12432 /*
12433 * Wait here instead of returning directly, this will block the
12434 * next connect command and allow processing of the scan for
12435 * ssid and the previous connect command in CSR. Else we might
12436 * hit some race conditions leading to SME and HDD out of sync.
12437 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012438 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012439 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12440 } else if (0 != status) {
12441 hdd_err("csrRoamDisconnect failure, returned %d",
12442 (int)status);
12443 pHddStaCtx->staDebugState = status;
12444 result = -EINVAL;
12445 goto disconnected;
12446 }
12447
12448 rc = wait_for_completion_timeout(
12449 &pAdapter->disconnect_comp_var,
12450 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012451 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012452 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12453 pAdapter->sessionId, pHddStaCtx->staDebugState);
12454 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012455 }
12456 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012457 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012458 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012459 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012460 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012461 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012462 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012463 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012464 }
12465 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012466disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012467 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12468 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012469}
12470
12471/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012472 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12473 * @adapter: Pointer to the HDD adapter
12474 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012475 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012476 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012477 * This function will start reassociation if prev_bssid is set and bssid/
12478 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012479 *
Naveen Rawat07332902016-07-27 09:13:17 -070012480 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012481 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012482#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12483 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012484static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12485 struct cfg80211_connect_params *req,
12486 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012487{
Naveen Rawat07332902016-07-27 09:13:17 -070012488 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012489 const uint8_t *bssid = NULL;
12490 uint16_t channel = 0;
12491
12492 if (req->bssid)
12493 bssid = req->bssid;
12494 else if (req->bssid_hint)
12495 bssid = req->bssid_hint;
12496
12497 if (req->channel)
12498 channel = req->channel->hw_value;
12499 else if (req->channel_hint)
12500 channel = req->channel_hint->hw_value;
12501
12502 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012503 reassoc = true;
12504 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012505 channel, MAC_ADDR_ARRAY(bssid));
12506 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012507 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012508 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012509 }
Naveen Rawat07332902016-07-27 09:13:17 -070012510 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012511}
12512#else
Naveen Rawat07332902016-07-27 09:13:17 -070012513static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12514 struct cfg80211_connect_params *req,
12515 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012516{
Naveen Rawat07332902016-07-27 09:13:17 -070012517 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012518}
12519#endif
12520
12521/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012522 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12523 * @wiphy: Pointer to wiphy
12524 * @dev: Pointer to network device
12525 * @req: Pointer to cfg80211 connect request
12526 *
12527 * This function is used to start the association process
12528 *
12529 * Return: 0 for success, non-zero for failure
12530 */
12531static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12532 struct net_device *ndev,
12533 struct cfg80211_connect_params *req)
12534{
12535 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012536 u16 channel;
12537#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12538 const u8 *bssid_hint = req->bssid_hint;
12539#else
12540 const u8 *bssid_hint = NULL;
12541#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012542 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12543 hdd_context_t *pHddCtx;
12544
12545 ENTER();
12546
Anurag Chouhan6d760662016-02-20 16:05:43 +053012547 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012548 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012549 return -EINVAL;
12550 }
12551
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012552 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12553 hdd_err("invalid session id: %d", pAdapter->sessionId);
12554 return -EINVAL;
12555 }
12556
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012557 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012558 TRACE_CODE_HDD_CFG80211_CONNECT,
12559 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012560 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012561 hdd_device_mode_to_string(pAdapter->device_mode),
12562 pAdapter->device_mode);
12563
Krunal Sonib4326f22016-03-10 13:05:51 -080012564 if (pAdapter->device_mode != QDF_STA_MODE &&
12565 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012566 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012567 hdd_device_mode_to_string(pAdapter->device_mode),
12568 pAdapter->device_mode);
12569 return -EINVAL;
12570 }
12571
12572 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12573 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012574 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012575 return -EINVAL;
12576 }
12577
12578 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012579 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012580 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012581
Naveen Rawat07332902016-07-27 09:13:17 -070012582 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012583 return status;
12584
Agrawal Ashishf156e942016-08-04 14:54:47 +053012585 wlan_hdd_disable_roaming(pAdapter);
12586
12587 /* Try disconnecting if already in connected state */
12588 status = wlan_hdd_try_disconnect(pAdapter);
12589 if (0 > status) {
12590 hdd_err("Failed to disconnect the existing connection");
12591 return -EALREADY;
12592 }
12593
12594 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012595 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012596 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012597 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012598 pAdapter->device_mode),
12599 req->channel->hw_value, HW_MODE_20_MHZ)) {
12600 hdd_err("This concurrency combination is not allowed");
12601 return -ECONNREFUSED;
12602 }
12603 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012604 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012605 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012606 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12607 hdd_err("This concurrency combination is not allowed");
12608 return -ECONNREFUSED;
12609 }
12610 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012611
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012612 /*initialise security parameters */
12613 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12614
12615 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012616 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012617 return status;
12618 }
12619
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012620 if (req->channel)
12621 channel = req->channel->hw_value;
12622 else
12623 channel = 0;
12624 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12625 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012626 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012627 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012628 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012629 return status;
12630 }
12631 EXIT();
12632 return status;
12633}
12634
12635/**
12636 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12637 * @wiphy: Pointer to wiphy
12638 * @dev: Pointer to network device
12639 * @req: Pointer to cfg80211 connect request
12640 *
12641 * Return: 0 for success, non-zero for failure
12642 */
12643static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12644 struct net_device *ndev,
12645 struct cfg80211_connect_params *req)
12646{
12647 int ret;
12648 cds_ssr_protect(__func__);
12649 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12650 cds_ssr_unprotect(__func__);
12651
12652 return ret;
12653}
12654
12655/**
12656 * wlan_hdd_disconnect() - hdd disconnect api
12657 * @pAdapter: Pointer to adapter
12658 * @reason: Disconnect reason code
12659 *
12660 * This function is used to issue a disconnect request to SME
12661 *
12662 * Return: 0 for success, non-zero for failure
12663 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012664static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012665{
12666 int status, result = 0;
12667 unsigned long rc;
12668 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12669 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12670
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012671 ENTER();
12672
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012673 status = wlan_hdd_validate_context(pHddCtx);
12674
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012675 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012676 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012677
12678 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012679 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012680 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12681 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012682 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012683 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12684 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12685
12686 /*issue disconnect */
12687
12688 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12689 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012690 /*
12691 * Wait here instead of returning directly, this will block the next
12692 * connect command and allow processing of the scan for ssid and
12693 * the previous connect command in CSR. Else we might hit some
12694 * race conditions leading to SME and HDD out of sync.
12695 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012696 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012697 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012698 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012699 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012700 (int)status);
12701 pHddStaCtx->staDebugState = status;
12702 result = -EINVAL;
12703 goto disconnected;
12704 }
12705 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12706 msecs_to_jiffies
12707 (WLAN_WAIT_TIME_DISCONNECT));
12708
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012709 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012710 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012711 result = -ETIMEDOUT;
12712 }
12713disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012714 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12715#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12716 /* Sending disconnect event to userspace for kernel version < 3.11
12717 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12718 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012719 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012720 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12721 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012722#endif
12723
12724 return result;
12725}
12726
12727/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012728 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12729 * @reason: ieee80211 reason code.
12730 *
12731 * This utility function helps log string conversion of reason code.
12732 *
12733 * Return: string conversion of reason code, if match found;
12734 * "Unknown" otherwise.
12735 */
12736static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12737{
12738 switch (reason) {
12739 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12740 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12741 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12742 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12743 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12744 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12745 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12746 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12747 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12748 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12749 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12750 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12751 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12752 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12753 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12754 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12755 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12756 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12757 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12758 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12759 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12760 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12761 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12762 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12763 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12764 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12765 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12766 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12767 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12768 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12769 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12770 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12771 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12772 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12773 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12774 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12775 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12776 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12777 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12778 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12779 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12780 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12781 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12782 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12783 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12784 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12785 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12786 default:
12787 return "Unknown";
12788 }
12789}
12790
12791/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012792 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12793 * @wiphy: Pointer to wiphy
12794 * @dev: Pointer to network device
12795 * @reason: Disconnect reason code
12796 *
12797 * This function is used to issue a disconnect request to SME
12798 *
12799 * Return: 0 for success, non-zero for failure
12800 */
12801static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12802 struct net_device *dev, u16 reason)
12803{
12804 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12805 int status;
12806 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12807 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12808#ifdef FEATURE_WLAN_TDLS
12809 uint8_t staIdx;
12810#endif
12811
12812 ENTER();
12813
Anurag Chouhan6d760662016-02-20 16:05:43 +053012814 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012815 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012816 return -EINVAL;
12817 }
12818
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012819 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12820 hdd_err("invalid session id: %d", pAdapter->sessionId);
12821 return -EINVAL;
12822 }
12823
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012824 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012825 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12826 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012827 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012828 hdd_device_mode_to_string(pAdapter->device_mode),
12829 pAdapter->device_mode, reason);
12830
12831 status = wlan_hdd_validate_context(pHddCtx);
12832
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012833 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012834 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012835
12836 /* Issue disconnect request to SME, if station is in connected state */
12837 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12838 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12839 eCsrRoamDisconnectReason reasonCode =
12840 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12841 hdd_scaninfo_t *pScanInfo;
12842
12843 switch (reason) {
12844 case WLAN_REASON_MIC_FAILURE:
12845 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12846 break;
12847
12848 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12849 case WLAN_REASON_DISASSOC_AP_BUSY:
12850 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12851 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12852 break;
12853
12854 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12855 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12856 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12857 break;
12858
12859 case WLAN_REASON_DEAUTH_LEAVING:
12860 reasonCode =
12861 pHddCtx->config->
12862 gEnableDeauthToDisassocMap ?
12863 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12864 eCSR_DISCONNECT_REASON_DEAUTH;
12865 break;
12866 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12867 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12868 break;
12869 default:
12870 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12871 break;
12872 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012873 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012874 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012875 pScanInfo = &pAdapter->scan_info;
12876 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012877 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012878 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12879 eCSR_SCAN_ABORT_DEFAULT);
12880 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012881 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012882#ifdef FEATURE_WLAN_TDLS
12883 /* First clean up the tdls peers if any */
12884 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12885 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12886 pAdapter->sessionId)
12887 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12888 uint8_t *mac;
12889 mac =
12890 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012891 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12892 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012893 pHddCtx->tdlsConnInfo[staIdx].staId,
12894 pAdapter->sessionId,
12895 MAC_ADDR_ARRAY(mac));
12896 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12897 (pAdapter),
12898 pAdapter->sessionId, mac);
12899 }
12900 }
12901#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012902 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012903 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012904 hdd_info("Disconnect request from user space with reason: %s",
12905 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012906 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12907 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012908 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012909 return -EINVAL;
12910 }
12911 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012912 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012913 pHddStaCtx->conn_info.connState);
12914 }
12915
12916 return status;
12917}
12918
12919/**
12920 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12921 * @wiphy: Pointer to wiphy
12922 * @dev: Pointer to network device
12923 * @reason: Disconnect reason code
12924 *
12925 * Return: 0 for success, non-zero for failure
12926 */
12927static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12928 struct net_device *dev, u16 reason)
12929{
12930 int ret;
12931 cds_ssr_protect(__func__);
12932 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12933 cds_ssr_unprotect(__func__);
12934
12935 return ret;
12936}
12937
12938/**
12939 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12940 * @pAdapter: Pointer to adapter
12941 * @param: Pointer to IBSS parameters
12942 *
12943 * This function is used to initialize the security settings in IBSS mode
12944 *
12945 * Return: 0 for success, non-zero for failure
12946 */
12947static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12948 struct cfg80211_ibss_params
12949 *params)
12950{
12951 int status = 0;
12952 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12953 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12954 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12955
12956 ENTER();
12957
12958 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012959 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012960 pHddStaCtx->ibss_enc_key_installed = 0;
12961
12962 if (params->ie_len && (NULL != params->ie)) {
12963 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12964 params->ie_len, WLAN_EID_RSN)) {
12965 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12966 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12967 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
12968 tDot11fIEWPA dot11WPAIE;
12969 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12970 u8 *ie;
12971
12972 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12973 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12974 params->ie_len,
12975 DOT11F_EID_WPA);
12976 if (NULL != ie) {
12977 pWextState->wpaVersion =
12978 IW_AUTH_WPA_VERSION_WPA;
12979 /* Unpack the WPA IE */
12980 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
12981 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
12982 &ie[2 + 4],
12983 ie[1] - 4, &dot11WPAIE);
12984 /*Extract the multicast cipher, the encType for unicast
12985 cipher for wpa-none is none */
12986 encryptionType =
12987 hdd_translate_wpa_to_csr_encryption_type
12988 (dot11WPAIE.multicast_cipher);
12989 }
12990 }
12991
12992 status =
12993 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
12994 params->ie_len);
12995
12996 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012997 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012998 return status;
12999 }
13000 }
13001
13002 pWextState->roamProfile.AuthType.authType[0] =
13003 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13004
13005 if (params->privacy) {
13006 /* Security enabled IBSS, At this time there is no information
13007 * available about the security paramters, so initialise the
13008 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
13009 * The correct security parameters will be updated later in
13010 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
13011 * set inorder enable privacy bit in beacons
13012 */
13013
13014 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
13015 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013016 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013017 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13018 pWextState->roamProfile.EncryptionType.numEntries = 1;
13019 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13020 encryptionType;
13021 return status;
13022}
13023
13024/**
13025 * __wlan_hdd_cfg80211_join_ibss() - join ibss
13026 * @wiphy: Pointer to wiphy
13027 * @dev: Pointer to network device
13028 * @param: Pointer to IBSS join parameters
13029 *
13030 * This function is used to create/join an IBSS network
13031 *
13032 * Return: 0 for success, non-zero for failure
13033 */
13034static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13035 struct net_device *dev,
13036 struct cfg80211_ibss_params *params)
13037{
13038 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13039 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13040 tCsrRoamProfile *pRoamProfile;
13041 int status;
13042 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13043 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053013044 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013045 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013046
13047 ENTER();
13048
Anurag Chouhan6d760662016-02-20 16:05:43 +053013049 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013050 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013051 return -EINVAL;
13052 }
13053
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013054 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13055 hdd_err("invalid session id: %d", pAdapter->sessionId);
13056 return -EINVAL;
13057 }
13058
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013059 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013060 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
13061 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013062 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013063 hdd_device_mode_to_string(pAdapter->device_mode),
13064 pAdapter->device_mode);
13065
13066 status = wlan_hdd_validate_context(pHddCtx);
13067
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013068 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013069 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013070
13071 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053013072 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013073 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
13074 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
13075 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13076 int indx;
13077
13078 /* Get channel number */
13079 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013080 params->
13081 chandef.
13082 chan->
13083 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013084
13085 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
13086 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013087 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013088 return -EOPNOTSUPP;
13089 }
13090
13091 for (indx = 0; indx < numChans; indx++) {
13092 if (channelNum == validChan[indx]) {
13093 break;
13094 }
13095 }
13096 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013097 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013098 return -EINVAL;
13099 }
13100 }
13101
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013102 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013103 HW_MODE_20_MHZ)) {
13104 hdd_err("This concurrency combination is not allowed");
13105 return -ECONNREFUSED;
13106 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013107
Krunal Soni3091bcc2016-06-23 12:28:21 -070013108 status = qdf_reset_connection_update();
13109 if (!QDF_IS_STATUS_SUCCESS(status))
13110 hdd_err("ERR: clear event failed");
13111
13112 status = cds_current_connections_update(pAdapter->sessionId,
13113 channelNum,
13114 SIR_UPDATE_REASON_JOIN_IBSS);
13115 if (QDF_STATUS_E_FAILURE == status) {
13116 hdd_err("ERROR: connections update failed!!");
13117 return -EINVAL;
13118 }
13119
13120 if (QDF_STATUS_SUCCESS == status) {
13121 status = qdf_wait_for_connection_update();
13122 if (!QDF_IS_STATUS_SUCCESS(status)) {
13123 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013124 return -EINVAL;
13125 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013126 }
13127
13128 /*Try disconnecting if already in connected state */
13129 status = wlan_hdd_try_disconnect(pAdapter);
13130 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013131 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013132 return -EALREADY;
13133 }
13134
13135 pRoamProfile = &pWextState->roamProfile;
13136
13137 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013138 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013139 return -EINVAL;
13140 }
13141
13142 /* enable selected protection checks in IBSS mode */
13143 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
13144
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013145 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013146 WNI_CFG_IBSS_ATIM_WIN_SIZE,
13147 pHddCtx->config->
13148 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013149 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013150 }
13151
13152 /* BSSID is provided by upper layers hence no need to AUTO generate */
13153 if (NULL != params->bssid) {
13154 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013155 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013156 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013157 return -EIO;
13158 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013159 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013160 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
13161 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013162 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013163 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013164 return -EIO;
13165 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053013166 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013167 }
13168 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13169 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13170 pRoamProfile->beaconInterval = params->beacon_interval;
13171 else {
13172 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013173 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013174 params->beacon_interval, pRoamProfile->beaconInterval);
13175 }
13176
13177 /* Set Channel */
13178 if (channelNum) {
13179 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013180 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013181 pRoamProfile->ChannelInfo.numOfChannels = 1;
13182 pHddStaCtx->conn_info.operationChannel = channelNum;
13183 pRoamProfile->ChannelInfo.ChannelList =
13184 &pHddStaCtx->conn_info.operationChannel;
13185 }
13186
13187 /* Initialize security parameters */
13188 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13189 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013190 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013191 return status;
13192 }
13193
13194 /* Issue connect start */
13195 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13196 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013197 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013198 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013199 operationChannel,
13200 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013201
13202 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013203 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013204 return status;
13205 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013206 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013207 return 0;
13208}
13209
13210/**
13211 * wlan_hdd_cfg80211_join_ibss() - join ibss
13212 * @wiphy: Pointer to wiphy
13213 * @dev: Pointer to network device
13214 * @param: Pointer to IBSS join parameters
13215 *
13216 * This function is used to create/join an IBSS network
13217 *
13218 * Return: 0 for success, non-zero for failure
13219 */
13220static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13221 struct net_device *dev,
13222 struct cfg80211_ibss_params *params)
13223{
13224 int ret = 0;
13225
13226 cds_ssr_protect(__func__);
13227 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13228 cds_ssr_unprotect(__func__);
13229
13230 return ret;
13231}
13232
13233/**
13234 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13235 * @wiphy: Pointer to wiphy
13236 * @dev: Pointer to network device
13237 *
13238 * This function is used to leave an IBSS network
13239 *
13240 * Return: 0 for success, non-zero for failure
13241 */
13242static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13243 struct net_device *dev)
13244{
13245 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13246 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13247 tCsrRoamProfile *pRoamProfile;
13248 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13249 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013250 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013251 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013252 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013253
13254 ENTER();
13255
Anurag Chouhan6d760662016-02-20 16:05:43 +053013256 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013257 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013258 return -EINVAL;
13259 }
13260
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013261 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13262 hdd_err("invalid session id: %d", pAdapter->sessionId);
13263 return -EINVAL;
13264 }
13265
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013266 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013267 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13268 pAdapter->sessionId,
13269 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13270 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013271 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013272 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013273
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013274 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013275 hdd_device_mode_to_string(pAdapter->device_mode),
13276 pAdapter->device_mode);
13277 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013278 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013279 return -EIO;
13280 }
13281
13282 pRoamProfile = &pWextState->roamProfile;
13283
13284 /* Issue disconnect only if interface type is set to IBSS */
13285 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013286 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013287 return -EINVAL;
13288 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013289 /* Clearing add IE of beacon */
13290 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13291 sizeof(tSirMacAddr));
13292 updateIE.smeSessionId = pAdapter->sessionId;
13293 updateIE.ieBufferlength = 0;
13294 updateIE.pAdditionIEBuffer = NULL;
13295 updateIE.append = true;
13296 updateIE.notify = true;
13297 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13298 &updateIE,
13299 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013300 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013301 }
13302
13303 /* Reset WNI_CFG_PROBE_RSP Flags */
13304 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013305
13306 /* Issue Disconnect request */
13307 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13308 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13309 pAdapter->sessionId,
13310 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013311 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013312 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013313 hal_status);
13314 return -EAGAIN;
13315 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013316
13317 /* wait for mc thread to cleanup and then return to upper stack
13318 * so by the time upper layer calls the change interface, we are
13319 * all set to proceed further
13320 */
13321 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13322 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13323 if (!rc) {
13324 hdd_err("Failed to disconnect, timed out");
13325 return -ETIMEDOUT;
13326 }
13327
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013328 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013329 return 0;
13330}
13331
13332/**
13333 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13334 * @wiphy: Pointer to wiphy
13335 * @dev: Pointer to network device
13336 *
13337 * This function is used to leave an IBSS network
13338 *
13339 * Return: 0 for success, non-zero for failure
13340 */
13341static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13342 struct net_device *dev)
13343{
13344 int ret = 0;
13345
13346 cds_ssr_protect(__func__);
13347 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13348 cds_ssr_unprotect(__func__);
13349
13350 return ret;
13351}
13352
13353/**
13354 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13355 * @wiphy: Pointer to wiphy
13356 * @changed: Parameters changed
13357 *
13358 * This function is used to set the phy parameters. RTS Threshold/FRAG
13359 * Threshold/Retry Count etc.
13360 *
13361 * Return: 0 for success, non-zero for failure
13362 */
13363static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13364 u32 changed)
13365{
13366 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13367 tHalHandle hHal = pHddCtx->hHal;
13368 int status;
13369
13370 ENTER();
13371
Anurag Chouhan6d760662016-02-20 16:05:43 +053013372 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013373 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013374 return -EINVAL;
13375 }
13376
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013377 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013378 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13379 NO_SESSION, wiphy->rts_threshold));
13380 status = wlan_hdd_validate_context(pHddCtx);
13381
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013382 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013383 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013384
13385 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13386 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13387 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13388
13389 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13390 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013391 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013392 rts_threshold);
13393 return -EINVAL;
13394 }
13395
13396 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13397 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013398 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013399 rts_threshold);
13400 return -EIO;
13401 }
13402
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013403 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013404 }
13405
13406 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13407 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13408 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13409 wiphy->frag_threshold;
13410
13411 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13412 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013413 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013414 frag_threshold);
13415 return -EINVAL;
13416 }
13417
13418 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13419 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013420 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013421 frag_threshold);
13422 return -EIO;
13423 }
13424
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013425 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013426 }
13427
13428 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13429 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13430 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13431 wiphy->retry_short : wiphy->retry_long;
13432
13433 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13434 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013435 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013436 return -EINVAL;
13437 }
13438
13439 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13440 if (0 != sme_cfg_set_int(hHal,
13441 WNI_CFG_LONG_RETRY_LIMIT,
13442 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013443 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013444 retry_value);
13445 return -EIO;
13446 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013447 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013448 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13449 if (0 != sme_cfg_set_int(hHal,
13450 WNI_CFG_SHORT_RETRY_LIMIT,
13451 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013452 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013453 retry_value);
13454 return -EIO;
13455 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013456 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013457 }
13458 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013459 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013460 return 0;
13461}
13462
13463/**
13464 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13465 * @wiphy: Pointer to wiphy
13466 * @changed: Parameters changed
13467 *
13468 * Return: 0 for success, non-zero for failure
13469 */
13470static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13471{
13472 int ret;
13473
13474 cds_ssr_protect(__func__);
13475 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13476 cds_ssr_unprotect(__func__);
13477
13478 return ret;
13479}
13480
13481/**
13482 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13483 * key
13484 * @wiphy: Pointer to wiphy
13485 * @dev: Pointer to network device
13486 * @key_index: Key index
13487 *
13488 * Return: 0
13489 */
13490static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13491 struct net_device *netdev,
13492 u8 key_index)
13493{
13494 ENTER();
13495 return 0;
13496}
13497
13498/**
13499 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13500 * wlan_hdd_set_default_mgmt_key
13501 * @wiphy: pointer to wiphy
13502 * @netdev: pointer to net_device structure
13503 * @key_index: key index
13504 *
13505 * Return: 0 on success, error number on failure
13506 */
13507static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13508 struct net_device *netdev,
13509 u8 key_index)
13510{
13511 int ret;
13512
13513 cds_ssr_protect(__func__);
13514 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13515 cds_ssr_unprotect(__func__);
13516
13517 return ret;
13518}
13519
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013520/**
13521 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13522 * @wiphy: Pointer to wiphy
13523 * @dev: Pointer to network device
13524 * @params: Pointer to tx queue parameters
13525 *
13526 * Return: 0
13527 */
13528static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13529 struct net_device *dev,
13530 struct ieee80211_txq_params *params)
13531{
13532 ENTER();
13533 return 0;
13534}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013535
13536/**
13537 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13538 * @wiphy: pointer to wiphy
13539 * @netdev: pointer to net_device structure
13540 * @params: pointer to ieee80211_txq_params
13541 *
13542 * Return: 0 on success, error number on failure
13543 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013544static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13545 struct net_device *dev,
13546 struct ieee80211_txq_params *params)
13547{
13548 int ret;
13549
13550 cds_ssr_protect(__func__);
13551 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13552 cds_ssr_unprotect(__func__);
13553
13554 return ret;
13555}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013556
13557/**
13558 * __wlan_hdd_cfg80211_del_station() - delete station v2
13559 * @wiphy: Pointer to wiphy
13560 * @param: Pointer to delete station parameter
13561 *
13562 * Return: 0 for success, non-zero for failure
13563 */
13564static
13565int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13566 struct net_device *dev,
13567 struct tagCsrDelStaParams *pDelStaParams)
13568{
13569 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13570 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013571 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013572 hdd_hostapd_state_t *hapd_state;
13573 int status;
13574 uint8_t staId;
13575 uint8_t *mac;
13576
13577 ENTER();
13578
Anurag Chouhan6d760662016-02-20 16:05:43 +053013579 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013580 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013581 return -EINVAL;
13582 }
13583
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013584 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13585 hdd_err("invalid session id: %d", pAdapter->sessionId);
13586 return -EINVAL;
13587 }
13588
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013589 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013590 TRACE_CODE_HDD_CFG80211_DEL_STA,
13591 pAdapter->sessionId, pAdapter->device_mode));
13592
13593 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13594 status = wlan_hdd_validate_context(pHddCtx);
13595
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013596 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013597 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013598
13599 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13600
Krunal Sonib4326f22016-03-10 13:05:51 -080013601 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13602 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013603
13604 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13605 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013606 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013607 return 0;
13608 }
13609
Anurag Chouhanc5548422016-02-24 18:33:27 +053013610 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013611 uint16_t i;
13612 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13613 if ((pAdapter->aStaInfo[i].isUsed) &&
13614 (!pAdapter->aStaInfo[i].
13615 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013616 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013617 mac,
13618 pAdapter->aStaInfo[i].
13619 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013620 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013621 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13622 hdd_ipa_wlan_evt(pAdapter,
13623 pAdapter->
13624 aStaInfo[i].
13625 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013626 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013627 mac);
13628 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013629 hdd_notice("Delete STA with MAC::"
13630 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013631 MAC_ADDR_ARRAY(mac));
13632
13633 if (pHddCtx->dev_dfs_cac_status ==
13634 DFS_CAC_IN_PROGRESS)
13635 goto fn_end;
13636
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013637 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013638 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013639 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013640 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013641 hdd_softap_sta_deauth(pAdapter,
13642 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013643 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013644 pAdapter->aStaInfo[i].
13645 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013646 qdf_status =
13647 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013648 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013649 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013650 if (!QDF_IS_STATUS_SUCCESS(
13651 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013652 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013653 }
13654 }
13655 }
13656 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013657 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013658 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013659 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013661 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013662 hdd_notice("Skip DEL STA as this is not used::"
13663 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013664 MAC_ADDR_ARRAY(mac));
13665 return -ENOENT;
13666 }
13667
13668 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13669 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013670 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013671 }
13672
13673 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13674 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013675 hdd_notice("Skip DEL STA as deauth is in progress::"
13676 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013677 MAC_ADDR_ARRAY(mac));
13678 return -ENOENT;
13679 }
13680
13681 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13682
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013683 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013684 MAC_ADDR_ARRAY(mac));
13685
13686 /* Case: SAP in ACS selected DFS ch and client connected
13687 * Now Radar detected. Then if random channel is another
13688 * DFS ch then new CAC is initiated and no TX allowed.
13689 * So do not send any mgmt frames as it will timeout
13690 * during CAC.
13691 */
13692
13693 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13694 goto fn_end;
13695
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013696 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013697 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13698 (pAdapter), pAdapter->sessionId,
13699 (uint8_t *)&pDelStaParams->peerMacAddr,
13700 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013701 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013702 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013703 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013704 pAdapter->aStaInfo[staId].isDeauthInProgress =
13705 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013706 hdd_notice("STA removal failed for ::"
13707 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013708 MAC_ADDR_ARRAY(mac));
13709 return -ENOENT;
13710 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013711 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013712 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013713 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013714 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013715 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013716 }
13717 }
13718 }
13719
13720fn_end:
13721 EXIT();
13722 return 0;
13723}
13724
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013725#if defined(USE_CFG80211_DEL_STA_V2)
13726/**
13727 * wlan_hdd_del_station() - delete station wrapper
13728 * @adapter: pointer to the hdd adapter
13729 *
13730 * Return: None
13731 */
13732void wlan_hdd_del_station(hdd_adapter_t *adapter)
13733{
13734 struct station_del_parameters del_sta;
13735 del_sta.mac = NULL;
13736 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13737 del_sta.reason_code = eCsrForcedDeauthSta;
13738
13739 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13740 &del_sta);
13741}
13742#else
13743void wlan_hdd_del_station(hdd_adapter_t *adapter)
13744{
13745 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13746}
13747#endif
13748
13749#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013750/**
13751 * wlan_hdd_cfg80211_del_station() - delete station v2
13752 * @wiphy: Pointer to wiphy
13753 * @param: Pointer to delete station parameter
13754 *
13755 * Return: 0 for success, non-zero for failure
13756 */
13757int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13758 struct net_device *dev,
13759 struct station_del_parameters *param)
13760#else
13761/**
13762 * wlan_hdd_cfg80211_del_station() - delete station
13763 * @wiphy: Pointer to wiphy
13764 * @mac: Pointer to station mac address
13765 *
13766 * Return: 0 for success, non-zero for failure
13767 */
13768#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13769int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13770 struct net_device *dev,
13771 const uint8_t *mac)
13772#else
13773int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13774 struct net_device *dev,
13775 uint8_t *mac)
13776#endif
13777#endif
13778{
13779 int ret;
13780 struct tagCsrDelStaParams delStaParams;
13781
13782 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013783#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013784 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013785 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013786 return -EINVAL;
13787 }
13788 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13789 param->subtype, &delStaParams);
13790#else
13791 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13792 (SIR_MAC_MGMT_DEAUTH >> 4),
13793 &delStaParams);
13794#endif
13795 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13796 cds_ssr_unprotect(__func__);
13797
13798 return ret;
13799}
13800
13801/**
13802 * __wlan_hdd_cfg80211_add_station() - add station
13803 * @wiphy: Pointer to wiphy
13804 * @mac: Pointer to station mac address
13805 * @pmksa: Pointer to add station parameter
13806 *
13807 * Return: 0 for success, non-zero for failure
13808 */
13809static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13810 struct net_device *dev,
13811 const uint8_t *mac,
13812 struct station_parameters *params)
13813{
13814 int status = -EPERM;
13815#ifdef FEATURE_WLAN_TDLS
13816 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13817 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13818 u32 mask, set;
13819
13820 ENTER();
13821
Anurag Chouhan6d760662016-02-20 16:05:43 +053013822 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013823 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013824 return -EINVAL;
13825 }
13826
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013827 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13828 hdd_err("invalid session id: %d", pAdapter->sessionId);
13829 return -EINVAL;
13830 }
13831
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013832 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013833 TRACE_CODE_HDD_CFG80211_ADD_STA,
13834 pAdapter->sessionId, params->listen_interval));
13835
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013836 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013837 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013838
13839 mask = params->sta_flags_mask;
13840
13841 set = params->sta_flags_set;
13842
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013843 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013844 MAC_ADDR_ARRAY(mac));
13845
13846 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13847 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13848 status =
13849 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13850 }
13851 }
13852#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013853 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013854 return status;
13855}
13856
13857/**
13858 * wlan_hdd_cfg80211_add_station() - add station
13859 * @wiphy: Pointer to wiphy
13860 * @mac: Pointer to station mac address
13861 * @pmksa: Pointer to add station parameter
13862 *
13863 * Return: 0 for success, non-zero for failure
13864 */
13865#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13866static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13867 struct net_device *dev,
13868 const uint8_t *mac,
13869 struct station_parameters *params)
13870#else
13871static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13872 struct net_device *dev, uint8_t *mac,
13873 struct station_parameters *params)
13874#endif
13875{
13876 int ret;
13877
13878 cds_ssr_protect(__func__);
13879 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13880 cds_ssr_unprotect(__func__);
13881
13882 return ret;
13883}
13884
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013885/**
13886 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13887 * @wiphy: Pointer to wiphy
13888 * @dev: Pointer to network device
13889 * @pmksa: Pointer to set pmksa parameter
13890 *
13891 * Return: 0 for success, non-zero for failure
13892 */
13893static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13894 struct net_device *dev,
13895 struct cfg80211_pmksa *pmksa)
13896{
13897 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13898 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13899 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013900 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013901 int status;
13902 tPmkidCacheInfo pmk_id;
13903
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013904 ENTER();
13905
Anurag Chouhan6d760662016-02-20 16:05:43 +053013906 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013907 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013908 return -EINVAL;
13909 }
13910
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013911 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13912 hdd_err("invalid session id: %d", pAdapter->sessionId);
13913 return -EINVAL;
13914 }
13915
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013916 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013917 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013918 return -EINVAL;
13919 }
13920
13921 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013922 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013923 pmksa->bssid, pmksa->pmkid);
13924 return -EINVAL;
13925 }
13926
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013927 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013928 MAC_ADDR_ARRAY(pmksa->bssid));
13929
13930 status = wlan_hdd_validate_context(pHddCtx);
13931
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013932 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013933 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013934
13935 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13936
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013937 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13938 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013939
13940 /* Add to the PMKSA ID Cache in CSR */
13941 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13942 &pmk_id, 1, false);
13943
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013944 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013945 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
13946 pAdapter->sessionId, result));
13947
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013948 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013949 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013950}
13951
13952/**
13953 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13954 * @wiphy: Pointer to wiphy
13955 * @dev: Pointer to network device
13956 * @pmksa: Pointer to set pmksa parameter
13957 *
13958 * Return: 0 for success, non-zero for failure
13959 */
13960static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13961 struct net_device *dev,
13962 struct cfg80211_pmksa *pmksa)
13963{
13964 int ret;
13965
13966 cds_ssr_protect(__func__);
13967 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
13968 cds_ssr_unprotect(__func__);
13969
13970 return ret;
13971}
13972
13973/**
13974 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13975 * @wiphy: Pointer to wiphy
13976 * @dev: Pointer to network device
13977 * @pmksa: Pointer to pmksa parameter
13978 *
13979 * Return: 0 for success, non-zero for failure
13980 */
13981static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13982 struct net_device *dev,
13983 struct cfg80211_pmksa *pmksa)
13984{
13985 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13986 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13987 tHalHandle halHandle;
13988 int status = 0;
13989
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013990 ENTER();
13991
Anurag Chouhan6d760662016-02-20 16:05:43 +053013992 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013993 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013994 return -EINVAL;
13995 }
13996
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013997 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13998 hdd_err("invalid session id: %d", pAdapter->sessionId);
13999 return -EINVAL;
14000 }
14001
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014002 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014003 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014004 return -EINVAL;
14005 }
14006
14007 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014008 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014009 return -EINVAL;
14010 }
14011
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014012 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014013 MAC_ADDR_ARRAY(pmksa->bssid));
14014
14015 status = wlan_hdd_validate_context(pHddCtx);
14016
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014017 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014018 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014019
14020 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14021
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014022 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014023 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
14024 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014025 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014026 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014027 sme_roam_del_pmkid_from_cache(halHandle,
14028 pAdapter->sessionId, pmksa->bssid,
14029 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014030 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014031 MAC_ADDR_ARRAY(pmksa->bssid));
14032 status = -EINVAL;
14033 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014034 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014035 return status;
14036}
14037
14038/**
14039 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14040 * @wiphy: Pointer to wiphy
14041 * @dev: Pointer to network device
14042 * @pmksa: Pointer to pmksa parameter
14043 *
14044 * Return: 0 for success, non-zero for failure
14045 */
14046static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14047 struct net_device *dev,
14048 struct cfg80211_pmksa *pmksa)
14049{
14050 int ret;
14051
14052 cds_ssr_protect(__func__);
14053 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
14054 cds_ssr_unprotect(__func__);
14055
14056 return ret;
14057
14058}
14059
14060/**
14061 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14062 * @wiphy: Pointer to wiphy
14063 * @dev: Pointer to network device
14064 *
14065 * Return: 0 for success, non-zero for failure
14066 */
14067static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14068 struct net_device *dev)
14069{
14070 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14071 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14072 tHalHandle halHandle;
14073 int status = 0;
14074
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014075 ENTER();
14076
Anurag Chouhan6d760662016-02-20 16:05:43 +053014077 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014078 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014079 return -EINVAL;
14080 }
14081
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014082 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14083 hdd_err("invalid session id: %d", pAdapter->sessionId);
14084 return -EINVAL;
14085 }
14086
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014087 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014088
14089 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14090 status = wlan_hdd_validate_context(pHddCtx);
14091
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014092 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014093 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014094
14095 /* Retrieve halHandle */
14096 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14097
14098 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014099 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014100 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
14101 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014102 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014103 status = -EINVAL;
14104 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014105 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014106 return status;
14107}
14108
14109/**
14110 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14111 * @wiphy: Pointer to wiphy
14112 * @dev: Pointer to network device
14113 *
14114 * Return: 0 for success, non-zero for failure
14115 */
14116static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14117 struct net_device *dev)
14118{
14119 int ret;
14120
14121 cds_ssr_protect(__func__);
14122 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
14123 cds_ssr_unprotect(__func__);
14124
14125 return ret;
14126}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014127
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014128#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014129/**
14130 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14131 * @wiphy: Pointer to wiphy
14132 * @dev: Pointer to network device
14133 * @ftie: Pointer to fast transition ie parameter
14134 *
14135 * Return: 0 for success, non-zero for failure
14136 */
14137static int
14138__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14139 struct net_device *dev,
14140 struct cfg80211_update_ft_ies_params *ftie)
14141{
14142 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14143 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14144 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14145 int status;
14146
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014147 ENTER();
14148
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014149 status = wlan_hdd_validate_context(hdd_ctx);
14150 if (status)
14151 return status;
14152
Anurag Chouhan6d760662016-02-20 16:05:43 +053014153 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014154 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014155 return -EINVAL;
14156 }
14157
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014158 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14159 hdd_err("invalid session id: %d", pAdapter->sessionId);
14160 return -EINVAL;
14161 }
14162
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014163 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014164 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
14165 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
14166 /* Added for debug on reception of Re-assoc Req. */
14167 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014168 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014169 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014170 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014171 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014172 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014173 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014174
14175 /* Pass the received FT IEs to SME */
14176 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
14177 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014178 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014179 return 0;
14180}
14181
14182/**
14183 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14184 * @wiphy: Pointer to wiphy
14185 * @dev: Pointer to network device
14186 * @ftie: Pointer to fast transition ie parameter
14187 *
14188 * Return: 0 for success, non-zero for failure
14189 */
14190static int
14191wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14192 struct net_device *dev,
14193 struct cfg80211_update_ft_ies_params *ftie)
14194{
14195 int ret;
14196
14197 cds_ssr_protect(__func__);
14198 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14199 cds_ssr_unprotect(__func__);
14200
14201 return ret;
14202}
14203#endif
14204
14205#ifdef WLAN_FEATURE_GTK_OFFLOAD
14206/**
14207 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14208 * @callbackContext: Callback context
14209 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14210 *
14211 * Callback rountine called upon receiving response for get offload info
14212 *
14213 * Return: none
14214 */
14215void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14216 tpSirGtkOffloadGetInfoRspParams
14217 pGtkOffloadGetInfoRsp)
14218{
14219 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14220 uint8_t tempReplayCounter[8];
14221 hdd_station_ctx_t *pHddStaCtx;
14222
14223 ENTER();
14224
14225 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014226 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014227 return;
14228 }
14229
14230 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014231 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014232 return;
14233 }
14234
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014235 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014236 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014237 return;
14238 }
14239
14240 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14241 /* Update replay counter */
14242 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14243 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14244
14245 {
14246 /* changing from little to big endian since supplicant
14247 * works on big endian format
14248 */
14249 int i;
14250 uint8_t *p =
14251 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14252
14253 for (i = 0; i < 8; i++) {
14254 tempReplayCounter[7 - i] = (uint8_t) p[i];
14255 }
14256 }
14257
14258 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014259 cfg80211_gtk_rekey_notify(pAdapter->dev,
14260 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014261 tempReplayCounter, GFP_KERNEL);
14262}
14263
14264/**
14265 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14266 * @wiphy: Pointer to wiphy
14267 * @dev: Pointer to network device
14268 * @data: Pointer to rekey data
14269 *
14270 * This function is used to offload GTK rekeying job to the firmware.
14271 *
14272 * Return: 0 for success, non-zero for failure
14273 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014274static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014275int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14276 struct net_device *dev,
14277 struct cfg80211_gtk_rekey_data *data)
14278{
14279 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14280 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14281 hdd_station_ctx_t *pHddStaCtx;
14282 tHalHandle hHal;
14283 int result;
14284 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014285 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014286
14287 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
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014299 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014300 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14301 pAdapter->sessionId, pAdapter->device_mode));
14302
14303 result = wlan_hdd_validate_context(pHddCtx);
14304
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014305 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014306 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014307
14308 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14309 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14310 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014311 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014312 return -EAGAIN;
14313 }
14314
14315 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14316 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14317 NL80211_KCK_LEN);
14318 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14319 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014320 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014321 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014322 {
14323 /* changing from big to little endian since driver
14324 * works on little endian format
14325 */
14326 uint8_t *p =
14327 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14328 ullKeyReplayCounter;
14329 int i;
14330
14331 for (i = 0; i < 8; i++) {
14332 p[7 - i] = data->replay_ctr[i];
14333 }
14334 }
14335
14336 if (true == pHddCtx->hdd_wlan_suspended) {
14337 /* if wlan is suspended, enable GTK offload directly from here */
14338 memcpy(&hddGtkOffloadReqParams,
14339 &pHddStaCtx->gtkOffloadReqParams,
14340 sizeof(tSirGtkOffloadParams));
14341 status =
14342 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14343 pAdapter->sessionId);
14344
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014345 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014346 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347 status);
14348 return -EINVAL;
14349 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014350 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014351 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014352 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014353 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014354 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014355 return result;
14356}
14357
14358/**
14359 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14360 * @wiphy: Pointer to wiphy
14361 * @dev: Pointer to network device
14362 * @data: Pointer to rekey data
14363 *
14364 * This function is used to offload GTK rekeying job to the firmware.
14365 *
14366 * Return: 0 for success, non-zero for failure
14367 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014368static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014369int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14370 struct net_device *dev,
14371 struct cfg80211_gtk_rekey_data *data)
14372{
14373 int ret;
14374
14375 cds_ssr_protect(__func__);
14376 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14377 cds_ssr_unprotect(__func__);
14378
14379 return ret;
14380}
14381#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14382
14383/**
14384 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14385 * @wiphy: Pointer to wiphy
14386 * @dev: Pointer to network device
14387 * @param: Pointer to access control parameter
14388 *
14389 * Return: 0 for success, non-zero for failure
14390 */
14391static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14392 struct net_device *dev,
14393 const struct cfg80211_acl_data *params)
14394{
14395 int i;
14396 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14397 hdd_hostapd_state_t *pHostapdState;
14398 tsap_Config_t *pConfig;
14399 v_CONTEXT_t p_cds_context = NULL;
14400 hdd_context_t *pHddCtx;
14401 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014402 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014403
14404 ENTER();
14405
Anurag Chouhan6d760662016-02-20 16:05:43 +053014406 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014407 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014408 return -EINVAL;
14409 }
14410
14411 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014412 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014413 return -EINVAL;
14414 }
14415
14416 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14417 status = wlan_hdd_validate_context(pHddCtx);
14418
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014419 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014420 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014421
14422 p_cds_context = pHddCtx->pcds_context;
14423 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14424
14425 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014426 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014427 return -EINVAL;
14428 }
14429
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014430 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014431 params->n_acl_entries);
14432
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014433 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014434 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14435 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014436 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014437 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14438
14439 /* default value */
14440 pConfig->num_accept_mac = 0;
14441 pConfig->num_deny_mac = 0;
14442
14443 /**
14444 * access control policy
14445 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14446 * listed in hostapd.deny file.
14447 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14448 * listed in hostapd.accept file.
14449 */
14450 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14451 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14452 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14453 params->acl_policy) {
14454 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14455 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014456 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014457 params->acl_policy);
14458 return -ENOTSUPP;
14459 }
14460
14461 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14462 pConfig->num_accept_mac = params->n_acl_entries;
14463 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014464 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14465 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014466 MAC_ADDR_ARRAY(
14467 params->mac_addrs[i].addr));
14468
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014469 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014470 params->mac_addrs[i].addr,
14471 sizeof(qcmacaddr));
14472 }
14473 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14474 pConfig->num_deny_mac = params->n_acl_entries;
14475 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014476 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14477 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014478 MAC_ADDR_ARRAY(
14479 params->mac_addrs[i].addr));
14480
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014481 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014482 params->mac_addrs[i].addr,
14483 sizeof(qcmacaddr));
14484 }
14485 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014486 qdf_status = wlansap_set_mac_acl(
14487 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014488 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014489 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014490 return -EINVAL;
14491 }
14492 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014493 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014494 hdd_device_mode_to_string(pAdapter->device_mode),
14495 pAdapter->device_mode);
14496 return -EINVAL;
14497 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014498 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014499 return 0;
14500}
14501
14502/**
14503 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14504 * __wlan_hdd_cfg80211_set_mac_acl
14505 * @wiphy: pointer to wiphy structure
14506 * @dev: pointer to net_device
14507 * @params: pointer to cfg80211_acl_data
14508 *
14509 * Return; 0 on success, error number otherwise
14510 */
14511static int
14512wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14513 struct net_device *dev,
14514 const struct cfg80211_acl_data *params)
14515{
14516 int ret;
14517
14518 cds_ssr_protect(__func__);
14519 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14520 cds_ssr_unprotect(__func__);
14521
14522 return ret;
14523}
14524
14525#ifdef WLAN_NL80211_TESTMODE
14526#ifdef FEATURE_WLAN_LPHB
14527/**
14528 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14529 * @pHddCtx: Pointer to hdd context
14530 * @lphbInd: Pointer to low power heart beat indication parameter
14531 *
14532 * Return: none
14533 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014534static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14535 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014536{
14537 struct sk_buff *skb;
14538
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014539 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014540
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014541 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014542 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014543
14544 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014545 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014546 return;
14547 }
14548
14549 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14550 wiphy, sizeof(tSirLPHBInd),
14551 GFP_ATOMIC);
14552 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014553 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014554 return;
14555 }
14556
14557 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014558 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014559 goto nla_put_failure;
14560 }
14561 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014562 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014563 goto nla_put_failure;
14564 }
14565 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014566 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014567 goto nla_put_failure;
14568 }
14569 cfg80211_testmode_event(skb, GFP_ATOMIC);
14570 return;
14571
14572nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014573 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014574 kfree_skb(skb);
14575
14576 return;
14577}
14578#endif /* FEATURE_WLAN_LPHB */
14579
14580/**
14581 * __wlan_hdd_cfg80211_testmode() - test mode
14582 * @wiphy: Pointer to wiphy
14583 * @data: Data pointer
14584 * @len: Data length
14585 *
14586 * Return: 0 for success, non-zero for failure
14587 */
14588static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14589 void *data, int len)
14590{
14591 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14592 int err;
14593 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14594
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014595 ENTER();
14596
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014597 err = wlan_hdd_validate_context(pHddCtx);
14598 if (err)
14599 return err;
14600
14601 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14602 len, wlan_hdd_tm_policy);
14603 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014604 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014605 return err;
14606 }
14607
14608 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014609 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014610 return -EINVAL;
14611 }
14612
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014613 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014614 TRACE_CODE_HDD_CFG80211_TESTMODE,
14615 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014616 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14617#ifdef FEATURE_WLAN_LPHB
14618 /* Low Power Heartbeat configuration request */
14619 case WLAN_HDD_TM_CMD_WLAN_HB:
14620 {
14621 int buf_len;
14622 void *buf;
14623 tSirLPHBReq *hb_params = NULL;
14624 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014625 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014626
14627 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014628 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014629 return -EINVAL;
14630 }
14631
14632 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14633 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14634
14635 hb_params_temp = (tSirLPHBReq *) buf;
14636 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14637 && (hb_params_temp->params.lphbTcpParamReq.
14638 timePeriodSec == 0))
14639 return -EINVAL;
14640
14641 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014642 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014643 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014644 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014645 return -ENOMEM;
14646 }
14647
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014648 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014649 smeStatus =
14650 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14651 hb_params,
14652 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014653 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014654 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014655 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014656 }
14657 return 0;
14658 }
14659#endif /* FEATURE_WLAN_LPHB */
14660
14661#if defined(QCA_WIFI_FTM)
14662 case WLAN_HDD_TM_CMD_WLAN_FTM:
14663 {
14664 int buf_len;
14665 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014666 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014667 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014668 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014669 return -EINVAL;
14670 }
14671
14672 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14673 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14674
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014675 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014676
14677 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14678
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014679 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014680 err = -EBUSY;
14681 break;
14682 }
14683#endif
14684
14685 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014686 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014687 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14688 return -EOPNOTSUPP;
14689 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014690 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014691 return err;
14692}
14693
14694/**
14695 * wlan_hdd_cfg80211_testmode() - test mode
14696 * @wiphy: Pointer to wiphy
14697 * @dev: Pointer to network device
14698 * @data: Data pointer
14699 * @len: Data length
14700 *
14701 * Return: 0 for success, non-zero for failure
14702 */
14703static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14704#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14705 struct wireless_dev *wdev,
14706#endif
14707 void *data, int len)
14708{
14709 int ret;
14710
14711 cds_ssr_protect(__func__);
14712 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14713 cds_ssr_unprotect(__func__);
14714
14715 return ret;
14716}
14717
14718#if defined(QCA_WIFI_FTM)
14719/**
14720 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14721 * @buf: Pointer to buffer
14722 * @buf_len: Buffer length
14723 *
14724 * Return: none
14725 */
14726void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14727{
14728 struct sk_buff *skb;
14729 hdd_context_t *hdd_ctx;
14730
14731 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014732 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014733 return;
14734 }
14735
Anurag Chouhan6d760662016-02-20 16:05:43 +053014736 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014737 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014738 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014739 return;
14740 }
14741
14742 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14743 buf_len, GFP_KERNEL);
14744 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014745 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014746 return;
14747 }
14748
14749 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14750 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14751 goto nla_put_failure;
14752
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014753 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014754
14755 cfg80211_testmode_event(skb, GFP_KERNEL);
14756 return;
14757
14758nla_put_failure:
14759 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014760 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014761}
14762#endif
14763#endif /* CONFIG_NL80211_TESTMODE */
14764
14765#ifdef QCA_HT_2040_COEX
14766/**
14767 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14768 * @wiphy: Pointer to wiphy
14769 * @dev: Pointer to network device
14770 * @chandef: Pointer to channel definition parameter
14771 *
14772 * Return: 0 for success, non-zero for failure
14773 */
14774static int
14775__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14776 struct net_device *dev,
14777 struct cfg80211_chan_def *chandef)
14778{
14779 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14780 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014781 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014782 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053014783 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014784
Anurag Chouhan6d760662016-02-20 16:05:43 +053014785 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014786 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014787 return -EINVAL;
14788 }
14789
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014790 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14791 hdd_err("invalid session id: %d", pAdapter->sessionId);
14792 return -EINVAL;
14793 }
14794
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014795 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14796 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014797 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014798 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014799
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014800 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014801 sme_get_config_param(pHddCtx->hHal, &sme_config);
14802 switch (chandef->width) {
14803 case NL80211_CHAN_WIDTH_20:
14804 if (sme_config.csrConfig.channelBondingMode24GHz !=
14805 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14806 sme_config.csrConfig.channelBondingMode24GHz =
14807 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14808 sme_update_config(pHddCtx->hHal, &sme_config);
14809 cbModeChange = true;
14810 }
14811 break;
14812
14813 case NL80211_CHAN_WIDTH_40:
14814 if (sme_config.csrConfig.channelBondingMode24GHz ==
14815 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14816 if (NL80211_CHAN_HT40MINUS ==
14817 cfg80211_get_chandef_type(chandef))
14818 sme_config.csrConfig.channelBondingMode24GHz =
14819 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14820 else
14821 sme_config.csrConfig.channelBondingMode24GHz =
14822 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14823 sme_update_config(pHddCtx->hHal, &sme_config);
14824 cbModeChange = true;
14825 }
14826 break;
14827
14828 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014829 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014830 return -EINVAL;
14831 }
14832
14833 if (!cbModeChange)
14834 return 0;
14835
Krunal Sonib4326f22016-03-10 13:05:51 -080014836 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014837 return 0;
14838
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014839 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014840 sme_config.csrConfig.channelBondingMode24GHz);
14841
14842 /* Change SAP ht2040 mode */
14843 status = hdd_set_sap_ht2040_mode(pAdapter,
14844 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014845 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014846 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014847 return -EINVAL;
14848 }
14849
14850 return 0;
14851}
14852
14853/**
14854 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14855 * @wiphy: Pointer to wiphy
14856 * @dev: Pointer to network device
14857 * @chandef: Pointer to channel definition parameter
14858 *
14859 * Return: 0 for success, non-zero for failure
14860 */
14861static int
14862wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14863 struct net_device *dev,
14864 struct cfg80211_chan_def *chandef)
14865{
14866 int ret;
14867
14868 cds_ssr_protect(__func__);
14869 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14870 cds_ssr_unprotect(__func__);
14871
14872 return ret;
14873}
14874#endif
14875
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014876#ifdef CHANNEL_SWITCH_SUPPORTED
14877/**
14878 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14879 * channel in SAP/GO
14880 * @wiphy: wiphy pointer
14881 * @dev: dev pointer.
14882 * @csa_params: Change channel params
14883 *
14884 * This function is called to switch channel in SAP/GO
14885 *
14886 * Return: 0 if success else return non zero
14887 */
14888static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14889 struct net_device *dev,
14890 struct cfg80211_csa_settings *csa_params)
14891{
14892 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14893 hdd_context_t *hdd_ctx;
14894 uint8_t channel;
14895 uint16_t freq;
14896 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014897 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014898
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014899 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014900 csa_params->chandef.chan->center_freq);
14901
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014902 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
14903 hdd_err("invalid session id: %d", adapter->sessionId);
14904 return -EINVAL;
14905 }
14906
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014907 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14908 ret = wlan_hdd_validate_context(hdd_ctx);
14909
14910 if (0 != ret)
14911 return ret;
14912
Krunal Sonib4326f22016-03-10 13:05:51 -080014913 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14914 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014915 return -ENOTSUPP;
14916
14917 freq = csa_params->chandef.chan->center_freq;
14918 channel = cds_freq_to_chan(freq);
14919
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014920 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14921
14922 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014923 return ret;
14924}
14925
14926/**
14927 * wlan_hdd_cfg80211_channel_switch()- function to switch
14928 * channel in SAP/GO
14929 * @wiphy: wiphy pointer
14930 * @dev: dev pointer.
14931 * @csa_params: Change channel params
14932 *
14933 * This function is called to switch channel in SAP/GO
14934 *
14935 * Return: 0 if success else return non zero
14936 */
14937static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14938 struct net_device *dev,
14939 struct cfg80211_csa_settings *csa_params)
14940{
14941 int ret;
14942
14943 cds_ssr_protect(__func__);
14944 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14945 cds_ssr_unprotect(__func__);
14946 return ret;
14947}
14948#endif
14949
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014950/**
14951 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14952 * translation from NL to policy manager type
14953 * @type: Generic connection mode type defined in NL
14954 *
14955 *
14956 * This function provides the type translation
14957 *
14958 * Return: cds_con_mode enum
14959 */
14960enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
14961 enum nl80211_iftype type)
14962{
14963 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
14964 switch (type) {
14965 case NL80211_IFTYPE_STATION:
14966 mode = CDS_STA_MODE;
14967 break;
14968 case NL80211_IFTYPE_P2P_CLIENT:
14969 mode = CDS_P2P_CLIENT_MODE;
14970 break;
14971 case NL80211_IFTYPE_P2P_GO:
14972 mode = CDS_P2P_GO_MODE;
14973 break;
14974 case NL80211_IFTYPE_AP:
14975 mode = CDS_SAP_MODE;
14976 break;
14977 case NL80211_IFTYPE_ADHOC:
14978 mode = CDS_IBSS_MODE;
14979 break;
14980 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014981 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014982 type);
14983 }
14984 return mode;
14985}
14986
14987/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014988 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14989 * @wiphy: Handle to struct wiphy to get handle to module context.
14990 * @chandef: Contains information about the capture channel to be set.
14991 *
14992 * This interface is called if and only if monitor mode interface alone is
14993 * active.
14994 *
14995 * Return: 0 success or error code on failure.
14996 */
14997static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14998 struct cfg80211_chan_def *chandef)
14999{
15000 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15001 hdd_adapter_t *adapter;
15002 hdd_station_ctx_t *sta_ctx;
15003 struct hdd_mon_set_ch_info *ch_info;
15004 QDF_STATUS status;
15005 tHalHandle hal_hdl;
15006 struct qdf_mac_addr bssid;
15007 tCsrRoamProfile roam_profile;
15008 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015009 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015010 int ret;
15011 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
15012
15013 ENTER();
15014
15015 ret = wlan_hdd_validate_context(hdd_ctx);
15016 if (ret)
15017 return ret;
15018
15019 hal_hdl = hdd_ctx->hHal;
15020
15021 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
15022 if (!adapter)
15023 return -EIO;
15024
15025 hdd_info("%s: set monitor mode Channel %d and freq %d",
15026 adapter->dev->name, chan_num, chandef->chan->center_freq);
15027
15028 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15029 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015030 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
15031 roam_profile.ChannelInfo.numOfChannels = 1;
15032 roam_profile.phyMode = ch_info->phy_mode;
15033 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015034 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015035
15036 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
15037 QDF_MAC_ADDR_SIZE);
15038
15039 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015040 /*
15041 * CDS api expects secondary channel for calculating
15042 * the channel params
15043 */
15044 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
15045 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
15046 if (chan_num >= 1 && chan_num <= 5)
15047 sec_ch = chan_num + 4;
15048 else if (chan_num >= 6 && chan_num <= 13)
15049 sec_ch = chan_num - 4;
15050 }
15051 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015052 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
15053 &roam_profile);
15054 if (status) {
15055 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
15056 status);
15057 ret = qdf_status_to_os_return(status);
15058 return ret;
15059 }
15060 EXIT();
15061 return 0;
15062}
15063
15064/**
15065 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15066 * @wiphy: Handle to struct wiphy to get handle to module context.
15067 * @chandef: Contains information about the capture channel to be set.
15068 *
15069 * This interface is called if and only if monitor mode interface alone is
15070 * active.
15071 *
15072 * Return: 0 success or error code on failure.
15073 */
15074static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15075 struct cfg80211_chan_def *chandef)
15076{
15077 int ret;
15078
15079 cds_ssr_protect(__func__);
15080 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
15081 cds_ssr_unprotect(__func__);
15082 return ret;
15083}
15084
15085/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015086 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
15087 * @adapter: pointer to adapter
15088 *
15089 * Wrapper function to clear link layer stats.
15090 * return - void
15091 */
15092void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
15093{
15094 tSirLLStatsClearReq link_layer_stats_clear_req;
15095 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
15096
Mukul Sharma491021c2016-09-29 21:39:19 +053015097 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
15098 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015099 link_layer_stats_clear_req.stopReq = 0;
15100 link_layer_stats_clear_req.reqId = 1;
15101 link_layer_stats_clear_req.staId = adapter->sessionId;
15102 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
15103
15104 return;
15105}
15106
15107/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015108 * struct cfg80211_ops - cfg80211_ops
15109 *
15110 * @add_virtual_intf: Add virtual interface
15111 * @del_virtual_intf: Delete virtual interface
15112 * @change_virtual_intf: Change virtual interface
15113 * @change_station: Change station
15114 * @add_beacon: Add beacon in sap mode
15115 * @del_beacon: Delete beacon in sap mode
15116 * @set_beacon: Set beacon in sap mode
15117 * @start_ap: Start ap
15118 * @change_beacon: Change beacon
15119 * @stop_ap: Stop ap
15120 * @change_bss: Change bss
15121 * @add_key: Add key
15122 * @get_key: Get key
15123 * @del_key: Delete key
15124 * @set_default_key: Set default key
15125 * @set_channel: Set channel
15126 * @scan: Scan
15127 * @connect: Connect
15128 * @disconnect: Disconnect
15129 * @join_ibss = Join ibss
15130 * @leave_ibss = Leave ibss
15131 * @set_wiphy_params = Set wiphy params
15132 * @set_tx_power = Set tx power
15133 * @get_tx_power = get tx power
15134 * @remain_on_channel = Remain on channel
15135 * @cancel_remain_on_channel = Cancel remain on channel
15136 * @mgmt_tx = Tx management frame
15137 * @mgmt_tx_cancel_wait = Cancel management tx wait
15138 * @set_default_mgmt_key = Set default management key
15139 * @set_txq_params = Set tx queue parameters
15140 * @get_station = Get station
15141 * @set_power_mgmt = Set power management
15142 * @del_station = Delete station
15143 * @add_station = Add station
15144 * @set_pmksa = Set pmksa
15145 * @del_pmksa = Delete pmksa
15146 * @flush_pmksa = Flush pmksa
15147 * @update_ft_ies = Update FT IEs
15148 * @tdls_mgmt = Tdls management
15149 * @tdls_oper = Tdls operation
15150 * @set_rekey_data = Set rekey data
15151 * @sched_scan_start = Scheduled scan start
15152 * @sched_scan_stop = Scheduled scan stop
15153 * @resume = Resume wlan
15154 * @suspend = Suspend wlan
15155 * @set_mac_acl = Set mac acl
15156 * @testmode_cmd = Test mode command
15157 * @set_ap_chanwidth = Set AP channel bandwidth
15158 * @dump_survey = Dump survey
15159 * @key_mgmt_set_pmk = Set pmk key management
15160 */
15161static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
15162 .add_virtual_intf = wlan_hdd_add_virtual_intf,
15163 .del_virtual_intf = wlan_hdd_del_virtual_intf,
15164 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
15165 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015166 .start_ap = wlan_hdd_cfg80211_start_ap,
15167 .change_beacon = wlan_hdd_cfg80211_change_beacon,
15168 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015169 .change_bss = wlan_hdd_cfg80211_change_bss,
15170 .add_key = wlan_hdd_cfg80211_add_key,
15171 .get_key = wlan_hdd_cfg80211_get_key,
15172 .del_key = wlan_hdd_cfg80211_del_key,
15173 .set_default_key = wlan_hdd_cfg80211_set_default_key,
15174 .scan = wlan_hdd_cfg80211_scan,
15175 .connect = wlan_hdd_cfg80211_connect,
15176 .disconnect = wlan_hdd_cfg80211_disconnect,
15177 .join_ibss = wlan_hdd_cfg80211_join_ibss,
15178 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
15179 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
15180 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
15181 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
15182 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
15183 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
15184 .mgmt_tx = wlan_hdd_mgmt_tx,
15185 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
15186 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
15187 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053015188 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015189 .get_station = wlan_hdd_cfg80211_get_station,
15190 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
15191 .del_station = wlan_hdd_cfg80211_del_station,
15192 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015193 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
15194 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
15195 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015196#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015197 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
15198#endif
15199#ifdef FEATURE_WLAN_TDLS
15200 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
15201 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
15202#endif
15203#ifdef WLAN_FEATURE_GTK_OFFLOAD
15204 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
15205#endif /* WLAN_FEATURE_GTK_OFFLOAD */
15206#ifdef FEATURE_WLAN_SCAN_PNO
15207 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
15208 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
15209#endif /*FEATURE_WLAN_SCAN_PNO */
15210 .resume = wlan_hdd_cfg80211_resume_wlan,
15211 .suspend = wlan_hdd_cfg80211_suspend_wlan,
15212 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
15213#ifdef WLAN_NL80211_TESTMODE
15214 .testmode_cmd = wlan_hdd_cfg80211_testmode,
15215#endif
15216#ifdef QCA_HT_2040_COEX
15217 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
15218#endif
15219 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015220#ifdef CHANNEL_SWITCH_SUPPORTED
15221 .channel_switch = wlan_hdd_cfg80211_channel_switch,
15222#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015223 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053015224#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
15225 defined(CFG80211_ABORT_SCAN)
15226 .abort_scan = wlan_hdd_cfg80211_abort_scan,
15227#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015228};