blob: 052c80abae02e2f01f9f2b2d0854af91f4330df3 [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"
Manikandan Mohanb6315dd2016-05-10 16:16:36 -070095#include "ol_txrx.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080096
Ravi Joshideb5a8d2015-11-09 19:11:43 -080097#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053098#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070099#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700100#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530101#include "wlan_hdd_disa.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800102
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800103#define g_mode_rates_size (12)
104#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
106 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
107
108/*
109 * Android CTS verifier needs atleast this much wait time (in msec)
110 */
111#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
112
113/*
114 * Refer @tCfgProtection structure for definition of the bit map.
115 * below value is obtained by setting the following bit-fields.
116 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
117 */
118#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
119
120#define HDD2GHZCHAN(freq, chan, flag) { \
121 .band = IEEE80211_BAND_2GHZ, \
122 .center_freq = (freq), \
123 .hw_value = (chan), \
124 .flags = (flag), \
125 .max_antenna_gain = 0, \
126 .max_power = 30, \
127}
128
129#define HDD5GHZCHAN(freq, chan, flag) { \
130 .band = IEEE80211_BAND_5GHZ, \
131 .center_freq = (freq), \
132 .hw_value = (chan), \
133 .flags = (flag), \
134 .max_antenna_gain = 0, \
135 .max_power = 30, \
136}
137
138#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
139 { \
140 .bitrate = rate, \
141 .hw_value = rate_id, \
142 .flags = flag, \
143 }
144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800145#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
146#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147
148#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149
Agrawal Ashish65634612016-08-18 13:24:32 +0530150#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
151 mode <= DFS_MODE_DEPRIORITIZE))
152#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
153 || (channel >= 36 && channel <= 184))
154
Peng Xu4d67c8f2015-10-16 16:02:26 -0700155#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530156#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700157
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158static const u32 hdd_cipher_suites[] = {
159 WLAN_CIPHER_SUITE_WEP40,
160 WLAN_CIPHER_SUITE_WEP104,
161 WLAN_CIPHER_SUITE_TKIP,
162#ifdef FEATURE_WLAN_ESE
163#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
164#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
165 WLAN_CIPHER_SUITE_BTK,
166 WLAN_CIPHER_SUITE_KRK,
167 WLAN_CIPHER_SUITE_CCMP,
168#else
169 WLAN_CIPHER_SUITE_CCMP,
170#endif
171#ifdef FEATURE_WLAN_WAPI
172 WLAN_CIPHER_SUITE_SMS4,
173#endif
174#ifdef WLAN_FEATURE_11W
175 WLAN_CIPHER_SUITE_AES_CMAC,
176#endif
177};
178
Abhishek Singhf512bf32016-05-04 16:47:46 +0530179static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 HDD2GHZCHAN(2412, 1, 0),
181 HDD2GHZCHAN(2417, 2, 0),
182 HDD2GHZCHAN(2422, 3, 0),
183 HDD2GHZCHAN(2427, 4, 0),
184 HDD2GHZCHAN(2432, 5, 0),
185 HDD2GHZCHAN(2437, 6, 0),
186 HDD2GHZCHAN(2442, 7, 0),
187 HDD2GHZCHAN(2447, 8, 0),
188 HDD2GHZCHAN(2452, 9, 0),
189 HDD2GHZCHAN(2457, 10, 0),
190 HDD2GHZCHAN(2462, 11, 0),
191 HDD2GHZCHAN(2467, 12, 0),
192 HDD2GHZCHAN(2472, 13, 0),
193 HDD2GHZCHAN(2484, 14, 0),
194};
195
Abhishek Singhf512bf32016-05-04 16:47:46 +0530196static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800197 HDD5GHZCHAN(5180, 36, 0),
198 HDD5GHZCHAN(5200, 40, 0),
199 HDD5GHZCHAN(5220, 44, 0),
200 HDD5GHZCHAN(5240, 48, 0),
201 HDD5GHZCHAN(5260, 52, 0),
202 HDD5GHZCHAN(5280, 56, 0),
203 HDD5GHZCHAN(5300, 60, 0),
204 HDD5GHZCHAN(5320, 64, 0),
205 HDD5GHZCHAN(5500, 100, 0),
206 HDD5GHZCHAN(5520, 104, 0),
207 HDD5GHZCHAN(5540, 108, 0),
208 HDD5GHZCHAN(5560, 112, 0),
209 HDD5GHZCHAN(5580, 116, 0),
210 HDD5GHZCHAN(5600, 120, 0),
211 HDD5GHZCHAN(5620, 124, 0),
212 HDD5GHZCHAN(5640, 128, 0),
213 HDD5GHZCHAN(5660, 132, 0),
214 HDD5GHZCHAN(5680, 136, 0),
215 HDD5GHZCHAN(5700, 140, 0),
216 HDD5GHZCHAN(5720, 144, 0),
217 HDD5GHZCHAN(5745, 149, 0),
218 HDD5GHZCHAN(5765, 153, 0),
219 HDD5GHZCHAN(5785, 157, 0),
220 HDD5GHZCHAN(5805, 161, 0),
221 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222 HDD5GHZCHAN(5852, 170, 0),
223 HDD5GHZCHAN(5855, 171, 0),
224 HDD5GHZCHAN(5860, 172, 0),
225 HDD5GHZCHAN(5865, 173, 0),
226 HDD5GHZCHAN(5870, 174, 0),
227 HDD5GHZCHAN(5875, 175, 0),
228 HDD5GHZCHAN(5880, 176, 0),
229 HDD5GHZCHAN(5885, 177, 0),
230 HDD5GHZCHAN(5890, 178, 0),
231 HDD5GHZCHAN(5895, 179, 0),
232 HDD5GHZCHAN(5900, 180, 0),
233 HDD5GHZCHAN(5905, 181, 0),
234 HDD5GHZCHAN(5910, 182, 0),
235 HDD5GHZCHAN(5915, 183, 0),
236 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800237};
238
239static struct ieee80211_rate g_mode_rates[] = {
240 HDD_G_MODE_RATETAB(10, 0x1, 0),
241 HDD_G_MODE_RATETAB(20, 0x2, 0),
242 HDD_G_MODE_RATETAB(55, 0x4, 0),
243 HDD_G_MODE_RATETAB(110, 0x8, 0),
244 HDD_G_MODE_RATETAB(60, 0x10, 0),
245 HDD_G_MODE_RATETAB(90, 0x20, 0),
246 HDD_G_MODE_RATETAB(120, 0x40, 0),
247 HDD_G_MODE_RATETAB(180, 0x80, 0),
248 HDD_G_MODE_RATETAB(240, 0x100, 0),
249 HDD_G_MODE_RATETAB(360, 0x200, 0),
250 HDD_G_MODE_RATETAB(480, 0x400, 0),
251 HDD_G_MODE_RATETAB(540, 0x800, 0),
252};
253
254static struct ieee80211_rate a_mode_rates[] = {
255 HDD_G_MODE_RATETAB(60, 0x10, 0),
256 HDD_G_MODE_RATETAB(90, 0x20, 0),
257 HDD_G_MODE_RATETAB(120, 0x40, 0),
258 HDD_G_MODE_RATETAB(180, 0x80, 0),
259 HDD_G_MODE_RATETAB(240, 0x100, 0),
260 HDD_G_MODE_RATETAB(360, 0x200, 0),
261 HDD_G_MODE_RATETAB(480, 0x400, 0),
262 HDD_G_MODE_RATETAB(540, 0x800, 0),
263};
264
265static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530266 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800267 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
268 .band = IEEE80211_BAND_2GHZ,
269 .bitrates = g_mode_rates,
270 .n_bitrates = g_mode_rates_size,
271 .ht_cap.ht_supported = 1,
272 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
273 | IEEE80211_HT_CAP_GRN_FLD
274 | IEEE80211_HT_CAP_DSSSCCK40
275 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
276 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
277 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
278 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
279 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
280 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
281 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
282};
283
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800284static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530285 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
287 .band = IEEE80211_BAND_5GHZ,
288 .bitrates = a_mode_rates,
289 .n_bitrates = a_mode_rates_size,
290 .ht_cap.ht_supported = 1,
291 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
292 | IEEE80211_HT_CAP_GRN_FLD
293 | IEEE80211_HT_CAP_DSSSCCK40
294 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
295 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
296 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
297 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
298 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
299 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
300 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
301 .vht_cap.vht_supported = 1,
302};
303
304/* This structure contain information what kind of frame are expected in
305 TX/RX direction for each kind of interface */
306static const struct ieee80211_txrx_stypes
307 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
308 [NL80211_IFTYPE_STATION] = {
309 .tx = 0xffff,
310 .rx = BIT(SIR_MAC_MGMT_ACTION) |
311 BIT(SIR_MAC_MGMT_PROBE_REQ),
312 },
313 [NL80211_IFTYPE_AP] = {
314 .tx = 0xffff,
315 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
316 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
317 BIT(SIR_MAC_MGMT_PROBE_REQ) |
318 BIT(SIR_MAC_MGMT_DISASSOC) |
319 BIT(SIR_MAC_MGMT_AUTH) |
320 BIT(SIR_MAC_MGMT_DEAUTH) |
321 BIT(SIR_MAC_MGMT_ACTION),
322 },
323 [NL80211_IFTYPE_ADHOC] = {
324 .tx = 0xffff,
325 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
326 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
327 BIT(SIR_MAC_MGMT_PROBE_REQ) |
328 BIT(SIR_MAC_MGMT_DISASSOC) |
329 BIT(SIR_MAC_MGMT_AUTH) |
330 BIT(SIR_MAC_MGMT_DEAUTH) |
331 BIT(SIR_MAC_MGMT_ACTION),
332 },
333 [NL80211_IFTYPE_P2P_CLIENT] = {
334 .tx = 0xffff,
335 .rx = BIT(SIR_MAC_MGMT_ACTION) |
336 BIT(SIR_MAC_MGMT_PROBE_REQ),
337 },
338 [NL80211_IFTYPE_P2P_GO] = {
339 /* This is also same as for SoftAP */
340 .tx = 0xffff,
341 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
342 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
343 BIT(SIR_MAC_MGMT_PROBE_REQ) |
344 BIT(SIR_MAC_MGMT_DISASSOC) |
345 BIT(SIR_MAC_MGMT_AUTH) |
346 BIT(SIR_MAC_MGMT_DEAUTH) |
347 BIT(SIR_MAC_MGMT_ACTION),
348 },
349};
350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351/* Interface limits and combinations registered by the driver */
352
353/* STA ( + STA ) combination */
354static const struct ieee80211_iface_limit
355 wlan_hdd_sta_iface_limit[] = {
356 {
357 .max = 3, /* p2p0 is a STA as well */
358 .types = BIT(NL80211_IFTYPE_STATION),
359 },
360};
361
362/* ADHOC (IBSS) limit */
363static const struct ieee80211_iface_limit
364 wlan_hdd_adhoc_iface_limit[] = {
365 {
366 .max = 1,
367 .types = BIT(NL80211_IFTYPE_STATION),
368 },
369 {
370 .max = 1,
371 .types = BIT(NL80211_IFTYPE_ADHOC),
372 },
373};
374
375/* AP ( + AP ) combination */
376static const struct ieee80211_iface_limit
377 wlan_hdd_ap_iface_limit[] = {
378 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530379 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800380 .types = BIT(NL80211_IFTYPE_AP),
381 },
382};
383
384/* P2P limit */
385static const struct ieee80211_iface_limit
386 wlan_hdd_p2p_iface_limit[] = {
387 {
388 .max = 1,
389 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
390 },
391 {
392 .max = 1,
393 .types = BIT(NL80211_IFTYPE_P2P_GO),
394 },
395};
396
397static const struct ieee80211_iface_limit
398 wlan_hdd_sta_ap_iface_limit[] = {
399 {
400 /* We need 1 extra STA interface for OBSS scan when SAP starts
401 * with HT40 in STA+SAP concurrency mode
402 */
403 .max = (1 + SAP_MAX_OBSS_STA_CNT),
404 .types = BIT(NL80211_IFTYPE_STATION),
405 },
406 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530407 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408 .types = BIT(NL80211_IFTYPE_AP),
409 },
410};
411
412/* STA + P2P combination */
413static const struct ieee80211_iface_limit
414 wlan_hdd_sta_p2p_iface_limit[] = {
415 {
416 /* One reserved for dedicated P2PDEV usage */
417 .max = 2,
418 .types = BIT(NL80211_IFTYPE_STATION)
419 },
420 {
421 /* Support for two identical (GO + GO or CLI + CLI)
422 * or dissimilar (GO + CLI) P2P interfaces
423 */
424 .max = 2,
425 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
426 },
427};
428
429/* STA + AP + P2PGO combination */
430static const struct ieee80211_iface_limit
431wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
432 /* Support for AP+P2PGO interfaces */
433 {
434 .max = 2,
435 .types = BIT(NL80211_IFTYPE_STATION)
436 },
437 {
438 .max = 1,
439 .types = BIT(NL80211_IFTYPE_P2P_GO)
440 },
441 {
442 .max = 1,
443 .types = BIT(NL80211_IFTYPE_AP)
444 }
445};
446
447/* SAP + P2P combination */
448static const struct ieee80211_iface_limit
449wlan_hdd_sap_p2p_iface_limit[] = {
450 {
451 /* 1 dedicated for p2p0 which is a STA type */
452 .max = 1,
453 .types = BIT(NL80211_IFTYPE_STATION)
454 },
455 {
456 /* The p2p interface in SAP+P2P can be GO/CLI.
457 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
458 */
459 .max = 1,
460 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
461 },
462 {
463 /* SAP+GO to support only one SAP interface */
464 .max = 1,
465 .types = BIT(NL80211_IFTYPE_AP)
466 }
467};
468
469/* P2P + P2P combination */
470static const struct ieee80211_iface_limit
471wlan_hdd_p2p_p2p_iface_limit[] = {
472 {
473 /* 1 dedicated for p2p0 which is a STA type */
474 .max = 1,
475 .types = BIT(NL80211_IFTYPE_STATION)
476 },
477 {
478 /* The p2p interface in P2P+P2P can be GO/CLI.
479 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
480 */
481 .max = 2,
482 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
483 },
484};
485
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700486static const struct ieee80211_iface_limit
487 wlan_hdd_mon_iface_limit[] = {
488 {
489 .max = 3, /* Monitor interface */
490 .types = BIT(NL80211_IFTYPE_MONITOR),
491 },
492};
493
494static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800495 wlan_hdd_iface_combination[] = {
496 /* STA */
497 {
498 .limits = wlan_hdd_sta_iface_limit,
499 .num_different_channels = 2,
500 .max_interfaces = 3,
501 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
502 },
503 /* ADHOC */
504 {
505 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700506 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800507 .max_interfaces = 2,
508 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
509 },
510 /* AP */
511 {
512 .limits = wlan_hdd_ap_iface_limit,
513 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530514 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800515 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
516 },
517 /* P2P */
518 {
519 .limits = wlan_hdd_p2p_iface_limit,
520 .num_different_channels = 2,
521 .max_interfaces = 2,
522 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
523 },
524 /* STA + AP */
525 {
526 .limits = wlan_hdd_sta_ap_iface_limit,
527 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530528 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
530 .beacon_int_infra_match = true,
531 },
532 /* STA + P2P */
533 {
534 .limits = wlan_hdd_sta_p2p_iface_limit,
535 .num_different_channels = 2,
536 /* one interface reserved for P2PDEV dedicated usage */
537 .max_interfaces = 4,
538 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
539 .beacon_int_infra_match = true,
540 },
541 /* STA + P2P GO + SAP */
542 {
543 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
544 /* we can allow 3 channels for three different persona
545 * but due to firmware limitation, allow max 2 concrnt channels.
546 */
547 .num_different_channels = 2,
548 /* one interface reserved for P2PDEV dedicated usage */
549 .max_interfaces = 4,
550 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
551 .beacon_int_infra_match = true,
552 },
553 /* SAP + P2P */
554 {
555 .limits = wlan_hdd_sap_p2p_iface_limit,
556 .num_different_channels = 2,
557 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
558 .max_interfaces = 3,
559 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
560 .beacon_int_infra_match = true,
561 },
562 /* P2P + P2P */
563 {
564 .limits = wlan_hdd_p2p_p2p_iface_limit,
565 .num_different_channels = 2,
566 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
567 .max_interfaces = 3,
568 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
569 .beacon_int_infra_match = true,
570 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530571 /* Monitor */
572 {
573 .limits = wlan_hdd_mon_iface_limit,
574 .max_interfaces = 3,
575 .num_different_channels = 2,
576 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
577 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800579
580static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530581struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582
583#ifdef WLAN_NL80211_TESTMODE
584enum wlan_hdd_tm_attr {
585 WLAN_HDD_TM_ATTR_INVALID = 0,
586 WLAN_HDD_TM_ATTR_CMD = 1,
587 WLAN_HDD_TM_ATTR_DATA = 2,
588 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
589 WLAN_HDD_TM_ATTR_TYPE = 4,
590 /* keep last */
591 WLAN_HDD_TM_ATTR_AFTER_LAST,
592 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
593};
594
595enum wlan_hdd_tm_cmd {
596 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
597 WLAN_HDD_TM_CMD_WLAN_HB = 1,
598};
599
600#define WLAN_HDD_TM_DATA_MAX_LEN 5000
601
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530602enum wlan_hdd_vendor_ie_access_policy {
603 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
604 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
605};
606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
608 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
609 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
610 .len = WLAN_HDD_TM_DATA_MAX_LEN},
611};
612#endif /* WLAN_NL80211_TESTMODE */
613
614#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
615static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
616 .flags = WIPHY_WOWLAN_MAGIC_PKT,
617 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
618 .pattern_min_len = 1,
619 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
620};
621#endif
622
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800623/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530624 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
625 * @flags: Pointer to the flags to Add channel switch flag.
626 *
627 * This Function adds Channel Switch support flag, if channel switch is
628 * supported by kernel.
629 * Return: void.
630 */
631#ifdef CHANNEL_SWITCH_SUPPORTED
632static inline void hdd_add_channel_switch_support(uint32_t *flags)
633{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800634 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530635 return;
636}
637#else
638static inline void hdd_add_channel_switch_support(uint32_t *flags)
639{
640 return;
641}
642#endif
643
Manikandan Mohan22b83722015-12-15 15:03:23 -0800644#ifdef FEATURE_WLAN_TDLS
645
646/* TDLS capabilities params */
647#define PARAM_MAX_TDLS_SESSION \
648 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
649#define PARAM_TDLS_FEATURE_SUPPORT \
650 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
651
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530652/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800653 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
654 * @wiphy: WIPHY structure pointer
655 * @wdev: Wireless device structure pointer
656 * @data: Pointer to the data received
657 * @data_len: Length of the data received
658 *
659 * This function provides TDLS capabilities
660 *
661 * Return: 0 on success and errno on failure
662 */
663static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
664 struct wireless_dev *wdev,
665 const void *data,
666 int data_len)
667{
668 int status;
669 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
670 struct sk_buff *skb;
671 uint32_t set = 0;
672
Jeff Johnson1f61b612016-02-12 16:28:33 -0800673 ENTER_DEV(wdev->netdev);
674
Anurag Chouhan6d760662016-02-20 16:05:43 +0530675 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676 hdd_err("Command not allowed in FTM mode");
677 return -EPERM;
678 }
679
680 status = wlan_hdd_validate_context(hdd_ctx);
681 if (status)
682 return status;
683
684 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
685 NLMSG_HDRLEN);
686 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700687 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 goto fail;
689 }
690
691 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700692 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800693 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
694 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700695 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 goto fail;
697 }
698 } else {
699 set = set | WIFI_TDLS_SUPPORT;
700 set = set | (hdd_ctx->config->fTDLSExternalControl ?
701 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
702 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
703 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700704 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
706 hdd_ctx->max_num_tdls_sta) ||
707 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
708 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700709 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 goto fail;
711 }
712 }
713 return cfg80211_vendor_cmd_reply(skb);
714fail:
715 if (skb)
716 kfree_skb(skb);
717 return -EINVAL;
718}
719
720/**
721 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
722 * @wiphy: WIPHY structure pointer
723 * @wdev: Wireless device structure pointer
724 * @data: Pointer to the data received
725 * @data_len: Length of the data received
726 *
727 * This function provides TDLS capabilities
728 *
729 * Return: 0 on success and errno on failure
730 */
731static int
732wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
733 struct wireless_dev *wdev,
734 const void *data,
735 int data_len)
736{
737 int ret;
738
739 cds_ssr_protect(__func__);
740 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
741 data, data_len);
742 cds_ssr_unprotect(__func__);
743
744 return ret;
745}
746#endif
747
748#ifdef QCA_HT_2040_COEX
749static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
750#endif
751
752#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
753/*
754 * FUNCTION: wlan_hdd_send_avoid_freq_event
755 * This is called when wlan driver needs to send vendor specific
756 * avoid frequency range event to userspace
757 */
758int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
759 tHddAvoidFreqList *pAvoidFreqList)
760{
761 struct sk_buff *vendor_event;
762
763 ENTER();
764
765 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700766 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 return -EINVAL;
768 }
769
770 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700771 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772 return -EINVAL;
773 }
774
775 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
776 NULL,
777 sizeof(tHddAvoidFreqList),
778 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
779 GFP_KERNEL);
780 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700781 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782 return -EINVAL;
783 }
784
785 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
786 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
787
788 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
789
790 EXIT();
791 return 0;
792}
793#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
794
795/* vendor specific events */
796static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
797#ifdef FEATURE_WLAN_CH_AVOID
798 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
799 .vendor_id =
800 QCA_NL80211_VENDOR_ID,
801 .subcmd =
802 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
803 },
804#endif /* FEATURE_WLAN_CH_AVOID */
805
806#ifdef WLAN_FEATURE_NAN
807 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
808 .vendor_id =
809 QCA_NL80211_VENDOR_ID,
810 .subcmd =
811 QCA_NL80211_VENDOR_SUBCMD_NAN
812 },
813#endif
814
815#ifdef WLAN_FEATURE_STATS_EXT
816 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
817 .vendor_id =
818 QCA_NL80211_VENDOR_ID,
819 .subcmd =
820 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
821 },
822#endif /* WLAN_FEATURE_STATS_EXT */
823#ifdef FEATURE_WLAN_EXTSCAN
824 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
825 .vendor_id =
826 QCA_NL80211_VENDOR_ID,
827 .subcmd =
828 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
829 },
830 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
831 .vendor_id =
832 QCA_NL80211_VENDOR_ID,
833 .subcmd =
834 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
835 },
836 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
837 .
838 vendor_id
839 =
840 QCA_NL80211_VENDOR_ID,
841 .subcmd =
842 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
843 },
844 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
845 .
846 vendor_id
847 =
848 QCA_NL80211_VENDOR_ID,
849 .
850 subcmd =
851 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
852 },
853 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
854 .
855 vendor_id
856 =
857 QCA_NL80211_VENDOR_ID,
858 .
859 subcmd
860 =
861 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
862 },
863 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
864 .
865 vendor_id
866 =
867 QCA_NL80211_VENDOR_ID,
868 .subcmd =
869 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
870 },
871 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
872 .vendor_id =
873 QCA_NL80211_VENDOR_ID,
874 .subcmd =
875 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
876 },
877 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
878 .
879 vendor_id
880 =
881 QCA_NL80211_VENDOR_ID,
882 .subcmd =
883 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
884 },
885 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
886 .
887 vendor_id
888 =
889 QCA_NL80211_VENDOR_ID,
890 .subcmd =
891 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
892 },
893 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
894 .
895 vendor_id
896 =
897 QCA_NL80211_VENDOR_ID,
898 .
899 subcmd
900 =
901 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
902 },
903 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
904 .
905 vendor_id
906 =
907 QCA_NL80211_VENDOR_ID,
908 .
909 subcmd =
910 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
911 },
912 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
913 .
914 vendor_id
915 =
916 QCA_NL80211_VENDOR_ID,
917 .
918 subcmd
919 =
920 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
921 },
922 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
923 .
924 vendor_id
925 =
926 QCA_NL80211_VENDOR_ID,
927 .
928 subcmd
929 =
930 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
931 },
932 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
933 .vendor_id = QCA_NL80211_VENDOR_ID,
934 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
935 },
936 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
937 .vendor_id = QCA_NL80211_VENDOR_ID,
938 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
939 },
940#endif /* FEATURE_WLAN_EXTSCAN */
941
942#ifdef WLAN_FEATURE_LINK_LAYER_STATS
943 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
944 .vendor_id =
945 QCA_NL80211_VENDOR_ID,
946 .subcmd =
947 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
948 },
949 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
950 .vendor_id =
951 QCA_NL80211_VENDOR_ID,
952 .subcmd =
953 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
954 },
955 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
956 .vendor_id =
957 QCA_NL80211_VENDOR_ID,
958 .subcmd =
959 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
960 },
961 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
962 .vendor_id =
963 QCA_NL80211_VENDOR_ID,
964 .subcmd =
965 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
966 },
967 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
968 .vendor_id =
969 QCA_NL80211_VENDOR_ID,
970 .subcmd =
971 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
972 },
973 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
974 .vendor_id =
975 QCA_NL80211_VENDOR_ID,
976 .subcmd =
977 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
978 },
979#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
980 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
981 .vendor_id =
982 QCA_NL80211_VENDOR_ID,
983 .subcmd =
984 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
985 },
986 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
987 .vendor_id = QCA_NL80211_VENDOR_ID,
988 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
989 },
990#ifdef WLAN_FEATURE_ROAM_OFFLOAD
991 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
992 .vendor_id =
993 QCA_NL80211_VENDOR_ID,
994 .subcmd =
995 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
996 },
997#endif
998 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
999 .vendor_id =
1000 QCA_NL80211_VENDOR_ID,
1001 .subcmd =
1002 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1003 },
1004 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1005 .vendor_id =
1006 QCA_NL80211_VENDOR_ID,
1007 .subcmd =
1008 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1009 },
1010 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1011 .vendor_id =
1012 QCA_NL80211_VENDOR_ID,
1013 .subcmd =
1014 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1015 },
1016 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1017 .vendor_id =
1018 QCA_NL80211_VENDOR_ID,
1019 .subcmd =
1020 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1021 },
1022 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1023 .vendor_id =
1024 QCA_NL80211_VENDOR_ID,
1025 .subcmd =
1026 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1027 },
1028#ifdef FEATURE_WLAN_EXTSCAN
1029 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1030 .vendor_id = QCA_NL80211_VENDOR_ID,
1031 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1032 },
1033 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1034 .vendor_id = QCA_NL80211_VENDOR_ID,
1035 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1036 },
1037 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1038 .vendor_id = QCA_NL80211_VENDOR_ID,
1039 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1040 },
1041 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1042 .vendor_id = QCA_NL80211_VENDOR_ID,
1043 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1044 },
1045 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1046 .vendor_id = QCA_NL80211_VENDOR_ID,
1047 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1048 },
1049#endif /* FEATURE_WLAN_EXTSCAN */
1050 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1051 .vendor_id = QCA_NL80211_VENDOR_ID,
1052 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1053 },
1054#ifdef WLAN_FEATURE_MEMDUMP
1055 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1056 .vendor_id = QCA_NL80211_VENDOR_ID,
1057 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1058 },
1059#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001060#ifdef WLAN_FEATURE_TSF
1061 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1062 .vendor_id = QCA_NL80211_VENDOR_ID,
1063 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1064 },
1065#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001066 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1067 .vendor_id = QCA_NL80211_VENDOR_ID,
1068 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1069 },
1070 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1071 .vendor_id = QCA_NL80211_VENDOR_ID,
1072 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1073 },
1074 /* OCB events */
1075 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1076 .vendor_id = QCA_NL80211_VENDOR_ID,
1077 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1078 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001079#ifdef FEATURE_LFR_SUBNET_DETECTION
1080 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1081 .vendor_id = QCA_NL80211_VENDOR_ID,
1082 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1083 },
1084#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001085
1086#ifdef WLAN_FEATURE_NAN_DATAPATH
1087 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1088 .vendor_id = QCA_NL80211_VENDOR_ID,
1089 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1090 },
1091#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001092
1093 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1094 .vendor_id = QCA_NL80211_VENDOR_ID,
1095 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1096 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301097 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1098 .vendor_id = QCA_NL80211_VENDOR_ID,
1099 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1100 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001101};
1102
1103/**
1104 * __is_driver_dfs_capable() - get driver DFS capability
1105 * @wiphy: pointer to wireless wiphy structure.
1106 * @wdev: pointer to wireless_dev structure.
1107 * @data: Pointer to the data to be passed via vendor interface
1108 * @data_len:Length of the data to be passed
1109 *
1110 * This function is called by userspace to indicate whether or not
1111 * the driver supports DFS offload.
1112 *
1113 * Return: 0 on success, negative errno on failure
1114 */
1115static int __is_driver_dfs_capable(struct wiphy *wiphy,
1116 struct wireless_dev *wdev,
1117 const void *data,
1118 int data_len)
1119{
1120 u32 dfs_capability = 0;
1121 struct sk_buff *temp_skbuff;
1122 int ret_val;
1123 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1124
Jeff Johnson1f61b612016-02-12 16:28:33 -08001125 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001126
1127 ret_val = wlan_hdd_validate_context(hdd_ctx);
1128 if (ret_val)
1129 return ret_val;
1130
Anurag Chouhan6d760662016-02-20 16:05:43 +05301131 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 hdd_err("Command not allowed in FTM mode");
1133 return -EPERM;
1134 }
1135
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137
1138 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1139 NLMSG_HDRLEN);
1140
1141 if (temp_skbuff != NULL) {
1142 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1143 dfs_capability);
1144 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001145 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146 kfree_skb(temp_skbuff);
1147
1148 return ret_val;
1149 }
1150
1151 return cfg80211_vendor_cmd_reply(temp_skbuff);
1152 }
1153
Jeff Johnson020db452016-06-29 14:37:26 -07001154 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001155 return -ENOMEM;
1156}
1157
1158/**
1159 * is_driver_dfs_capable() - get driver DFS capability
1160 * @wiphy: pointer to wireless wiphy structure.
1161 * @wdev: pointer to wireless_dev structure.
1162 * @data: Pointer to the data to be passed via vendor interface
1163 * @data_len:Length of the data to be passed
1164 *
1165 * This function is called by userspace to indicate whether or not
1166 * the driver supports DFS offload. This is an SSR-protected
1167 * wrapper function.
1168 *
1169 * Return: 0 on success, negative errno on failure
1170 */
1171static int is_driver_dfs_capable(struct wiphy *wiphy,
1172 struct wireless_dev *wdev,
1173 const void *data,
1174 int data_len)
1175{
1176 int ret;
1177
1178 cds_ssr_protect(__func__);
1179 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1180 cds_ssr_unprotect(__func__);
1181
1182 return ret;
1183}
1184
1185/**
1186 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1187 *
1188 * @adapter: SAP adapter pointer
1189 *
1190 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1191 * radio. So in case of DFS MCC scenario override current SAP given config
1192 * to follow concurrent SAP DFS config
1193 *
1194 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1195 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001196int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1197{
1198 hdd_adapter_t *con_sap_adapter;
1199 tsap_Config_t *sap_config, *con_sap_config;
1200 int con_ch;
1201
1202 /*
1203 * Check if AP+AP case, once primary AP chooses a DFS
1204 * channel secondary AP should always follow primary APs channel
1205 */
1206 if (!cds_concurrent_beaconing_sessions_running())
1207 return 0;
1208
1209 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1210 if (!con_sap_adapter)
1211 return 0;
1212
1213 sap_config = &adapter->sessionCtx.ap.sapConfig;
1214 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1215 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1216
1217 if (!CDS_IS_DFS_CH(con_ch))
1218 return 0;
1219
Jeff Johnson020db452016-06-29 14:37:26 -07001220 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001222 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223 sap_config->channel = con_ch;
1224
1225 if (con_sap_config->acs_cfg.acs_mode == true) {
1226 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1227 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001228 hdd_err("Primary AP channel config error");
1229 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230 con_ch, con_sap_config->acs_cfg.pri_ch,
1231 con_sap_config->acs_cfg.ht_sec_ch);
1232 return -EINVAL;
1233 }
1234 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1235 * MCC restriction. So free ch list allocated in do_acs
1236 * func for Sec AP and realloc for Pri AP ch list size
1237 */
1238 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301239 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301241 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242 &con_sap_config->acs_cfg,
1243 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301244 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001245 sizeof(uint8_t) *
1246 con_sap_config->acs_cfg.ch_list_count);
1247 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001248 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249 return -ENOMEM;
1250 }
1251
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301252 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253 con_sap_config->acs_cfg.ch_list,
1254 con_sap_config->acs_cfg.ch_list_count);
1255
1256 } else {
1257 sap_config->acs_cfg.pri_ch = con_ch;
1258 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1259 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1260 }
1261
1262 return con_ch;
1263}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264
1265/**
1266 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1267 * @sap_cfg: pointer to SAP config struct
1268 *
1269 * This function sets the default ACS start and end channel for the given band
1270 * and also parses the given ACS channel list.
1271 *
1272 * Return: None
1273 */
1274
1275static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1276 bool vht_enabled)
1277{
1278 int i;
1279 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1280 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001281 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1282 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001283 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1284 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001285 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1286 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001287 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1288 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001289 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1290 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1292 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001293 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1294 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295 }
1296
1297 if (ht_enabled)
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1299
1300 if (vht_enabled)
1301 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1302
1303
1304 /* Parse ACS Chan list from hostapd */
1305 if (!sap_cfg->acs_cfg.ch_list)
1306 return;
1307
1308 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1309 sap_cfg->acs_cfg.end_ch =
1310 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1311 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301312 /* avoid channel as start channel */
1313 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1314 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001315 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1316 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1317 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1318 }
1319}
1320
1321
1322static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1323
1324/**
1325 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1326 * @adapter: pointer to SAP adapter struct
1327 *
1328 * This function starts the ACS procedure if there are no
1329 * constraints like MBSSID DFS restrictions.
1330 *
1331 * Return: Status of ACS Start procedure
1332 */
1333
1334static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1335{
1336
1337 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1338 tsap_Config_t *sap_config;
1339 tpWLAN_SAPEventCB acs_event_callback;
1340 int status;
1341
1342 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301343 if (hdd_ctx->acs_policy.acs_channel)
1344 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1345 else
1346 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347
1348 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1349 if (status < 0) {
1350 return status;
1351 } else {
1352 if (status > 0) {
1353 /*notify hostapd about channel override */
1354 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1355 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1356 return 0;
1357 }
1358 }
1359 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1360 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001361 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362 return -EINVAL;
1363 }
1364
1365 acs_event_callback = hdd_hostapd_sap_event_cb;
1366
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301367 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301368 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001369 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 acs_event_callback, sap_config, adapter->dev);
1373
1374
1375 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001376 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 return -EINVAL;
1378 }
1379 sap_config->acs_cfg.acs_mode = true;
1380 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1381
1382 return 0;
1383}
1384
1385/**
1386 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1387 * @wiphy: Linux wiphy struct pointer
1388 * @wdev: Linux wireless device struct pointer
1389 * @data: ACS information from hostapd
1390 * @data_len: ACS information length
1391 *
1392 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1393 * and starts ACS procedure.
1394 *
1395 * Return: ACS procedure start status
1396 */
1397
1398static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1399 struct wireless_dev *wdev,
1400 const void *data, int data_len)
1401{
1402 struct net_device *ndev = wdev->netdev;
1403 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1404 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1405 tsap_Config_t *sap_config;
1406 struct sk_buff *temp_skbuff;
1407 int status = -EINVAL, i = 0;
1408 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1409 bool ht_enabled, ht40_enabled, vht_enabled;
1410 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301411 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001412
1413 /* ***Note*** Donot set SME config related to ACS operation here because
1414 * ACS operation is not synchronouse and ACS for Second AP may come when
1415 * ACS operation for first AP is going on. So only do_acs is split to
1416 * seperate start_acs routine. Also SME-PMAC struct that is used to
1417 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1418 * config shall be set only from start_acs.
1419 */
1420
1421 /* nla_policy Policy template. Policy not applied as some attributes are
1422 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1423 *
1424 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1425 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1426 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1427 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1428 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1429 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1430 */
1431
Jeff Johnson1f61b612016-02-12 16:28:33 -08001432 ENTER_DEV(ndev);
1433
Anurag Chouhan6d760662016-02-20 16:05:43 +05301434 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001435 hdd_err("Command not allowed in FTM mode");
1436 return -EPERM;
1437 }
1438
1439 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001440 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001441 return -EPERM;
1442 }
1443
1444 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301445 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001446 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301447
Naveen Rawat64e477e2016-05-20 10:34:56 -07001448 if (cds_is_sub_20_mhz_enabled()) {
1449 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1450 status = -EINVAL;
1451 goto out;
1452 }
1453
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001454 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301455 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456
1457 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1458 NULL);
1459 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001460 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001461 goto out;
1462 }
1463
1464 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001465 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001466 goto out;
1467 }
1468 sap_config->acs_cfg.hw_mode = nla_get_u8(
1469 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1470
1471 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1472 ht_enabled =
1473 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1474 else
1475 ht_enabled = 0;
1476
1477 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1478 ht40_enabled =
1479 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1480 else
1481 ht40_enabled = 0;
1482
1483 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1484 vht_enabled =
1485 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1486 else
1487 vht_enabled = 0;
1488
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301489 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1490 vht_enabled = 0;
1491 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1492 }
1493
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001494 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1495 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1496 } else {
1497 if (ht_enabled && ht40_enabled)
1498 ch_width = 40;
1499 else
1500 ch_width = 20;
1501 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301502
1503 /* this may be possible, when sap_force_11n_for_11ac is set */
1504 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1505 if (ht_enabled && ht40_enabled)
1506 ch_width = 40;
1507 else
1508 ch_width = 20;
1509 }
1510
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511 if (ch_width == 80)
1512 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1513 else if (ch_width == 40)
1514 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1515 else
1516 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1517
1518 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1519 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1520 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1521 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1522 * since it contains the frequency values of the channels in
1523 * the channel list.
1524 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1525 * is present
1526 */
1527 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1528 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1529 sap_config->acs_cfg.ch_list_count = nla_len(
1530 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1531 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301532 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533 sizeof(uint8_t) *
1534 sap_config->acs_cfg.ch_list_count);
1535 if (sap_config->acs_cfg.ch_list == NULL)
1536 goto out;
1537
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301538 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001539 sap_config->acs_cfg.ch_list_count);
1540 }
1541 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1542 uint32_t *freq =
1543 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1544 sap_config->acs_cfg.ch_list_count = nla_len(
1545 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1546 sizeof(uint32_t);
1547 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301548 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001549 sap_config->acs_cfg.ch_list_count);
1550 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001551 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001552 status = -ENOMEM;
1553 goto out;
1554 }
1555
1556 /* convert frequency to channel */
1557 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1558 sap_config->acs_cfg.ch_list[i] =
1559 ieee80211_frequency_to_channel(freq[i]);
1560 }
1561 }
1562
1563 hdd_debug("get pcl for DO_ACS vendor command");
1564
1565 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001566 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301567 sap_config->acs_cfg.pcl_channels,
1568 &sap_config->acs_cfg.pcl_ch_count,
1569 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301570 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001571 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001572
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001573 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301574 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
1575 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07001576 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001577 vht_enabled = 1;
1578 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1579 sap_config->acs_cfg.ch_width =
1580 hdd_ctx->config->vhtChannelWidth;
1581 /* No VHT80 in 2.4G so perform ACS accordingly */
1582 if (sap_config->acs_cfg.end_ch <= 14 &&
1583 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1584 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1585 }
1586
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301587 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1588
Jeff Johnson020db452016-06-29 14:37:26 -07001589 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 -08001590 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1591 ch_width, ht_enabled, vht_enabled,
1592 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1593
1594 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001595 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001596 sap_config->acs_cfg.ch_list_count);
1597 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001598 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001599 }
1600 sap_config->acs_cfg.acs_mode = true;
1601 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001602 /* ***Note*** Completion variable usage is not allowed
1603 * here since ACS scan operation may take max 2.2 sec
1604 * for 5G band:
1605 * 9 Active channel X 40 ms active scan time +
1606 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001607 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1608 * for this long. So we split up the scanning part.
1609 */
1610 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001611 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001612 status = 0;
1613 } else {
1614 status = wlan_hdd_cfg80211_start_acs(adapter);
1615 }
1616
1617out:
1618 if (0 == status) {
1619 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1620 NLMSG_HDRLEN);
1621 if (temp_skbuff != NULL)
1622 return cfg80211_vendor_cmd_reply(temp_skbuff);
1623 }
1624
1625 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1626
1627 return status;
1628}
1629
1630 /**
1631 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1632 * @wiphy: Linux wiphy struct pointer
1633 * @wdev: Linux wireless device struct pointer
1634 * @data: ACS information from hostapd
1635 * @data_len: ACS information len
1636 *
1637 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1638 * and starts ACS procedure.
1639 *
1640 * Return: ACS procedure start status
1641 */
1642
1643static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1644 struct wireless_dev *wdev,
1645 const void *data, int data_len)
1646{
1647 int ret;
1648
1649 cds_ssr_protect(__func__);
1650 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1651 cds_ssr_unprotect(__func__);
1652
1653 return ret;
1654}
1655
1656/**
1657 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1658 * @work: Linux workqueue struct pointer for ACS work
1659 *
1660 * This function starts the ACS procedure which was marked pending when an ACS
1661 * procedure was in progress for a concurrent SAP interface.
1662 *
1663 * Return: None
1664 */
1665
1666static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1667{
1668 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1669 acs_pending_work.work);
1670 wlan_hdd_cfg80211_start_acs(adapter);
1671}
1672
1673/**
1674 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1675 * @adapter: Pointer to SAP adapter struct
1676 * @pri_channel: SAP ACS procedure selected Primary channel
1677 * @sec_channel: SAP ACS procedure selected secondary channel
1678 *
1679 * This is a callback function from SAP module on ACS procedure is completed.
1680 * This function send the ACS selected channel information to hostapd
1681 *
1682 * Return: None
1683 */
1684
1685void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1686{
1687 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1688 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1689 struct sk_buff *vendor_event;
1690 int ret_val;
1691 hdd_adapter_t *con_sap_adapter;
1692 uint16_t ch_width;
1693
1694 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001695 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001696 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1697 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1698 GFP_KERNEL);
1699
1700 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001701 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001702 return;
1703 }
1704
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001705 ret_val = nla_put_u8(vendor_event,
1706 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1707 sap_cfg->acs_cfg.pri_ch);
1708 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001709 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001710 kfree_skb(vendor_event);
1711 return;
1712 }
1713
1714 ret_val = nla_put_u8(vendor_event,
1715 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1716 sap_cfg->acs_cfg.ht_sec_ch);
1717 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001718 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001719 kfree_skb(vendor_event);
1720 return;
1721 }
1722
1723 ret_val = nla_put_u8(vendor_event,
1724 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1725 sap_cfg->acs_cfg.vht_seg0_center_ch);
1726 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001727 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728 kfree_skb(vendor_event);
1729 return;
1730 }
1731
1732 ret_val = nla_put_u8(vendor_event,
1733 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1734 sap_cfg->acs_cfg.vht_seg1_center_ch);
1735 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001736 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001737 kfree_skb(vendor_event);
1738 return;
1739 }
1740
1741 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1742 ch_width = 80;
1743 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1744 ch_width = 40;
1745 else
1746 ch_width = 20;
1747
1748 ret_val = nla_put_u16(vendor_event,
1749 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1750 ch_width);
1751 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001752 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001753 kfree_skb(vendor_event);
1754 return;
1755 }
1756 if (sap_cfg->acs_cfg.pri_ch > 14)
1757 ret_val = nla_put_u8(vendor_event,
1758 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1759 QCA_ACS_MODE_IEEE80211A);
1760 else
1761 ret_val = nla_put_u8(vendor_event,
1762 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1763 QCA_ACS_MODE_IEEE80211G);
1764
1765 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001766 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001767 kfree_skb(vendor_event);
1768 return;
1769 }
1770
Jeff Johnson46b40792016-06-29 14:03:14 -07001771 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 -08001772 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1773 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1774 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1775
1776 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1777 /* ***Note*** As already mentioned Completion variable usage is not
1778 * allowed here since ACS scan operation may take max 2.2 sec.
1779 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1780 * operation.
1781 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1782 * when Primary AP ACS is complete and secondary AP ACS is started here
1783 * immediately, Primary AP start_bss may come inbetween ACS operation
1784 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1785 * delay. This path and below constraint will be removed on sessionizing
1786 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1787 * As per design constraint user space control application must take
1788 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1789 * this code path. Sec AP hostapd should be started after Primary AP
1790 * start beaconing which can be confirmed by getchannel iwpriv command
1791 */
1792
1793 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1794 if (con_sap_adapter &&
1795 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001796 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1797 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001798 /* Lets give 500ms for OBSS + START_BSS to complete */
1799 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1800 msecs_to_jiffies(500));
1801 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1802 }
1803
1804 return;
1805}
1806
1807static int
1808__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1809 struct wireless_dev *wdev,
1810 const void *data,
1811 int data_len)
1812{
1813 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1814 struct sk_buff *skb = NULL;
1815 uint32_t fset = 0;
1816 int ret;
1817
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001818 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301819
Anurag Chouhan6d760662016-02-20 16:05:43 +05301820 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001821 hdd_err("Command not allowed in FTM mode");
1822 return -EPERM;
1823 }
1824
1825 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301826 if (ret)
1827 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001828
1829 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001830 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001831 fset |= WIFI_FEATURE_INFRA;
1832 }
1833 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001834 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001835 fset |= WIFI_FEATURE_INFRA_5G;
1836 }
1837#ifdef WLAN_FEATURE_P2P
1838 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1839 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001840 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001841 fset |= WIFI_FEATURE_P2P;
1842 }
1843#endif
1844 fset |= WIFI_FEATURE_SOFT_AP;
1845
1846 /* HOTSPOT is a supplicant feature, enable it by default */
1847 fset |= WIFI_FEATURE_HOTSPOT;
1848
1849#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301850 if (pHddCtx->config->extscan_enabled &&
1851 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001852 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001853 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1854 }
1855#endif
1856 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001857 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001858 fset |= WIFI_FEATURE_NAN;
1859 }
1860 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001861 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001862 fset |= WIFI_FEATURE_D2D_RTT;
1863 fset |= WIFI_FEATURE_D2AP_RTT;
1864 }
1865#ifdef FEATURE_WLAN_SCAN_PNO
1866 if (pHddCtx->config->configPNOScanSupport &&
1867 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001868 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001869 fset |= WIFI_FEATURE_PNO;
1870 }
1871#endif
1872 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1873#ifdef FEATURE_WLAN_TDLS
1874 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1875 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001876 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001877 fset |= WIFI_FEATURE_TDLS;
1878 }
1879 if (sme_is_feature_supported_by_fw(TDLS) &&
1880 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1881 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001882 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001883 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1884 }
1885#endif
1886#ifdef WLAN_AP_STA_CONCURRENCY
1887 fset |= WIFI_FEATURE_AP_STA;
1888#endif
1889 fset |= WIFI_FEATURE_RSSI_MONITOR;
1890
1891 if (hdd_link_layer_stats_supported())
1892 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1893
1894 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1895 NLMSG_HDRLEN);
1896 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001897 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001898 return -EINVAL;
1899 }
Jeff Johnson020db452016-06-29 14:37:26 -07001900 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001902 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903 goto nla_put_failure;
1904 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301905 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301906 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001907nla_put_failure:
1908 kfree_skb(skb);
1909 return -EINVAL;
1910}
1911
1912/**
1913 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1914 * @wiphy: pointer to wireless wiphy structure.
1915 * @wdev: pointer to wireless_dev structure.
1916 * @data: Pointer to the data to be passed via vendor interface
1917 * @data_len:Length of the data to be passed
1918 *
1919 * Return: Return the Success or Failure code.
1920 */
1921static int
1922wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1923 struct wireless_dev *wdev,
1924 const void *data, int data_len)
1925{
1926 int ret = 0;
1927
1928 cds_ssr_protect(__func__);
1929 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1930 data, data_len);
1931 cds_ssr_unprotect(__func__);
1932
1933 return ret;
1934}
1935
1936/**
1937 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1938 * @wiphy: pointer to wireless wiphy structure.
1939 * @wdev: pointer to wireless_dev structure.
1940 * @data: Pointer to the data to be passed via vendor interface
1941 * @data_len:Length of the data to be passed
1942 *
1943 * Set the MAC address that is to be used for scanning.
1944 *
1945 * Return: Return the Success or Failure code.
1946 */
1947static int
1948__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1949 struct wireless_dev *wdev,
1950 const void *data,
1951 int data_len)
1952{
1953 tpSirScanMacOui pReqMsg = NULL;
1954 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1955 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301956 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957 int ret;
1958
Jeff Johnson1f61b612016-02-12 16:28:33 -08001959 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960
Anurag Chouhan6d760662016-02-20 16:05:43 +05301961 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001962 hdd_err("Command not allowed in FTM mode");
1963 return -EPERM;
1964 }
1965
1966 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301967 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001969
1970 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001971 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 return -ENOTSUPP;
1973 }
1974
1975 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1976 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001977 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 return -EINVAL;
1979 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301980 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07001982 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983 return -ENOMEM;
1984 }
1985 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001986 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987 goto fail;
1988 }
1989 nla_memcpy(&pReqMsg->oui[0],
1990 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
1991 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07001992 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993 pReqMsg->oui[1], pReqMsg->oui[2]);
1994 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301995 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001996 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997 goto fail;
1998 }
1999 return 0;
2000fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302001 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002002 return -EINVAL;
2003}
2004
2005/**
2006 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2007 * @wiphy: pointer to wireless wiphy structure.
2008 * @wdev: pointer to wireless_dev structure.
2009 * @data: Pointer to the data to be passed via vendor interface
2010 * @data_len:Length of the data to be passed
2011 *
2012 * Set the MAC address that is to be used for scanning. This is an
2013 * SSR-protecting wrapper function.
2014 *
2015 * Return: Return the Success or Failure code.
2016 */
2017static int
2018wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2019 struct wireless_dev *wdev,
2020 const void *data,
2021 int data_len)
2022{
2023 int ret;
2024
2025 cds_ssr_protect(__func__);
2026 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2027 data, data_len);
2028 cds_ssr_unprotect(__func__);
2029
2030 return ret;
2031}
2032
2033/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302034 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2035 * @wiphy: pointer phy adapter
2036 * @wdev: pointer to wireless device structure
2037 * @data: pointer to data buffer
2038 * @data_len: length of data
2039 *
2040 * This routine will give concurrency matrix
2041 *
2042 * Return: int status code
2043 */
2044static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2045 struct wireless_dev *wdev,
2046 const void *data,
2047 int data_len)
2048{
2049 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2050 uint8_t i, feature_sets, max_feature_sets;
2051 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2052 struct sk_buff *reply_skb;
2053 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2054 int ret;
2055
2056 ENTER_DEV(wdev->netdev);
2057
2058 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2059 hdd_err("Command not allowed in FTM mode");
2060 return -EPERM;
2061 }
2062
2063 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302064 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302065 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302066
2067 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2068 data, data_len, NULL)) {
2069 hdd_err("Invalid ATTR");
2070 return -EINVAL;
2071 }
2072
2073 /* Parse and fetch max feature set */
2074 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2075 hdd_err("Attr max feature set size failed");
2076 return -EINVAL;
2077 }
2078 max_feature_sets = nla_get_u32(tb[
2079 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2080 hdd_info("Max feature set size: %d", max_feature_sets);
2081
2082 /* Fill feature combination matrix */
2083 feature_sets = 0;
2084 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002085 WIFI_FEATURE_P2P;
2086 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2087 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302088 /* Add more feature combinations here */
2089
2090 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002091 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302092 hdd_info("Feature set matrix");
2093 for (i = 0; i < feature_sets; i++)
2094 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2095
2096 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2097 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2098 if (!reply_skb) {
2099 hdd_err("Feature set matrix: buffer alloc fail");
2100 return -ENOMEM;
2101 }
2102
2103 if (nla_put_u32(reply_skb,
2104 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2105 feature_sets) ||
2106 nla_put(reply_skb,
2107 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2108 sizeof(u32) * feature_sets,
2109 feature_set_matrix)) {
2110 hdd_err("nla put fail");
2111 kfree_skb(reply_skb);
2112 return -EINVAL;
2113 }
2114 return cfg80211_vendor_cmd_reply(reply_skb);
2115}
2116
2117/**
2118 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2119 * @wiphy: pointer to wireless wiphy structure.
2120 * @wdev: pointer to wireless_dev structure.
2121 * @data: Pointer to the data to be passed via vendor interface
2122 * @data_len:Length of the data to be passed
2123 *
2124 * Retrieves the concurrency feature set matrix
2125 *
2126 * Return: 0 on success, negative errno on failure
2127 */
2128static int
2129wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2130 struct wireless_dev *wdev,
2131 const void *data,
2132 int data_len)
2133{
2134 int ret;
2135
2136 cds_ssr_protect(__func__);
2137 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2138 data, data_len);
2139 cds_ssr_unprotect(__func__);
2140
2141 return ret;
2142}
2143
2144/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002145 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2146 * @feature_flags: pointer to the byte array of features.
2147 * @feature: Feature to be turned ON in the byte array.
2148 *
2149 * Return: None
2150 *
2151 * This is called to turn ON or SET the feature flag for the requested feature.
2152 **/
2153#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002154static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2155 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002156{
2157 uint32_t index;
2158 uint8_t bit_mask;
2159
2160 index = feature / NUM_BITS_IN_BYTE;
2161 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2162 feature_flags[index] |= bit_mask;
2163}
2164
2165/**
2166 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2167 * @wiphy: pointer to wireless wiphy structure.
2168 * @wdev: pointer to wireless_dev structure.
2169 * @data: Pointer to the data to be passed via vendor interface
2170 * @data_len:Length of the data to be passed
2171 *
2172 * This is called when wlan driver needs to send supported feature set to
2173 * supplicant upon a request/query from the supplicant.
2174 *
2175 * Return: Return the Success or Failure code.
2176 **/
2177#define MAX_CONCURRENT_CHAN_ON_24G 2
2178#define MAX_CONCURRENT_CHAN_ON_5G 2
2179static int
2180__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2181 struct wireless_dev *wdev,
2182 const void *data, int data_len)
2183{
2184 struct sk_buff *skb = NULL;
2185 uint32_t dbs_capability = 0;
2186 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302187 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002188 int ret_val;
2189
2190 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2191 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2192
Jeff Johnson1f61b612016-02-12 16:28:33 -08002193 ENTER_DEV(wdev->netdev);
2194
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002195 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2196 if (ret_val)
2197 return ret_val;
2198
Anurag Chouhan6d760662016-02-20 16:05:43 +05302199 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002200 hdd_err("Command not allowed in FTM mode");
2201 return -EPERM;
2202 }
2203
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002204 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002205 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002206 wlan_hdd_cfg80211_set_feature(feature_flags,
2207 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2208 }
2209
2210 wlan_hdd_cfg80211_set_feature(feature_flags,
2211 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2212 if (wma_is_scan_simultaneous_capable())
2213 wlan_hdd_cfg80211_set_feature(feature_flags,
2214 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002215
2216 if (wma_is_p2p_lo_capable())
2217 wlan_hdd_cfg80211_set_feature(feature_flags,
2218 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2219
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002220 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2221 NLMSG_HDRLEN);
2222
2223 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002224 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002225 return -ENOMEM;
2226 }
2227
2228 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2229 sizeof(feature_flags), feature_flags))
2230 goto nla_put_failure;
2231
2232 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302233 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002234 if (one_by_one_dbs)
2235 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2236
2237 if (two_by_two_dbs)
2238 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2239
2240 if (!one_by_one_dbs && !two_by_two_dbs)
2241 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2242 } else {
2243 hdd_err("wma_get_dbs_hw_mode failed");
2244 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2245 }
2246
2247 hdd_info("dbs_capability is %d", dbs_capability);
2248
2249 if (nla_put_u32(skb,
2250 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2251 MAX_CONCURRENT_CHAN_ON_24G))
2252 goto nla_put_failure;
2253
2254 if (nla_put_u32(skb,
2255 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2256 MAX_CONCURRENT_CHAN_ON_5G))
2257 goto nla_put_failure;
2258
2259 return cfg80211_vendor_cmd_reply(skb);
2260
2261nla_put_failure:
2262 kfree_skb(skb);
2263 return -EINVAL;
2264}
2265
2266/**
2267 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2268 * @wiphy: pointer to wireless wiphy structure.
2269 * @wdev: pointer to wireless_dev structure.
2270 * @data: Pointer to the data to be passed via vendor interface
2271 * @data_len:Length of the data to be passed
2272 *
2273 * This is called when wlan driver needs to send supported feature set to
2274 * supplicant upon a request/query from the supplicant.
2275 *
2276 * Return: Return the Success or Failure code.
2277 */
2278static int
2279wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2280 struct wireless_dev *wdev,
2281 const void *data, int data_len)
2282{
2283 int ret;
2284
2285 cds_ssr_protect(__func__);
2286 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2287 data, data_len);
2288 cds_ssr_unprotect(__func__);
2289
2290 return ret;
2291}
2292
2293
2294/**
2295 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2296 * @wiphy: The wiphy structure
2297 * @wdev: The wireless device
2298 * @data: Data passed by framework
2299 * @data_len: Parameters to be configured passed as data
2300 *
2301 * The roaming related parameters are configured by the framework
2302 * using this interface.
2303 *
2304 * Return: Return either success or failure code.
2305 */
2306static int
2307__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2308 struct wireless_dev *wdev, const void *data, int data_len)
2309{
2310 struct net_device *dev = wdev->netdev;
2311 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2312 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2313 uint8_t session_id;
2314 struct roam_ext_params roam_params;
2315 uint32_t cmd_type, req_id;
2316 struct nlattr *curr_attr;
2317 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2318 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2319 int rem, i;
2320 uint32_t buf_len = 0;
2321 int ret;
2322
Jeff Johnson1f61b612016-02-12 16:28:33 -08002323 ENTER_DEV(dev);
2324
Anurag Chouhan6d760662016-02-20 16:05:43 +05302325 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002326 hdd_err("Command not allowed in FTM mode");
2327 return -EPERM;
2328 }
2329
2330 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302331 if (ret)
2332 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002333
2334 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2335 data, data_len,
2336 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002337 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002338 return -EINVAL;
2339 }
2340 /* Parse and fetch Command Type*/
2341 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002342 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343 goto fail;
2344 }
2345 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302346 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002347 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2348 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002349 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002350 goto fail;
2351 }
2352 req_id = nla_get_u32(
2353 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002354 hdd_debug("Req Id (%d)", req_id);
2355 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002356 switch (cmd_type) {
2357 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2358 i = 0;
2359 nla_for_each_nested(curr_attr,
2360 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2361 rem) {
2362 if (nla_parse(tb2,
2363 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2364 nla_data(curr_attr), nla_len(curr_attr),
2365 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002366 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002367 goto fail;
2368 }
2369 /* Parse and Fetch allowed SSID list*/
2370 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002371 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002372 goto fail;
2373 }
2374 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2375 /*
2376 * Upper Layers include a null termination character.
2377 * Check for the actual permissible length of SSID and
2378 * also ensure not to copy the NULL termination
2379 * character to the driver buffer.
2380 */
2381 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2382 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2383 nla_memcpy(
2384 roam_params.ssid_allowed_list[i].ssId,
2385 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2386 buf_len - 1);
2387 roam_params.ssid_allowed_list[i].length =
2388 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002389 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002390 roam_params.ssid_allowed_list[i].length,
2391 roam_params.ssid_allowed_list[i].ssId,
2392 roam_params.ssid_allowed_list[i].length);
2393 i++;
2394 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002395 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002396 }
2397 }
2398 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002399 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002400 roam_params.num_ssid_allowed_list);
2401 sme_update_roam_params(pHddCtx->hHal, session_id,
2402 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2403 break;
2404 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2405 /* Parse and fetch 5G Boost Threshold */
2406 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002407 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002408 goto fail;
2409 }
2410 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2411 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002412 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002413 roam_params.raise_rssi_thresh_5g);
2414 /* Parse and fetch 5G Penalty Threshold */
2415 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002416 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002417 goto fail;
2418 }
2419 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2420 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002421 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002422 roam_params.drop_rssi_thresh_5g);
2423 /* Parse and fetch 5G Boost Factor */
2424 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002425 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002426 goto fail;
2427 }
2428 roam_params.raise_factor_5g = nla_get_u32(
2429 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002430 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002431 roam_params.raise_factor_5g);
2432 /* Parse and fetch 5G Penalty factor */
2433 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002434 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435 goto fail;
2436 }
2437 roam_params.drop_factor_5g = nla_get_u32(
2438 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002439 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440 roam_params.drop_factor_5g);
2441 /* Parse and fetch 5G Max Boost */
2442 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002443 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002444 goto fail;
2445 }
2446 roam_params.max_raise_rssi_5g = nla_get_u32(
2447 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002448 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449 roam_params.max_raise_rssi_5g);
2450 /* Parse and fetch Rssi Diff */
2451 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002452 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453 goto fail;
2454 }
2455 roam_params.rssi_diff = nla_get_s32(
2456 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002457 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458 roam_params.rssi_diff);
2459 /* Parse and fetch Alert Rssi Threshold */
2460 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002461 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002462 goto fail;
2463 }
2464 roam_params.alert_rssi_threshold = nla_get_u32(
2465 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002466 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002467 roam_params.alert_rssi_threshold);
2468 sme_update_roam_params(pHddCtx->hHal, session_id,
2469 roam_params,
2470 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2471 break;
2472 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2473 /* Parse and fetch Activate Good Rssi Roam */
2474 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002475 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476 goto fail;
2477 }
2478 roam_params.good_rssi_roam = nla_get_s32(
2479 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002480 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002481 roam_params.good_rssi_roam);
2482 sme_update_roam_params(pHddCtx->hHal, session_id,
2483 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2484 break;
2485 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2486 /* Parse and fetch number of preferred BSSID */
2487 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002488 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489 goto fail;
2490 }
2491 roam_params.num_bssid_favored = nla_get_u32(
2492 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002493 hdd_debug("Num of Preferred BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002494 roam_params.num_bssid_favored);
2495 i = 0;
2496 nla_for_each_nested(curr_attr,
2497 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2498 rem) {
2499 if (nla_parse(tb2,
2500 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2501 nla_data(curr_attr), nla_len(curr_attr),
2502 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002503 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002504 goto fail;
2505 }
2506 /* Parse and fetch MAC address */
2507 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002508 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 goto fail;
2510 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002511 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002512 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302513 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002514 hdd_debug(MAC_ADDRESS_STR,
2515 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002516 /* Parse and fetch preference factor*/
2517 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002518 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002519 goto fail;
2520 }
2521 roam_params.bssid_favored_factor[i] = nla_get_u32(
2522 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002523 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 roam_params.bssid_favored_factor[i]);
2525 i++;
2526 }
2527 sme_update_roam_params(pHddCtx->hHal, session_id,
2528 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2529 break;
2530 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2531 /* Parse and fetch number of blacklist BSSID */
2532 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002533 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002534 goto fail;
2535 }
2536 roam_params.num_bssid_avoid_list = nla_get_u32(
2537 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002538 hdd_debug("Num of blacklist BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 roam_params.num_bssid_avoid_list);
2540 i = 0;
2541 nla_for_each_nested(curr_attr,
2542 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2543 rem) {
2544 if (nla_parse(tb2,
2545 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2546 nla_data(curr_attr), nla_len(curr_attr),
2547 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002548 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 goto fail;
2550 }
2551 /* Parse and fetch MAC address */
2552 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002553 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 goto fail;
2555 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002556 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302558 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002559 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002561 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002562 i++;
2563 }
2564 sme_update_roam_params(pHddCtx->hHal, session_id,
2565 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2566 break;
2567 }
2568 return 0;
2569fail:
2570 return -EINVAL;
2571}
2572
2573/**
2574 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2575 * @wiphy: pointer to wireless wiphy structure.
2576 * @wdev: pointer to wireless_dev structure.
2577 * @data: Pointer to the data to be passed via vendor interface
2578 * @data_len:Length of the data to be passed
2579 *
2580 * Return: Return the Success or Failure code.
2581 */
2582static int
2583wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2584 struct wireless_dev *wdev,
2585 const void *data,
2586 int data_len)
2587{
2588 int ret;
2589
2590 cds_ssr_protect(__func__);
2591 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2592 data, data_len);
2593 cds_ssr_unprotect(__func__);
2594
2595 return ret;
2596}
2597
2598static const struct nla_policy
2599wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2600 +1] = {
2601 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2602};
2603
2604/**
2605 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2606 * @hdd_ctx: HDD context
2607 * @device_mode: device mode
2608 * Return: bool
2609 */
2610static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002611 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612{
2613 hdd_adapter_t *adapter;
2614 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2615 hdd_ap_ctx_t *ap_ctx;
2616 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302617 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002618
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302619 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620 &adapter_node);
2621
2622 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302623 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002624 adapter = adapter_node->pAdapter;
2625
2626 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002627 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 ap_ctx =
2629 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2630
2631 /*
2632 * if there is SAP already running on DFS channel,
2633 * do not disable scan on dfs channels. Note that
2634 * with SAP on DFS, there cannot be conurrency on
2635 * single radio. But then we can have multiple
2636 * radios !!
2637 */
2638 if (CHANNEL_STATE_DFS ==
2639 cds_get_channel_state(
2640 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002641 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002642 return true;
2643 }
2644 }
2645
2646 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002647 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002648 sta_ctx =
2649 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2650
2651 /*
2652 * if STA is already connected on DFS channel,
2653 * do not disable scan on dfs channels
2654 */
2655 if (hdd_conn_is_connected(sta_ctx) &&
2656 (CHANNEL_STATE_DFS ==
2657 cds_get_channel_state(
2658 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002659 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002660 return true;
2661 }
2662 }
2663
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302664 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002665 adapter_node,
2666 &next);
2667 adapter_node = next;
2668 }
2669
2670 return false;
2671}
2672
2673/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002674 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2675 * @hdd_ctx: HDD context within host driver
2676 * @adapter: Adapter pointer
2677 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2678 *
2679 * Loops through devices to see who is operating on DFS channels
2680 * and then disables/enables DFS channels by calling SME API.
2681 * Fails the disable request if any device is active on a DFS channel.
2682 *
2683 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002685
2686int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2687 hdd_adapter_t *adapter,
2688 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002690 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302691 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002692 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002693
2694 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2695 if (no_dfs_flag) {
2696 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002697 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002698
2699 if (true == status)
2700 return -EOPNOTSUPP;
2701
2702 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002703 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002704
2705 if (true == status)
2706 return -EOPNOTSUPP;
2707 }
2708
2709 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2710
2711 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2712
2713 /*
2714 * call the SME API to tunnel down the new channel list
2715 * to the firmware
2716 */
2717 status = sme_handle_dfs_chan_scan(
2718 h_hal, hdd_ctx->config->enableDFSChnlScan);
2719
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302720 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002721 ret_val = 0;
2722
2723 /*
2724 * Clear the SME scan cache also. Note that the
2725 * clearing of scan results is independent of session;
2726 * so no need to iterate over
2727 * all sessions
2728 */
2729 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302730 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731 ret_val = -EPERM;
2732 }
2733
2734 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002735 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002736 ret_val = 0;
2737 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002738 return ret_val;
2739}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002741/**
2742 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2743 * @wiphy: corestack handler
2744 * @wdev: wireless device
2745 * @data: data
2746 * @data_len: data length
2747 * Return: success(0) or reason code for failure
2748 */
2749static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2750 struct wireless_dev *wdev,
2751 const void *data,
2752 int data_len)
2753{
2754 struct net_device *dev = wdev->netdev;
2755 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2756 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2757 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2758 int ret_val;
2759 uint32_t no_dfs_flag = 0;
2760
Jeff Johnson1f61b612016-02-12 16:28:33 -08002761 ENTER_DEV(dev);
2762
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002763 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302764 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002765 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002766
2767 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2768 data, data_len,
2769 wlan_hdd_set_no_dfs_flag_config_policy)) {
2770 hdd_err("invalid attr");
2771 return -EINVAL;
2772 }
2773
2774 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2775 hdd_err("attr dfs flag failed");
2776 return -EINVAL;
2777 }
2778
2779 no_dfs_flag = nla_get_u32(
2780 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2781
Jeff Johnson020db452016-06-29 14:37:26 -07002782 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002783
2784 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002785 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002786 return -EINVAL;
2787 }
2788
2789 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2790 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791 return ret_val;
2792}
2793
2794/**
2795 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2796 *
2797 * @wiphy: wiphy device pointer
2798 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002799 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002800 * @data_len: Buffer length
2801 *
2802 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2803 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2804 *
2805 * Return: EOK or other error codes.
2806 */
2807
2808static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2809 struct wireless_dev *wdev,
2810 const void *data,
2811 int data_len)
2812{
2813 int ret;
2814
2815 cds_ssr_protect(__func__);
2816 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2817 data, data_len);
2818 cds_ssr_unprotect(__func__);
2819
2820 return ret;
2821}
2822
Manikandan Mohan80dea792016-04-28 16:36:48 -07002823static const struct nla_policy
2824wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2825 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2826};
2827
2828/**
2829 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2830 * @wiphy: wiphy device pointer
2831 * @wdev: wireless device pointer
2832 * @data: Vendor command data buffer
2833 * @data_len: Buffer length
2834 *
2835 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2836 * setup WISA Mode features.
2837 *
2838 * Return: Success(0) or reason code for failure
2839 */
2840static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2841 struct wireless_dev *wdev, const void *data, int data_len)
2842{
2843 struct net_device *dev = wdev->netdev;
2844 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2845 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2846 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2847 struct sir_wisa_params wisa;
2848 int ret_val;
2849 QDF_STATUS status;
2850 bool wisa_mode;
2851
2852 ENTER_DEV(dev);
2853 ret_val = wlan_hdd_validate_context(hdd_ctx);
2854 if (ret_val)
2855 goto err;
2856
2857 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2858 hdd_err("Command not allowed in FTM mode");
2859 return -EPERM;
2860 }
2861
2862 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2863 wlan_hdd_wisa_cmd_policy)) {
2864 hdd_err("Invalid WISA cmd attributes");
2865 ret_val = -EINVAL;
2866 goto err;
2867 }
2868 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2869 hdd_err("Invalid WISA mode");
2870 ret_val = -EINVAL;
2871 goto err;
2872 }
2873
2874 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2875 hdd_info("WISA Mode: %d", wisa_mode);
2876 wisa.mode = wisa_mode;
2877 wisa.vdev_id = adapter->sessionId;
2878 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002879 if (!QDF_IS_STATUS_SUCCESS(status)) {
2880 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002881 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002882 }
2883 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
2884 ol_txrx_set_wisa_mode(ol_txrx_get_vdev_from_vdev_id(
2885 adapter->sessionId), wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002886err:
2887 EXIT();
2888 return ret_val;
2889}
2890
2891/**
2892 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2893 * @wiphy: corestack handler
2894 * @wdev: wireless device
2895 * @data: data
2896 * @data_len: data length
2897 *
2898 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2899 * setup WISA mode features.
2900 *
2901 * Return: Success(0) or reason code for failure
2902 */
2903static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2904 struct wireless_dev *wdev,
2905 const void *data,
2906 int data_len)
2907{
2908 int ret;
2909
2910 cds_ssr_protect(__func__);
2911 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2912 cds_ssr_unprotect(__func__);
2913
2914 return ret;
2915}
2916
Anurag Chouhan96919482016-07-13 16:36:57 +05302917/*
2918 * define short names for the global vendor params
2919 * used by __wlan_hdd_cfg80211_get_station_cmd()
2920 */
2921#define STATION_INVALID \
2922 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2923#define STATION_INFO \
2924 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2925#define STATION_ASSOC_FAIL_REASON \
2926 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2927#define STATION_MAX \
2928 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2929
2930static const struct nla_policy
2931hdd_get_station_policy[STATION_MAX + 1] = {
2932 [STATION_INFO] = {.type = NLA_FLAG},
2933 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2934};
2935
2936/**
2937 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2938 * @hdd_ctx: HDD context within host driver
2939 * @wdev: wireless device
2940 *
2941 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
2942 * Validate cmd attributes and send the station info to upper layers.
2943 *
2944 * Return: Success(0) or reason code for failure
2945 */
2946static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
2947 hdd_adapter_t *adapter)
2948{
2949 struct sk_buff *skb = NULL;
2950 uint32_t nl_buf_len;
2951 hdd_station_ctx_t *hdd_sta_ctx;
2952
2953 nl_buf_len = NLMSG_HDRLEN;
2954 nl_buf_len += sizeof(uint32_t);
2955 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
2956
2957 if (!skb) {
2958 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
2959 return -ENOMEM;
2960 }
2961
2962 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2963
2964 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
2965 hdd_sta_ctx->conn_info.assoc_status_code)) {
2966 hdd_err("put fail");
2967 goto fail;
2968 }
2969 return cfg80211_vendor_cmd_reply(skb);
2970fail:
2971 if (skb)
2972 kfree_skb(skb);
2973 return -EINVAL;
2974}
2975
2976/**
2977 * hdd_map_auth_type() - transform auth type specific to
2978 * vendor command
2979 * @auth_type: csr auth type
2980 *
2981 * Return: Success(0) or reason code for failure
2982 */
2983static int hdd_convert_auth_type(uint32_t auth_type)
2984{
2985 uint32_t ret_val;
2986
2987 switch (auth_type) {
2988 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
2989 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
2990 break;
2991 case eCSR_AUTH_TYPE_SHARED_KEY:
2992 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
2993 break;
2994 case eCSR_AUTH_TYPE_WPA:
2995 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
2996 break;
2997 case eCSR_AUTH_TYPE_WPA_PSK:
2998 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
2999 break;
3000 case eCSR_AUTH_TYPE_AUTOSWITCH:
3001 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3002 break;
3003 case eCSR_AUTH_TYPE_WPA_NONE:
3004 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3005 break;
3006 case eCSR_AUTH_TYPE_RSN:
3007 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3008 break;
3009 case eCSR_AUTH_TYPE_RSN_PSK:
3010 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3011 break;
3012 case eCSR_AUTH_TYPE_FT_RSN:
3013 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3014 break;
3015 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3016 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3017 break;
3018 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3019 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3020 break;
3021 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3022 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3023 break;
3024 case eCSR_AUTH_TYPE_CCKM_WPA:
3025 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3026 break;
3027 case eCSR_AUTH_TYPE_CCKM_RSN:
3028 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3029 break;
3030 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3031 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3032 break;
3033 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3034 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3035 break;
3036 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3037 case eCSR_AUTH_TYPE_FAILED:
3038 case eCSR_AUTH_TYPE_NONE:
3039 default:
3040 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3041 break;
3042 }
3043 return ret_val;
3044}
3045
3046/**
3047 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3048 * vendor command
3049 * @dot11mode: dot11mode
3050 *
3051 * Return: Success(0) or reason code for failure
3052 */
3053static int hdd_convert_dot11mode(uint32_t dot11mode)
3054{
3055 uint32_t ret_val;
3056
3057 switch (dot11mode) {
3058 case eCSR_CFG_DOT11_MODE_11A:
3059 ret_val = QCA_WLAN_802_11_MODE_11A;
3060 break;
3061 case eCSR_CFG_DOT11_MODE_11B:
3062 ret_val = QCA_WLAN_802_11_MODE_11B;
3063 break;
3064 case eCSR_CFG_DOT11_MODE_11G:
3065 ret_val = QCA_WLAN_802_11_MODE_11G;
3066 break;
3067 case eCSR_CFG_DOT11_MODE_11N:
3068 ret_val = QCA_WLAN_802_11_MODE_11N;
3069 break;
3070 case eCSR_CFG_DOT11_MODE_11AC:
3071 ret_val = QCA_WLAN_802_11_MODE_11AC;
3072 break;
3073 case eCSR_CFG_DOT11_MODE_AUTO:
3074 case eCSR_CFG_DOT11_MODE_ABG:
3075 default:
3076 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3077 }
3078 return ret_val;
3079}
3080
3081/**
3082 * hdd_add_tx_bitrate() - add tx bitrate attribute
3083 * @skb: pointer to sk buff
3084 * @hdd_sta_ctx: pointer to hdd station context
3085 * @idx: attribute index
3086 *
3087 * Return: Success(0) or reason code for failure
3088 */
3089static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3090 hdd_station_ctx_t *hdd_sta_ctx,
3091 int idx)
3092{
3093 struct nlattr *nla_attr;
3094 uint32_t bitrate, bitrate_compat;
3095
3096 nla_attr = nla_nest_start(skb, idx);
3097 if (!nla_attr)
3098 goto fail;
3099 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3100 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3101
3102 /* report 16-bit bitrate only if we can */
3103 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3104 if (bitrate > 0 &&
3105 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3106 hdd_err("put fail");
3107 goto fail;
3108 }
3109 if (bitrate_compat > 0 &&
3110 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3111 hdd_err("put fail");
3112 goto fail;
3113 }
3114 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3115 hdd_sta_ctx->conn_info.txrate.nss)) {
3116 hdd_err("put fail");
3117 goto fail;
3118 }
3119 nla_nest_end(skb, nla_attr);
3120 return 0;
3121fail:
3122 return -EINVAL;
3123}
3124
3125/**
3126 * hdd_add_sta_info() - add station info attribute
3127 * @skb: pointer to sk buff
3128 * @hdd_sta_ctx: pointer to hdd station context
3129 * @idx: attribute index
3130 *
3131 * Return: Success(0) or reason code for failure
3132 */
3133static int32_t hdd_add_sta_info(struct sk_buff *skb,
3134 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3135{
3136 struct nlattr *nla_attr;
3137
3138 nla_attr = nla_nest_start(skb, idx);
3139 if (!nla_attr)
3140 goto fail;
3141 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3142 (hdd_sta_ctx->conn_info.signal + 100))) {
3143 hdd_err("put fail");
3144 goto fail;
3145 }
3146 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3147 goto fail;
3148 nla_nest_end(skb, nla_attr);
3149 return 0;
3150fail:
3151 return -EINVAL;
3152}
3153
3154/**
3155 * hdd_add_survey_info() - add survey info attribute
3156 * @skb: pointer to sk buff
3157 * @hdd_sta_ctx: pointer to hdd station context
3158 * @idx: attribute index
3159 *
3160 * Return: Success(0) or reason code for failure
3161 */
3162static int32_t hdd_add_survey_info(struct sk_buff *skb,
3163 hdd_station_ctx_t *hdd_sta_ctx,
3164 int idx)
3165{
3166 struct nlattr *nla_attr;
3167
3168 nla_attr = nla_nest_start(skb, idx);
3169 if (!nla_attr)
3170 goto fail;
3171 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3172 hdd_sta_ctx->conn_info.freq) ||
3173 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3174 (hdd_sta_ctx->conn_info.noise + 100))) {
3175 hdd_err("put fail");
3176 goto fail;
3177 }
3178 nla_nest_end(skb, nla_attr);
3179 return 0;
3180fail:
3181 return -EINVAL;
3182}
3183
3184/**
3185 * hdd_add_link_standard_info() - add link info attribute
3186 * @skb: pointer to sk buff
3187 * @hdd_sta_ctx: pointer to hdd station context
3188 * @idx: attribute index
3189 *
3190 * Return: Success(0) or reason code for failure
3191 */
3192static int32_t
3193hdd_add_link_standard_info(struct sk_buff *skb,
3194 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3195{
3196 struct nlattr *nla_attr;
3197
3198 nla_attr = nla_nest_start(skb, idx);
3199 if (!nla_attr)
3200 goto fail;
3201 if (nla_put(skb,
3202 NL80211_ATTR_SSID,
3203 hdd_sta_ctx->conn_info.SSID.SSID.length,
3204 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3205 hdd_err("put fail");
3206 goto fail;
3207 }
3208 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3209 goto fail;
3210 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3211 goto fail;
3212 nla_nest_end(skb, nla_attr);
3213 return 0;
3214fail:
3215 return -EINVAL;
3216}
3217
3218/**
3219 * hdd_add_ap_standard_info() - add ap info attribute
3220 * @skb: pointer to sk buff
3221 * @hdd_sta_ctx: pointer to hdd station context
3222 * @idx: attribute index
3223 *
3224 * Return: Success(0) or reason code for failure
3225 */
3226static int32_t
3227hdd_add_ap_standard_info(struct sk_buff *skb,
3228 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3229{
3230 struct nlattr *nla_attr;
3231
3232 nla_attr = nla_nest_start(skb, idx);
3233 if (!nla_attr)
3234 goto fail;
3235 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3236 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3237 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3238 &hdd_sta_ctx->conn_info.vht_caps)) {
3239 hdd_err("put fail");
3240 goto fail;
3241 }
3242 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3243 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3244 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3245 &hdd_sta_ctx->conn_info.ht_caps)) {
3246 hdd_err("put fail");
3247 goto fail;
3248 }
3249 nla_nest_end(skb, nla_attr);
3250 return 0;
3251fail:
3252 return -EINVAL;
3253}
3254
3255/**
3256 * hdd_get_station_info() - send BSS information to supplicant
3257 * @hdd_ctx: pointer to hdd context
3258 * @adapter: pointer to adapter
3259 *
3260 * Return: 0 if success else error status
3261 */
3262static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3263 hdd_adapter_t *adapter)
3264{
3265 struct sk_buff *skb = NULL;
3266 uint8_t *tmp_hs20 = NULL;
3267 uint32_t nl_buf_len;
3268 hdd_station_ctx_t *hdd_sta_ctx;
3269
3270 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3271
3272 nl_buf_len = NLMSG_HDRLEN;
3273 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3274 sizeof(hdd_sta_ctx->conn_info.freq) +
3275 sizeof(hdd_sta_ctx->conn_info.noise) +
3276 sizeof(hdd_sta_ctx->conn_info.signal) +
3277 (sizeof(uint32_t) * 2) +
3278 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3279 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3280 sizeof(hdd_sta_ctx->conn_info.authType) +
3281 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3282 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3283 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3284 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3285 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3286 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3287 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3288 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3289 1);
3290 }
3291 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3292 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3293 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3294 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3295
3296
3297 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3298 if (!skb) {
3299 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3300 return -ENOMEM;
3301 }
3302
3303 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3304 LINK_INFO_STANDARD_NL80211_ATTR)) {
3305 hdd_err("put fail");
3306 goto fail;
3307 }
3308 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3309 AP_INFO_STANDARD_NL80211_ATTR)) {
3310 hdd_err("put fail");
3311 goto fail;
3312 }
3313 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3314 hdd_sta_ctx->conn_info.roam_count) ||
3315 nla_put_u32(skb, INFO_AKM,
3316 hdd_convert_auth_type(
3317 hdd_sta_ctx->conn_info.authType)) ||
3318 nla_put_u32(skb, WLAN802_11_MODE,
3319 hdd_convert_dot11mode(
3320 hdd_sta_ctx->conn_info.dot11Mode))) {
3321 hdd_err("put fail");
3322 goto fail;
3323 }
3324 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3325 if (nla_put(skb, HT_OPERATION,
3326 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3327 &hdd_sta_ctx->conn_info.ht_operation)) {
3328 hdd_err("put fail");
3329 goto fail;
3330 }
3331 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3332 if (nla_put(skb, VHT_OPERATION,
3333 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3334 &hdd_sta_ctx->conn_info.vht_operation)) {
3335 hdd_err("put fail");
3336 goto fail;
3337 }
3338 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3339 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3340 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3341 tmp_hs20 + 1)) {
3342 hdd_err("put fail");
3343 goto fail;
3344 }
3345
3346 return cfg80211_vendor_cmd_reply(skb);
3347fail:
3348 if (skb)
3349 kfree_skb(skb);
3350 return -EINVAL;
3351}
3352
3353/**
3354 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3355 * @wiphy: corestack handler
3356 * @wdev: wireless device
3357 * @data: data
3358 * @data_len: data length
3359 *
3360 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3361 * Validate cmd attributes and send the station info to upper layers.
3362 *
3363 * Return: Success(0) or reason code for failure
3364 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303365static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303366__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3367 struct wireless_dev *wdev,
3368 const void *data,
3369 int data_len)
3370{
3371 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3372 struct net_device *dev = wdev->netdev;
3373 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3374 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3375 int32_t status;
3376
3377 ENTER_DEV(dev);
3378 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3379 hdd_err("Command not allowed in FTM mode");
3380 status = -EPERM;
3381 goto out;
3382 }
3383
3384 status = wlan_hdd_validate_context(hdd_ctx);
3385 if (0 != status)
3386 goto out;
3387
3388
3389 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3390 data, data_len, NULL);
3391 if (status) {
3392 hdd_err("Invalid ATTR");
3393 goto out;
3394 }
3395
3396 /* Parse and fetch Command Type*/
3397 if (tb[STATION_INFO]) {
3398 status = hdd_get_station_info(hdd_ctx, adapter);
3399 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3400 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3401 } else {
3402 hdd_err("get station info cmd type failed");
3403 status = -EINVAL;
3404 goto out;
3405 }
3406 EXIT();
3407out:
3408 return status;
3409}
3410
3411/**
3412 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3413 * @wiphy: corestack handler
3414 * @wdev: wireless device
3415 * @data: data
3416 * @data_len: data length
3417 *
3418 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3419 * Validate cmd attributes and send the station info to upper layers.
3420 *
3421 * Return: Success(0) or reason code for failure
3422 */
3423static int32_t
3424hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3425 struct wireless_dev *wdev,
3426 const void *data,
3427 int data_len)
3428{
3429 int ret;
3430
3431 cds_ssr_protect(__func__);
3432 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3433 cds_ssr_unprotect(__func__);
3434
3435 return ret;
3436}
3437
3438/*
3439 * undef short names defined for get station command
3440 * used by __wlan_hdd_cfg80211_get_station_cmd()
3441 */
3442#undef STATION_INVALID
3443#undef STATION_INFO
3444#undef STATION_ASSOC_FAIL_REASON
3445#undef STATION_MAX
3446
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003447#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3448/**
3449 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3450 * @wiphy: pointer to wireless wiphy structure.
3451 * @wdev: pointer to wireless_dev structure.
3452 * @data: Pointer to the Key data
3453 * @data_len:Length of the data passed
3454 *
3455 * This is called when wlan driver needs to save the keys received via
3456 * vendor specific command.
3457 *
3458 * Return: Return the Success or Failure code.
3459 */
3460static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3461 struct wireless_dev *wdev,
3462 const void *data, int data_len)
3463{
3464 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3465 struct net_device *dev = wdev->netdev;
3466 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3467 hdd_context_t *hdd_ctx_ptr;
3468 int status;
3469
Jeff Johnson1f61b612016-02-12 16:28:33 -08003470 ENTER_DEV(dev);
3471
Anurag Chouhan6d760662016-02-20 16:05:43 +05303472 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003473 hdd_err("Command not allowed in FTM mode");
3474 return -EPERM;
3475 }
3476
3477 if ((data == NULL) || (data_len == 0) ||
3478 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003479 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003480 return -EINVAL;
3481 }
3482
3483 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3484 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003485 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003486 return -EINVAL;
3487 }
3488
3489 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303490 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003491 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3493 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003494 true,
3495 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303496 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3497 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003498 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3499 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3500 return 0;
3501}
3502
3503/**
3504 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3505 * @wiphy: pointer to wireless wiphy structure.
3506 * @wdev: pointer to wireless_dev structure.
3507 * @data: Pointer to the Key data
3508 * @data_len:Length of the data passed
3509 *
3510 * This is called when wlan driver needs to save the keys received via
3511 * vendor specific command.
3512 *
3513 * Return: Return the Success or Failure code.
3514 */
3515static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3516 struct wireless_dev *wdev,
3517 const void *data, int data_len)
3518{
3519 int ret;
3520
3521 cds_ssr_protect(__func__);
3522 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3523 cds_ssr_unprotect(__func__);
3524
3525 return ret;
3526}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003527#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003528
3529static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3530 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3531 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3532 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003533 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003534};
3535
3536/**
3537 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3538 * @wiphy: pointer to wireless wiphy structure.
3539 * @wdev: pointer to wireless_dev structure.
3540 * @data: Pointer to the data to be passed via vendor interface
3541 * @data_len:Length of the data to be passed
3542 *
3543 * This is called when wlan driver needs to send wifi driver related info
3544 * (driver/fw version) to the user space application upon request.
3545 *
3546 * Return: Return the Success or Failure code.
3547 */
3548static int
3549__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3550 struct wireless_dev *wdev,
3551 const void *data, int data_len)
3552{
3553 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3554 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003555 tSirVersionString driver_version;
3556 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003557 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003558 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003559 struct sk_buff *reply_skb;
3560 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561
Jeff Johnson1f61b612016-02-12 16:28:33 -08003562 ENTER_DEV(wdev->netdev);
3563
Anurag Chouhan6d760662016-02-20 16:05:43 +05303564 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003565 hdd_err("Command not allowed in FTM mode");
3566 return -EPERM;
3567 }
3568
3569 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303570 if (status)
3571 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003572
3573 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3574 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003575 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003576 return -EINVAL;
3577 }
3578
3579 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003580 hdd_err("Rcvd req for Driver version");
3581 strlcpy(driver_version, QWLAN_VERSIONSTR,
3582 sizeof(driver_version));
3583 skb_len += strlen(driver_version) + 1;
3584 count++;
3585 }
3586
3587 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3588 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003589 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3590 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003591 snprintf(firmware_version, sizeof(firmware_version),
3592 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3593 skb_len += strlen(firmware_version) + 1;
3594 count++;
3595 }
3596
3597 if (count == 0) {
3598 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003599 return -EINVAL;
3600 }
3601
Ryan Hsu7ac88852016-04-28 10:20:34 -07003602 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3603 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3604
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003605 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003606 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003607 return -ENOMEM;
3608 }
3609
Ryan Hsu7ac88852016-04-28 10:20:34 -07003610 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3611 if (nla_put_string(reply_skb,
3612 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3613 driver_version))
3614 goto error_nla_fail;
3615 }
3616
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05303617 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003618 if (nla_put_string(reply_skb,
3619 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3620 firmware_version))
3621 goto error_nla_fail;
3622 }
3623
3624 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3625 if (nla_put_u32(reply_skb,
3626 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3627 hdd_ctx->radio_index))
3628 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003629 }
3630
3631 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003632
3633error_nla_fail:
3634 hdd_err("nla put fail");
3635 kfree_skb(reply_skb);
3636 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003637}
3638
3639/**
3640 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3641 * @wiphy: pointer to wireless wiphy structure.
3642 * @wdev: pointer to wireless_dev structure.
3643 * @data: Pointer to the data to be passed via vendor interface
3644 * @data_len:Length of the data to be passed
3645 *
3646 * This is called when wlan driver needs to send wifi driver related info
3647 * (driver/fw version) to the user space application upon request.
3648 *
3649 * Return: Return the Success or Failure code.
3650 */
3651static int
3652wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3653 struct wireless_dev *wdev,
3654 const void *data, int data_len)
3655{
3656 int ret;
3657
3658 cds_ssr_protect(__func__);
3659 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3660 cds_ssr_unprotect(__func__);
3661
3662 return ret;
3663}
3664
3665/**
3666 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3667 * @wiphy: pointer to wireless wiphy structure.
3668 * @wdev: pointer to wireless_dev structure.
3669 * @data: Pointer to the data to be passed via vendor interface
3670 * @data_len:Length of the data to be passed
3671 *
3672 * This is called by userspace to know the supported logger features
3673 *
3674 * Return: Return the Success or Failure code.
3675 */
3676static int
3677__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3678 struct wireless_dev *wdev,
3679 const void *data, int data_len)
3680{
3681 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3682 int status;
3683 uint32_t features;
3684 struct sk_buff *reply_skb = NULL;
3685
Jeff Johnson1f61b612016-02-12 16:28:33 -08003686 ENTER_DEV(wdev->netdev);
3687
Anurag Chouhan6d760662016-02-20 16:05:43 +05303688 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003689 hdd_err("Command not allowed in FTM mode");
3690 return -EPERM;
3691 }
3692
3693 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303694 if (status)
3695 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003696
3697 features = 0;
3698
3699 if (hdd_is_memdump_supported())
3700 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3701 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3702 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3703 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3704
3705 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3706 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3707 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003708 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003709 return -ENOMEM;
3710 }
3711
Jeff Johnson020db452016-06-29 14:37:26 -07003712 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003713 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3714 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003715 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003716 kfree_skb(reply_skb);
3717 return -EINVAL;
3718 }
3719
3720 return cfg80211_vendor_cmd_reply(reply_skb);
3721}
3722
3723/**
3724 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3725 * @wiphy: pointer to wireless wiphy structure.
3726 * @wdev: pointer to wireless_dev structure.
3727 * @data: Pointer to the data to be passed via vendor interface
3728 * @data_len:Length of the data to be passed
3729 *
3730 * This is called by userspace to know the supported logger features
3731 *
3732 * Return: Return the Success or Failure code.
3733 */
3734static int
3735wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3736 struct wireless_dev *wdev,
3737 const void *data, int data_len)
3738{
3739 int ret;
3740
3741 cds_ssr_protect(__func__);
3742 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3743 data, data_len);
3744 cds_ssr_unprotect(__func__);
3745
3746 return ret;
3747}
3748
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003749#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003750/**
3751 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3752 * @hdd_ctx_ptr: pointer to HDD Context.
3753 * @bssid: pointer to bssid of roamed AP.
3754 * @req_rsn_ie: Pointer to request RSN IE
3755 * @req_rsn_len: Length of the request RSN IE
3756 * @rsp_rsn_ie: Pointer to response RSN IE
3757 * @rsp_rsn_len: Length of the response RSN IE
3758 * @roam_info_ptr: Pointer to the roaming related information
3759 *
3760 * This is called when wlan driver needs to send the roaming and
3761 * authorization information after roaming.
3762 *
3763 * The information that would be sent is the request RSN IE, response
3764 * RSN IE and BSSID of the newly roamed AP.
3765 *
3766 * If the Authorized status is authenticated, then additional parameters
3767 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3768 * supplicant.
3769 *
3770 * The supplicant upon receiving this event would ignore the legacy
3771 * cfg80211_roamed call and use the entire information from this event.
3772 * The cfg80211_roamed should still co-exist since the kernel will
3773 * make use of the parameters even if the supplicant ignores it.
3774 *
3775 * Return: Return the Success or Failure code.
3776 */
3777int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3778 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3779 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3780{
3781 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003782 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783 ENTER();
3784
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303785 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003786 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003787
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003788 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003789 !roam_info_ptr->roamSynchInProgress)
3790 return 0;
3791
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003792 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3793 NULL,
3794 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3795 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3796 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003797 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003798 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3799 GFP_KERNEL);
3800
3801 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003802 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003803 return -EINVAL;
3804 }
3805
3806 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3807 ETH_ALEN, bssid) ||
3808 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3809 req_rsn_len, req_rsn_ie) ||
3810 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3811 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003812 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003813 goto nla_put_failure;
3814 }
Jeff Johnson020db452016-06-29 14:37:26 -07003815 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003816 if (roam_info_ptr->synchAuthStatus ==
3817 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003818 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003819 if (nla_put_u8(skb,
3820 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3821 hdd_err("nla put fail");
3822 goto nla_put_failure;
3823 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003824 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3825 /* if FT or CCKM connection: dont send replay counter */
3826 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3827 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3828 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3829 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3830 nla_put(skb,
3831 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3832 SIR_REPLAY_CTR_LEN,
3833 roam_info_ptr->replay_ctr)) {
3834 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003835 hdd_err("failed to send replay counter.");
3836 goto nla_put_failure;
3837 }
3838 if (nla_put(skb,
3839 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3840 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3841 nla_put(skb,
3842 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3843 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3844 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003845 goto nla_put_failure;
3846 }
3847 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003848 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003849 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3850 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003851 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003852 goto nla_put_failure;
3853 }
3854 }
3855
Jeff Johnson020db452016-06-29 14:37:26 -07003856 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003857 roam_info_ptr->subnet_change_status);
3858
3859 /*
3860 * Add subnet change status if subnet has changed
3861 * 0 = unchanged
3862 * 1 = changed
3863 * 2 = unknown
3864 */
3865 if (roam_info_ptr->subnet_change_status) {
3866 if (nla_put_u8(skb,
3867 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3868 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003869 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003870 goto nla_put_failure;
3871 }
3872 }
3873
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003874 cfg80211_vendor_event(skb, GFP_KERNEL);
3875 return 0;
3876
3877nla_put_failure:
3878 kfree_skb(skb);
3879 return -EINVAL;
3880}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003881#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003882
3883static const struct nla_policy
3884wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3885
3886 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3887 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3888 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303889 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303890 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3891 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003892 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
3893 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
3894 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
3895 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
3896 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003897};
3898
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003899/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303900 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3901 *
3902 * @adapter: Pointer to HDD adapter
3903 * @ie_data: Pointer to Scan IEs buffer
3904 * @ie_len: Length of Scan IEs
3905 *
3906 * Return: 0 on success; error number otherwise
3907 */
3908static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3909 uint8_t *ie_data, uint8_t ie_len)
3910{
3911 hdd_scaninfo_t *scan_info = NULL;
3912 scan_info = &adapter->scan_info;
3913
3914 if (scan_info->default_scan_ies) {
3915 qdf_mem_free(scan_info->default_scan_ies);
3916 scan_info->default_scan_ies = NULL;
3917 }
3918
3919 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3920 if (!scan_info->default_scan_ies)
3921 return -ENOMEM;
3922
3923 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3924 scan_info->default_scan_ies_len = ie_len;
3925 return 0;
3926}
3927
3928/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003929 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3930 * vendor command
3931 *
3932 * @wiphy: wiphy device pointer
3933 * @wdev: wireless device pointer
3934 * @data: Vendor command data buffer
3935 * @data_len: Buffer length
3936 *
3937 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3938 *
3939 * Return: Error code.
3940 */
3941static int
3942__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3943 struct wireless_dev *wdev,
3944 const void *data,
3945 int data_len)
3946{
3947 struct net_device *dev = wdev->netdev;
3948 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3949 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3950 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3951 int ret_val = 0;
3952 u32 modulated_dtim;
3953 u16 stats_avg_factor;
3954 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303955 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003956 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07003957 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303958 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303959 int attr_len;
3960 int access_policy = 0;
3961 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3962 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303963 uint16_t scan_ie_len = 0;
3964 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303965 struct sir_set_tx_rx_aggregation_size request;
3966 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003967 uint8_t retry, delay;
3968 int param_id;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303969
Jeff Johnson1f61b612016-02-12 16:28:33 -08003970 ENTER_DEV(dev);
3971
Anurag Chouhan6d760662016-02-20 16:05:43 +05303972 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003973 hdd_err("Command not allowed in FTM mode");
3974 return -EPERM;
3975 }
3976
3977 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303978 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003979 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003980
3981 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3982 data, data_len,
3983 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07003984 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003985 return -EINVAL;
3986 }
3987
Krunal Sonie3531942016-04-12 17:43:53 -07003988 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
3989 ftm_capab = nla_get_u32(tb[
3990 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
3991 hdd_ctx->config->fine_time_meas_cap =
3992 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
3993 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05303994 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07003995 hdd_ctx->config->fine_time_meas_cap);
3996 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
3997 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
3998 hdd_ctx->config->fine_time_meas_cap);
3999 }
4000
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004001 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4002 modulated_dtim = nla_get_u32(
4003 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4004
4005 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4006 adapter->sessionId,
4007 modulated_dtim);
4008
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304009 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004010 ret_val = -EPERM;
4011 }
4012
Kapil Gupta6213c012016-09-02 19:39:09 +05304013 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4014 qpower = nla_get_u8(
4015 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4016 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4017 ret_val = -EINVAL;
4018 }
4019
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004020 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4021 stats_avg_factor = nla_get_u16(
4022 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4023 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4024 adapter->sessionId,
4025 stats_avg_factor);
4026
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304027 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004028 ret_val = -EPERM;
4029 }
4030
4031
4032 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4033 guard_time = nla_get_u32(
4034 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4035 status = sme_configure_guard_time(hdd_ctx->hHal,
4036 adapter->sessionId,
4037 guard_time);
4038
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304039 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004040 ret_val = -EPERM;
4041 }
4042
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304043 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4044 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4045 attr_len = nla_len(
4046 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4047 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4048 hdd_info("Invalid value. attr_len %d",
4049 attr_len);
4050 return -EINVAL;
4051 }
4052
4053 nla_memcpy(&vendor_ie,
4054 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4055 attr_len);
4056 vendor_ie_present = true;
4057 hdd_info("Access policy vendor ie present.attr_len %d",
4058 attr_len);
4059 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4060 &vendor_ie[0], attr_len);
4061 }
4062
4063 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4064 access_policy = (int) nla_get_u32(
4065 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4066 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4067 (access_policy >
4068 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4069 hdd_info("Invalid value. access_policy %d",
4070 access_policy);
4071 return -EINVAL;
4072 }
4073 access_policy_present = true;
4074 hdd_info("Access policy present. access_policy %d",
4075 access_policy);
4076 }
4077
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004078 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4079 retry = nla_get_u8(tb[
4080 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4081 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4082 CFG_NON_AGG_RETRY_MAX : retry;
4083 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4084 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4085 retry, PDEV_CMD);
4086 }
4087
4088 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4089 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4090 retry = retry > CFG_AGG_RETRY_MAX ?
4091 CFG_AGG_RETRY_MAX : retry;
4092
4093 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4094 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4095 CFG_AGG_RETRY_MIN : retry;
4096 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4097 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4098 retry, PDEV_CMD);
4099 }
4100
4101 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4102 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4103 retry = retry > CFG_MGMT_RETRY_MAX ?
4104 CFG_MGMT_RETRY_MAX : retry;
4105 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4106 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4107 retry, PDEV_CMD);
4108 }
4109
4110 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4111 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4112 retry = retry > CFG_CTRL_RETRY_MAX ?
4113 CFG_CTRL_RETRY_MAX : retry;
4114 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4115 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4116 retry, PDEV_CMD);
4117 }
4118
4119 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4120 delay = nla_get_u8(tb[
4121 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4122 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4123 CFG_PROPAGATION_DELAY_MAX : delay;
4124 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4125 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4126 delay, PDEV_CMD);
4127 }
4128
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304129 if (vendor_ie_present && access_policy_present) {
4130 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4131 access_policy =
4132 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304133 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304134 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304135 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304136
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304137 hdd_info("calling sme_update_access_policy_vendor_ie");
4138 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4139 adapter->sessionId, &vendor_ie[0],
4140 access_policy);
4141 if (QDF_STATUS_SUCCESS != status) {
4142 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304143 return -EINVAL;
4144 }
4145 }
4146
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304147 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4148 set_value = nla_get_u8(
4149 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4150 hdd_info("set_value: %d", set_value);
4151 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4152 }
4153
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304154 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4155 scan_ie_len = nla_len(
4156 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4157 hdd_info("Received default scan IE of len %d session %d device mode %d",
4158 scan_ie_len, adapter->sessionId,
4159 adapter->device_mode);
4160 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4161 scan_ie = (uint8_t *) nla_data(tb
4162 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304163
4164 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4165 scan_ie_len))
4166 hdd_err("Failed to save default scan IEs");
4167
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304168 if (adapter->device_mode == QDF_STA_MODE) {
4169 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4170 adapter->sessionId, scan_ie,
4171 scan_ie_len);
4172 if (QDF_STATUS_SUCCESS != status)
4173 ret_val = -EPERM;
4174 }
4175 } else
4176 ret_val = -EPERM;
4177 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304178
4179 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4180 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4181 /* if one is specified, both must be specified */
4182 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4183 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4184 hdd_err("Both TX and RX MPDU Aggregation required");
4185 return -EINVAL;
4186 }
4187
4188 request.tx_aggregation_size = nla_get_u8(
4189 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4190 request.rx_aggregation_size = nla_get_u8(
4191 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4192 request.vdev_id = adapter->sessionId;
4193
4194 if (request.tx_aggregation_size >=
4195 CFG_TX_AGGREGATION_SIZE_MIN &&
4196 request.tx_aggregation_size <=
4197 CFG_TX_AGGREGATION_SIZE_MAX &&
4198 request.rx_aggregation_size >=
4199 CFG_RX_AGGREGATION_SIZE_MIN &&
4200 request.rx_aggregation_size <=
4201 CFG_RX_AGGREGATION_SIZE_MAX) {
4202 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4203 if (qdf_status != QDF_STATUS_SUCCESS) {
4204 hdd_err("failed to set aggr sizes err %d",
4205 qdf_status);
4206 ret_val = -EPERM;
4207 }
4208 } else {
4209 hdd_err("TX %d RX %d MPDU aggr size not in range",
4210 request.tx_aggregation_size,
4211 request.rx_aggregation_size);
4212 ret_val = -EINVAL;
4213 }
4214 }
4215
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304216 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4217 uint8_t ignore_assoc_disallowed;
4218
4219 ignore_assoc_disallowed
4220 = nla_get_u8(tb[
4221 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4222 hdd_info("Set ignore_assoc_disallowed value - %d",
4223 ignore_assoc_disallowed);
4224 if ((ignore_assoc_disallowed <
4225 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4226 (ignore_assoc_disallowed >
4227 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4228 return -EPERM;
4229
4230 sme_update_session_param(hdd_ctx->hHal,
4231 adapter->sessionId,
4232 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4233 ignore_assoc_disallowed);
4234 }
4235
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004236 return ret_val;
4237}
4238
4239/**
4240 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4241 * vendor command
4242 *
4243 * @wiphy: wiphy device pointer
4244 * @wdev: wireless device pointer
4245 * @data: Vendor command data buffer
4246 * @data_len: Buffer length
4247 *
4248 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4249 *
4250 * Return: EOK or other error codes.
4251 */
4252static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4253 struct wireless_dev *wdev,
4254 const void *data,
4255 int data_len)
4256{
4257 int ret;
4258
4259 cds_ssr_protect(__func__);
4260 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4261 data, data_len);
4262 cds_ssr_unprotect(__func__);
4263
4264 return ret;
4265}
4266
4267static const struct
4268nla_policy
4269qca_wlan_vendor_wifi_logger_start_policy
4270[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4271 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4272 = {.type = NLA_U32 },
4273 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4274 = {.type = NLA_U32 },
4275 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4276 = {.type = NLA_U32 },
4277};
4278
4279/**
4280 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4281 * or disable the collection of packet statistics from the firmware
4282 * @wiphy: WIPHY structure pointer
4283 * @wdev: Wireless device structure pointer
4284 * @data: Pointer to the data received
4285 * @data_len: Length of the data received
4286 *
4287 * This function enables or disables the collection of packet statistics from
4288 * the firmware
4289 *
4290 * Return: 0 on success and errno on failure
4291 */
4292static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4293 struct wireless_dev *wdev,
4294 const void *data,
4295 int data_len)
4296{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304297 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004298 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4299 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4300 struct sir_wifi_start_log start_log;
4301
Jeff Johnson1f61b612016-02-12 16:28:33 -08004302 ENTER_DEV(wdev->netdev);
4303
Anurag Chouhan6d760662016-02-20 16:05:43 +05304304 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004305 hdd_err("Command not allowed in FTM mode");
4306 return -EPERM;
4307 }
4308
4309 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304310 if (status)
4311 return status;
4312
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313
4314 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4315 data, data_len,
4316 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004317 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004318 return -EINVAL;
4319 }
4320
4321 /* Parse and fetch ring id */
4322 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004323 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004324 return -EINVAL;
4325 }
4326 start_log.ring_id = nla_get_u32(
4327 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004328 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004329
4330 /* Parse and fetch verbose level */
4331 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004332 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004333 return -EINVAL;
4334 }
4335 start_log.verbose_level = nla_get_u32(
4336 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004337 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004338
4339 /* Parse and fetch flag */
4340 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004341 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004342 return -EINVAL;
4343 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304344 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304346 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004347
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304348 /* size is buff size which can be set using iwpriv command*/
4349 start_log.size = 0;
4350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004351 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4352
4353 if (start_log.ring_id == RING_ID_WAKELOCK) {
4354 /* Start/stop wakelock events */
4355 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4356 cds_set_wakelock_logging(true);
4357 else
4358 cds_set_wakelock_logging(false);
4359 return 0;
4360 }
4361
4362 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304363 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004364 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004365 status);
4366 return -EINVAL;
4367 }
4368 return 0;
4369}
4370
4371/**
4372 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4373 * or disable the collection of packet statistics from the firmware
4374 * @wiphy: WIPHY structure pointer
4375 * @wdev: Wireless device structure pointer
4376 * @data: Pointer to the data received
4377 * @data_len: Length of the data received
4378 *
4379 * This function is used to enable or disable the collection of packet
4380 * statistics from the firmware
4381 *
4382 * Return: 0 on success and errno on failure
4383 */
4384static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4385 struct wireless_dev *wdev,
4386 const void *data,
4387 int data_len)
4388{
4389 int ret = 0;
4390
4391 cds_ssr_protect(__func__);
4392 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4393 wdev, data, data_len);
4394 cds_ssr_unprotect(__func__);
4395
4396 return ret;
4397}
4398
4399static const struct
4400nla_policy
4401qca_wlan_vendor_wifi_logger_get_ring_data_policy
4402[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4403 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4404 = {.type = NLA_U32 },
4405};
4406
4407/**
4408 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4409 * @wiphy: WIPHY structure pointer
4410 * @wdev: Wireless device structure pointer
4411 * @data: Pointer to the data received
4412 * @data_len: Length of the data received
4413 *
4414 * This function is used to flush or retrieve the per packet statistics from
4415 * the driver
4416 *
4417 * Return: 0 on success and errno on failure
4418 */
4419static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4420 struct wireless_dev *wdev,
4421 const void *data,
4422 int data_len)
4423{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304424 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004425 uint32_t ring_id;
4426 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4427 struct nlattr *tb
4428 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4429
Jeff Johnson1f61b612016-02-12 16:28:33 -08004430 ENTER_DEV(wdev->netdev);
4431
Anurag Chouhan6d760662016-02-20 16:05:43 +05304432 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004433 hdd_err("Command not allowed in FTM mode");
4434 return -EPERM;
4435 }
4436
4437 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304438 if (status)
4439 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004440
4441 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4442 data, data_len,
4443 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004444 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004445 return -EINVAL;
4446 }
4447
4448 /* Parse and fetch ring id */
4449 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004450 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004451 return -EINVAL;
4452 }
4453
4454 ring_id = nla_get_u32(
4455 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4456
4457 if (ring_id == RING_ID_PER_PACKET_STATS) {
4458 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004459 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304460 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4461 /*
4462 * As part of DRIVER ring ID, flush both driver and fw logs.
4463 * For other Ring ID's driver doesn't have any rings to flush
4464 */
4465 hdd_notice("Bug report triggered by framework");
4466
4467 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4468 WLAN_LOG_INDICATOR_FRAMEWORK,
4469 WLAN_LOG_REASON_CODE_UNUSED,
4470 true, false);
4471 if (QDF_STATUS_SUCCESS != status) {
4472 hdd_err("Failed to trigger bug report");
4473 return -EINVAL;
4474 }
4475 } else {
4476 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4477 WLAN_LOG_INDICATOR_FRAMEWORK,
4478 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004479 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004480 return 0;
4481}
4482
4483/**
4484 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4485 * @wiphy: WIPHY structure pointer
4486 * @wdev: Wireless device structure pointer
4487 * @data: Pointer to the data received
4488 * @data_len: Length of the data received
4489 *
4490 * This function is used to flush or retrieve the per packet statistics from
4491 * the driver
4492 *
4493 * Return: 0 on success and errno on failure
4494 */
4495static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4496 struct wireless_dev *wdev,
4497 const void *data,
4498 int data_len)
4499{
4500 int ret = 0;
4501
4502 cds_ssr_protect(__func__);
4503 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4504 wdev, data, data_len);
4505 cds_ssr_unprotect(__func__);
4506
4507 return ret;
4508}
4509
4510#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4511/**
4512 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4513 * @hdd_ctx: HDD context
4514 * @request_id: [input] request id
4515 * @pattern_id: [output] pattern id
4516 *
4517 * This function loops through request id to pattern id array
4518 * if the slot is available, store the request id and return pattern id
4519 * if entry exists, return the pattern id
4520 *
4521 * Return: 0 on success and errno on failure
4522 */
4523static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4524 uint32_t request_id,
4525 uint8_t *pattern_id)
4526{
4527 uint32_t i;
4528
4529 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4530 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4531 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4532 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4533 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4534 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4535 return 0;
4536 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4537 request_id) {
4538 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4539 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4540 return 0;
4541 }
4542 }
4543 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4544 return -EINVAL;
4545}
4546
4547/**
4548 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4549 * @hdd_ctx: HDD context
4550 * @request_id: [input] request id
4551 * @pattern_id: [output] pattern id
4552 *
4553 * This function loops through request id to pattern id array
4554 * reset request id to 0 (slot available again) and
4555 * return pattern id
4556 *
4557 * Return: 0 on success and errno on failure
4558 */
4559static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4560 uint32_t request_id,
4561 uint8_t *pattern_id)
4562{
4563 uint32_t i;
4564
4565 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4566 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4567 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4568 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4569 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4570 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4571 return 0;
4572 }
4573 }
4574 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4575 return -EINVAL;
4576}
4577
4578
4579/*
4580 * define short names for the global vendor params
4581 * used by __wlan_hdd_cfg80211_offloaded_packets()
4582 */
4583#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4584#define PARAM_REQUEST_ID \
4585 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4586#define PARAM_CONTROL \
4587 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4588#define PARAM_IP_PACKET \
4589 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4590#define PARAM_SRC_MAC_ADDR \
4591 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4592#define PARAM_DST_MAC_ADDR \
4593 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4594#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4595
4596/**
4597 * wlan_hdd_add_tx_ptrn() - add tx pattern
4598 * @adapter: adapter pointer
4599 * @hdd_ctx: hdd context
4600 * @tb: nl attributes
4601 *
4602 * This function reads the NL attributes and forms a AddTxPtrn message
4603 * posts it to SME.
4604 *
4605 */
4606static int
4607wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4608 struct nlattr **tb)
4609{
4610 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304611 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004612 uint32_t request_id, ret, len;
4613 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304614 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004615 uint16_t eth_type = htons(ETH_P_IP);
4616
4617 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004618 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004619 return -ENOTSUPP;
4620 }
4621
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304622 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004623 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004624 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004625 return -ENOMEM;
4626 }
4627
4628 /* Parse and fetch request Id */
4629 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004630 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004631 goto fail;
4632 }
4633
4634 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4635 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004636 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004637 return -EINVAL;
4638 }
Jeff Johnson77848112016-06-29 14:52:06 -07004639 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004640
4641 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004642 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004643 goto fail;
4644 }
4645 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004646 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004647 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004648 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004649 goto fail;
4650 }
4651
4652 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004653 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004654 goto fail;
4655 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004656 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304657 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004658 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004659 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004660
Anurag Chouhanc5548422016-02-24 18:33:27 +05304661 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004662 &adapter->macAddressCurrent)) {
4663 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004664 goto fail;
4665 }
4666
4667 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004668 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004669 goto fail;
4670 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304671 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004672 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004673 MAC_ADDR_ARRAY(dst_addr.bytes));
4674
4675 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004676 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004677 goto fail;
4678 }
4679 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004680 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681
4682 if (add_req->ucPtrnSize < 0 ||
4683 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4684 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004685 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004686 add_req->ucPtrnSize);
4687 goto fail;
4688 }
4689
4690 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304691 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304692 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304693 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304694 QDF_MAC_ADDR_SIZE);
4695 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304696 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697 len += 2;
4698
4699 /*
4700 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4701 * ------------------------------------------------------------
4702 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4703 * ------------------------------------------------------------
4704 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304705 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004706 nla_data(tb[PARAM_IP_PACKET]),
4707 add_req->ucPtrnSize);
4708 add_req->ucPtrnSize += len;
4709
4710 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4711 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004712 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004713 goto fail;
4714 }
4715 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004716 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004717
4718 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304719 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004720 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004721 goto fail;
4722 }
4723
4724 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304725 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004726 return 0;
4727
4728fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304729 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004730 return -EINVAL;
4731}
4732
4733/**
4734 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4735 * @adapter: adapter pointer
4736 * @hdd_ctx: hdd context
4737 * @tb: nl attributes
4738 *
4739 * This function reads the NL attributes and forms a DelTxPtrn message
4740 * posts it to SME.
4741 *
4742 */
4743static int
4744wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4745 struct nlattr **tb)
4746{
4747 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304748 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004749 uint32_t request_id, ret;
4750 uint8_t pattern_id = 0;
4751
4752 /* Parse and fetch request Id */
4753 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004754 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004755 return -EINVAL;
4756 }
4757 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4758 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004759 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004760 return -EINVAL;
4761 }
4762
4763 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4764 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004765 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004766 return -EINVAL;
4767 }
4768
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304769 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004770 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004771 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004772 return -ENOMEM;
4773 }
4774
Anurag Chouhanc5548422016-02-24 18:33:27 +05304775 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004776 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004777 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004778 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004779 request_id, del_req->ucPtrnId);
4780
4781 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304782 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004783 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004784 goto fail;
4785 }
4786
4787 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304788 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004789 return 0;
4790
4791fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304792 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004793 return -EINVAL;
4794}
4795
4796
4797/**
4798 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4799 * @wiphy: Pointer to wireless phy
4800 * @wdev: Pointer to wireless device
4801 * @data: Pointer to data
4802 * @data_len: Data length
4803 *
4804 * Return: 0 on success, negative errno on failure
4805 */
4806static int
4807__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4808 struct wireless_dev *wdev,
4809 const void *data,
4810 int data_len)
4811{
4812 struct net_device *dev = wdev->netdev;
4813 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4814 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4815 struct nlattr *tb[PARAM_MAX + 1];
4816 uint8_t control;
4817 int ret;
4818 static const struct nla_policy policy[PARAM_MAX + 1] = {
4819 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4820 [PARAM_CONTROL] = { .type = NLA_U32 },
4821 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304822 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004823 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304824 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004825 [PARAM_PERIOD] = { .type = NLA_U32 },
4826 };
4827
Jeff Johnson1f61b612016-02-12 16:28:33 -08004828 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004829
Anurag Chouhan6d760662016-02-20 16:05:43 +05304830 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004831 hdd_err("Command not allowed in FTM mode");
4832 return -EPERM;
4833 }
4834
4835 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304836 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004837 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004838
4839 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004840 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004841 return -ENOTSUPP;
4842 }
4843
4844 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004845 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004846 return -EINVAL;
4847 }
4848
4849 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004850 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004851 return -EINVAL;
4852 }
4853 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004854 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004855
4856 if (control == WLAN_START_OFFLOADED_PACKETS)
4857 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4858 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4859 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4860 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004861 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004862 return -EINVAL;
4863 }
4864}
4865
4866/*
4867 * done with short names for the global vendor params
4868 * used by __wlan_hdd_cfg80211_offloaded_packets()
4869 */
4870#undef PARAM_MAX
4871#undef PARAM_REQUEST_ID
4872#undef PARAM_CONTROL
4873#undef PARAM_IP_PACKET
4874#undef PARAM_SRC_MAC_ADDR
4875#undef PARAM_DST_MAC_ADDR
4876#undef PARAM_PERIOD
4877
4878/**
4879 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4880 * @wiphy: wiphy structure pointer
4881 * @wdev: Wireless device structure pointer
4882 * @data: Pointer to the data received
4883 * @data_len: Length of @data
4884 *
4885 * Return: 0 on success; errno on failure
4886 */
4887static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4888 struct wireless_dev *wdev,
4889 const void *data,
4890 int data_len)
4891{
4892 int ret = 0;
4893
4894 cds_ssr_protect(__func__);
4895 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4896 wdev, data, data_len);
4897 cds_ssr_unprotect(__func__);
4898
4899 return ret;
4900}
4901#endif
4902
4903/*
4904 * define short names for the global vendor params
4905 * used by __wlan_hdd_cfg80211_monitor_rssi()
4906 */
4907#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4908#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4909#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4910#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4911#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4912
4913/**
4914 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4915 * @wiphy: Pointer to wireless phy
4916 * @wdev: Pointer to wireless device
4917 * @data: Pointer to data
4918 * @data_len: Data length
4919 *
4920 * Return: 0 on success, negative errno on failure
4921 */
4922static int
4923__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4924 struct wireless_dev *wdev,
4925 const void *data,
4926 int data_len)
4927{
4928 struct net_device *dev = wdev->netdev;
4929 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4930 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4931 struct nlattr *tb[PARAM_MAX + 1];
4932 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304933 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004934 int ret;
4935 uint32_t control;
4936 static const struct nla_policy policy[PARAM_MAX + 1] = {
4937 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4938 [PARAM_CONTROL] = { .type = NLA_U32 },
4939 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4940 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4941 };
4942
Jeff Johnson1f61b612016-02-12 16:28:33 -08004943 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004944
4945 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304946 if (ret)
4947 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004948
4949 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004950 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004951 return -ENOTSUPP;
4952 }
4953
4954 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004955 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004956 return -EINVAL;
4957 }
4958
4959 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004960 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004961 return -EINVAL;
4962 }
4963
4964 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004965 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004966 return -EINVAL;
4967 }
4968
4969 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4970 req.session_id = adapter->sessionId;
4971 control = nla_get_u32(tb[PARAM_CONTROL]);
4972
4973 if (control == QCA_WLAN_RSSI_MONITORING_START) {
4974 req.control = true;
4975 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004976 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004977 return -EINVAL;
4978 }
4979
4980 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004981 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004982 return -EINVAL;
4983 }
4984
4985 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
4986 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
4987
4988 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004989 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004990 req.min_rssi, req.max_rssi);
4991 return -EINVAL;
4992 }
Jeff Johnson77848112016-06-29 14:52:06 -07004993 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004994 req.min_rssi, req.max_rssi);
4995
4996 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
4997 req.control = false;
4998 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004999 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005000 return -EINVAL;
5001 }
Jeff Johnson77848112016-06-29 14:52:06 -07005002 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005003 req.request_id, req.session_id, req.control);
5004
5005 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305006 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005007 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005008 return -EINVAL;
5009 }
5010
5011 return 0;
5012}
5013
5014/*
5015 * done with short names for the global vendor params
5016 * used by __wlan_hdd_cfg80211_monitor_rssi()
5017 */
5018#undef PARAM_MAX
5019#undef PARAM_CONTROL
5020#undef PARAM_REQUEST_ID
5021#undef PARAM_MAX_RSSI
5022#undef PARAM_MIN_RSSI
5023
5024/**
5025 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5026 * @wiphy: wiphy structure pointer
5027 * @wdev: Wireless device structure pointer
5028 * @data: Pointer to the data received
5029 * @data_len: Length of @data
5030 *
5031 * Return: 0 on success; errno on failure
5032 */
5033static int
5034wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5035 const void *data, int data_len)
5036{
5037 int ret;
5038
5039 cds_ssr_protect(__func__);
5040 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5041 cds_ssr_unprotect(__func__);
5042
5043 return ret;
5044}
5045
5046/**
5047 * hdd_rssi_threshold_breached() - rssi breached NL event
5048 * @hddctx: HDD context
5049 * @data: rssi breached event data
5050 *
5051 * This function reads the rssi breached event %data and fill in the skb with
5052 * NL attributes and send up the NL event.
5053 *
5054 * Return: none
5055 */
5056void hdd_rssi_threshold_breached(void *hddctx,
5057 struct rssi_breach_event *data)
5058{
5059 hdd_context_t *hdd_ctx = hddctx;
5060 struct sk_buff *skb;
5061
5062 ENTER();
5063
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305064 if (wlan_hdd_validate_context(hdd_ctx))
5065 return;
5066 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005067 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005068 return;
5069 }
5070
5071 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5072 NULL,
5073 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5074 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5075 GFP_KERNEL);
5076
5077 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005078 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005079 return;
5080 }
5081
Jeff Johnson77848112016-06-29 14:52:06 -07005082 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005083 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005084 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005085 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5086
5087 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5088 data->request_id) ||
5089 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5090 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5091 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5092 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005093 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005094 goto fail;
5095 }
5096
5097 cfg80211_vendor_event(skb, GFP_KERNEL);
5098 return;
5099
5100fail:
5101 kfree_skb(skb);
5102 return;
5103}
5104
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305105static const struct nla_policy
5106ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5107 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5108};
5109
5110/**
5111 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5112 * @wiphy: Pointer to wireless phy
5113 * @wdev: Pointer to wireless device
5114 * @data: Pointer to data
5115 * @data_len: Length of @data
5116 *
5117 * Return: 0 on success, negative errno on failure
5118 */
5119static int
5120__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5121 struct wireless_dev *wdev,
5122 const void *data, int data_len)
5123{
5124 int status;
5125 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5126 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005127 struct net_device *dev = wdev->netdev;
5128 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305129
5130 ENTER_DEV(wdev->netdev);
5131
5132 status = wlan_hdd_validate_context(pHddCtx);
5133 if (0 != status)
5134 return status;
5135 if (!pHddCtx->config->fhostNSOffload) {
5136 hdd_err("ND Offload not supported");
5137 return -EINVAL;
5138 }
5139
5140 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5141 (struct nlattr *)data,
5142 data_len, ns_offload_set_policy)) {
5143 hdd_err("nla_parse failed");
5144 return -EINVAL;
5145 }
5146
5147 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5148 hdd_err("ND Offload flag attribute not present");
5149 return -EINVAL;
5150 }
5151
5152 pHddCtx->ns_offload_enable =
5153 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5154
Dustin Brownd8279d22016-09-07 14:52:57 -07005155 /* update ns offload in case it is already enabled/disabled */
5156 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5157
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305158 return 0;
5159}
5160
5161/**
5162 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5163 * @wiphy: pointer to wireless wiphy structure.
5164 * @wdev: pointer to wireless_dev structure.
5165 * @data: Pointer to the data to be passed via vendor interface
5166 * @data_len:Length of the data to be passed
5167 *
5168 * Return: Return the Success or Failure code.
5169 */
5170static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5171 struct wireless_dev *wdev,
5172 const void *data, int data_len)
5173{
5174 int ret;
5175
5176 cds_ssr_protect(__func__);
5177 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5178 cds_ssr_unprotect(__func__);
5179
5180 return ret;
5181}
5182
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005183/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5184 * @wiphy: Pointer to wireless phy
5185 * @wdev: Pointer to wireless device
5186 * @data: Pointer to data
5187 * @data_len: Data length
5188 *
5189 * This function return the preferred frequency list generated by the policy
5190 * manager.
5191 *
5192 * Return: success or failure code
5193 */
5194static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5195 struct wireless_dev
5196 *wdev, const void *data,
5197 int data_len)
5198{
5199 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5200 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305201 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305202 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005203 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305204 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005205 enum cds_con_mode intf_mode;
5206 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5207 struct sk_buff *reply_skb;
5208
Jeff Johnson1f61b612016-02-12 16:28:33 -08005209 ENTER_DEV(wdev->netdev);
5210
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005211 ret = wlan_hdd_validate_context(hdd_ctx);
5212 if (ret)
5213 return -EINVAL;
5214
5215 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5216 data, data_len, NULL)) {
5217 hdd_err("Invalid ATTR");
5218 return -EINVAL;
5219 }
5220
5221 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5222 hdd_err("attr interface type failed");
5223 return -EINVAL;
5224 }
5225
5226 intf_mode = nla_get_u32(tb
5227 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5228
5229 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5230 hdd_err("Invalid interface type");
5231 return -EINVAL;
5232 }
5233
5234 hdd_debug("Userspace requested pref freq list");
5235
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305236 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5237 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305238 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239 hdd_err("Get pcl failed");
5240 return -EINVAL;
5241 }
5242
5243 /* convert channel number to frequency */
5244 for (i = 0; i < pcl_len; i++) {
5245 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5246 freq_list[i] =
5247 ieee80211_channel_to_frequency(pcl[i],
5248 IEEE80211_BAND_2GHZ);
5249 else
5250 freq_list[i] =
5251 ieee80211_channel_to_frequency(pcl[i],
5252 IEEE80211_BAND_5GHZ);
5253 }
5254
5255 /* send the freq_list back to supplicant */
5256 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5257 sizeof(u32) *
5258 pcl_len +
5259 NLMSG_HDRLEN);
5260
5261 if (!reply_skb) {
5262 hdd_err("Allocate reply_skb failed");
5263 return -EINVAL;
5264 }
5265
5266 if (nla_put_u32(reply_skb,
5267 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5268 intf_mode) ||
5269 nla_put(reply_skb,
5270 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5271 sizeof(uint32_t) * pcl_len,
5272 freq_list)) {
5273 hdd_err("nla put fail");
5274 kfree_skb(reply_skb);
5275 return -EINVAL;
5276 }
5277
5278 return cfg80211_vendor_cmd_reply(reply_skb);
5279}
5280
5281/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5282 * @wiphy: Pointer to wireless phy
5283 * @wdev: Pointer to wireless device
5284 * @data: Pointer to data
5285 * @data_len: Data length
5286 *
5287 * This function return the preferred frequency list generated by the policy
5288 * manager.
5289 *
5290 * Return: success or failure code
5291 */
5292static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5293 struct wireless_dev
5294 *wdev, const void *data,
5295 int data_len)
5296{
5297 int ret = 0;
5298
5299 cds_ssr_protect(__func__);
5300 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5301 data, data_len);
5302 cds_ssr_unprotect(__func__);
5303
5304 return ret;
5305}
5306
5307/**
5308 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5309 * @wiphy: Pointer to wireless phy
5310 * @wdev: Pointer to wireless device
5311 * @data: Pointer to data
5312 * @data_len: Data length
5313 *
5314 * Return: 0 on success, negative errno on failure
5315 */
5316static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5317 struct wireless_dev *wdev,
5318 const void *data,
5319 int data_len)
5320{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305321 struct net_device *ndev = wdev->netdev;
5322 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005323 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5324 int ret = 0;
5325 enum cds_con_mode intf_mode;
5326 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5327 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328
Jeff Johnson1f61b612016-02-12 16:28:33 -08005329 ENTER_DEV(ndev);
5330
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005331 ret = wlan_hdd_validate_context(hdd_ctx);
5332 if (ret)
5333 return ret;
5334
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005335 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5336 data, data_len, NULL)) {
5337 hdd_err("Invalid ATTR");
5338 return -EINVAL;
5339 }
5340
5341 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5342 hdd_err("attr interface type failed");
5343 return -EINVAL;
5344 }
5345
5346 intf_mode = nla_get_u32(tb
5347 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5348
5349 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5350 hdd_err("Invalid interface type");
5351 return -EINVAL;
5352 }
5353
5354 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5355 hdd_err("attr probable freq failed");
5356 return -EINVAL;
5357 }
5358
5359 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5360 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5361
5362 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005363 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364 channel_hint, HW_MODE_20_MHZ)) {
5365 hdd_err("Set channel hint failed due to concurrency check");
5366 return -EINVAL;
5367 }
5368
Krunal Soni09e55032016-06-07 10:06:55 -07005369 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5370 hdd_warn("Remain On Channel Pending");
5371
Krunal Soni3091bcc2016-06-23 12:28:21 -07005372 ret = qdf_reset_connection_update();
5373 if (!QDF_IS_STATUS_SUCCESS(ret))
5374 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005375
Krunal Soni3091bcc2016-06-23 12:28:21 -07005376 ret = cds_current_connections_update(adapter->sessionId,
5377 channel_hint,
5378 SIR_UPDATE_REASON_SET_OPER_CHAN);
5379 if (QDF_STATUS_E_FAILURE == ret) {
5380 /* return in the failure case */
5381 hdd_err("ERROR: connections update failed!!");
5382 return -EINVAL;
5383 }
5384
5385 if (QDF_STATUS_SUCCESS == ret) {
5386 /*
5387 * Success is the only case for which we expect hw mode
5388 * change to take place, hence we need to wait.
5389 * For any other return value it should be a pass
5390 * through
5391 */
5392 ret = qdf_wait_for_connection_update();
5393 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5394 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005395 return -EINVAL;
5396 }
5397
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005398 }
5399
5400 return 0;
5401}
5402
5403/**
5404 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5405 * @wiphy: Pointer to wireless phy
5406 * @wdev: Pointer to wireless device
5407 * @data: Pointer to data
5408 * @data_len: Data length
5409 *
5410 * Return: 0 on success, negative errno on failure
5411 */
5412static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5413 struct wireless_dev *wdev,
5414 const void *data,
5415 int data_len)
5416{
5417 int ret = 0;
5418
5419 cds_ssr_protect(__func__);
5420 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5421 data, data_len);
5422 cds_ssr_unprotect(__func__);
5423
5424 return ret;
5425}
5426
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305427static const struct
5428nla_policy
5429qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5430 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5431};
5432
5433/**
5434 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5435 * @wiphy: WIPHY structure pointer
5436 * @wdev: Wireless device structure pointer
5437 * @data: Pointer to the data received
5438 * @data_len: Length of the data received
5439 *
5440 * This function is used to get link properties like nss, rate flags and
5441 * operating frequency for the active connection with the given peer.
5442 *
5443 * Return: 0 on success and errno on failure
5444 */
5445static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5446 struct wireless_dev *wdev,
5447 const void *data,
5448 int data_len)
5449{
5450 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5451 struct net_device *dev = wdev->netdev;
5452 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5453 hdd_station_ctx_t *hdd_sta_ctx;
5454 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305455 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305456 uint32_t sta_id;
5457 struct sk_buff *reply_skb;
5458 uint32_t rate_flags = 0;
5459 uint8_t nss;
5460 uint8_t final_rate_flags = 0;
5461 uint32_t freq;
5462
Jeff Johnson1f61b612016-02-12 16:28:33 -08005463 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305464
Anurag Chouhan6d760662016-02-20 16:05:43 +05305465 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305466 hdd_err("Command not allowed in FTM mode");
5467 return -EPERM;
5468 }
5469
5470 if (0 != wlan_hdd_validate_context(hdd_ctx))
5471 return -EINVAL;
5472
5473 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5474 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005475 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305476 return -EINVAL;
5477 }
5478
5479 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005480 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305481 adapter->device_mode);
5482 return -EINVAL;
5483 }
5484
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305485 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305486 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005487 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305488 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5489
Krunal Sonib4326f22016-03-10 13:05:51 -08005490 if (adapter->device_mode == QDF_STA_MODE ||
5491 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305492 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5493 if ((hdd_sta_ctx->conn_info.connState !=
5494 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305495 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305496 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005497 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305498 MAC_ADDR_ARRAY(peer_mac));
5499 return -EINVAL;
5500 }
5501
5502 nss = hdd_sta_ctx->conn_info.nss;
5503 freq = cds_chan_to_freq(
5504 hdd_sta_ctx->conn_info.operationChannel);
5505 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005506 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5507 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305508
5509 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5510 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305511 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305512 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305513 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305514 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305515 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305516 break;
5517 }
5518
5519 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005520 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305521 MAC_ADDR_ARRAY(peer_mac));
5522 return -EINVAL;
5523 }
5524
5525 nss = adapter->aStaInfo[sta_id].nss;
5526 freq = cds_chan_to_freq(
5527 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5528 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5529 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005530 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305531 MAC_ADDR_ARRAY(peer_mac));
5532 return -EINVAL;
5533 }
5534
5535 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5536 if (rate_flags & eHAL_TX_RATE_VHT80) {
5537 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005538#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305539 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005540#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305541 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5542 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005543#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305544 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005545#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305546 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5547 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5548 } else if (rate_flags &
5549 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5550 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005551#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305552 if (rate_flags & eHAL_TX_RATE_HT40)
5553 final_rate_flags |=
5554 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005555#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305556 }
5557
5558 if (rate_flags & eHAL_TX_RATE_SGI) {
5559 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5560 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5561 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5562 }
5563 }
5564
5565 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5566 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5567
5568 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005569 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305570 return -EINVAL;
5571 }
5572
5573 if (nla_put_u8(reply_skb,
5574 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5575 nss) ||
5576 nla_put_u8(reply_skb,
5577 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5578 final_rate_flags) ||
5579 nla_put_u32(reply_skb,
5580 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5581 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005582 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305583 kfree_skb(reply_skb);
5584 return -EINVAL;
5585 }
5586
5587 return cfg80211_vendor_cmd_reply(reply_skb);
5588}
5589
5590/**
5591 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5592 * properties.
5593 * @wiphy: WIPHY structure pointer
5594 * @wdev: Wireless device structure pointer
5595 * @data: Pointer to the data received
5596 * @data_len: Length of the data received
5597 *
5598 * This function is used to get link properties like nss, rate flags and
5599 * operating frequency for the active connection with the given peer.
5600 *
5601 * Return: 0 on success and errno on failure
5602 */
5603static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5604 struct wireless_dev *wdev,
5605 const void *data,
5606 int data_len)
5607{
5608 int ret = 0;
5609
5610 cds_ssr_protect(__func__);
5611 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5612 wdev, data, data_len);
5613 cds_ssr_unprotect(__func__);
5614
5615 return ret;
5616}
5617
Peng Xu278d0122015-09-24 16:34:17 -07005618static const struct
5619nla_policy
5620qca_wlan_vendor_ota_test_policy
5621[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5622 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5623};
5624
5625/**
5626 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5627 * @wiphy: Pointer to wireless phy
5628 * @wdev: Pointer to wireless device
5629 * @data: Pointer to data
5630 * @data_len: Data length
5631 *
5632 * Return: 0 on success, negative errno on failure
5633 */
5634static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5635 struct wireless_dev *wdev,
5636 const void *data,
5637 int data_len)
5638{
5639 struct net_device *dev = wdev->netdev;
5640 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5641 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5642 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5643 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5644 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305645 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005646 uint32_t current_roam_state;
5647
Jeff Johnson1f61b612016-02-12 16:28:33 -08005648 ENTER_DEV(dev);
5649
Anurag Chouhan6d760662016-02-20 16:05:43 +05305650 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005651 hdd_err("Command not allowed in FTM mode");
5652 return -EPERM;
5653 }
5654
5655 if (0 != wlan_hdd_validate_context(hdd_ctx))
5656 return -EINVAL;
5657
5658 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5659 data, data_len,
5660 qca_wlan_vendor_ota_test_policy)) {
5661 hdd_err("invalid attr");
5662 return -EINVAL;
5663 }
5664
5665 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5666 hdd_err("attr ota test failed");
5667 return -EINVAL;
5668 }
5669
5670 ota_enable = nla_get_u8(
5671 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5672
5673 hdd_info(" OTA test enable = %d", ota_enable);
5674 if (ota_enable != 1) {
5675 hdd_err("Invalid value, only enable test mode is supported!");
5676 return -EINVAL;
5677 }
5678
5679 current_roam_state =
5680 sme_get_current_roam_state(hal, adapter->sessionId);
5681 status = sme_stop_roaming(hal, adapter->sessionId,
5682 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305683 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005684 hdd_err("Enable/Disable roaming failed");
5685 return -EINVAL;
5686 }
5687
5688 status = sme_ps_enable_disable(hal, adapter->sessionId,
5689 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305690 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005691 hdd_err("Enable/Disable power save failed");
5692 /* restore previous roaming setting */
5693 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5694 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5695 status = sme_start_roaming(hal, adapter->sessionId,
5696 eCsrHddIssued);
5697 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5698 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5699 status = sme_stop_roaming(hal, adapter->sessionId,
5700 eCsrHddIssued);
5701
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305702 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005703 hdd_err("Restoring roaming state failed");
5704
5705 return -EINVAL;
5706 }
5707
5708
5709 return 0;
5710}
5711
5712/**
5713 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5714 * @wiphy: Pointer to wireless phy
5715 * @wdev: Pointer to wireless device
5716 * @data: Pointer to data
5717 * @data_len: Data length
5718 *
5719 * Return: 0 on success, negative errno on failure
5720 */
5721static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5722 struct wireless_dev *wdev,
5723 const void *data,
5724 int data_len)
5725{
5726 int ret = 0;
5727
5728 cds_ssr_protect(__func__);
5729 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5730 cds_ssr_unprotect(__func__);
5731
5732 return ret;
5733}
5734
Peng Xu4d67c8f2015-10-16 16:02:26 -07005735/**
5736 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5737 * @wiphy: Pointer to wireless phy
5738 * @wdev: Pointer to wireless device
5739 * @data: Pointer to data
5740 * @data_len: Data length
5741 *
5742 * Return: 0 on success, negative errno on failure
5743 */
5744static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5745 struct wireless_dev *wdev,
5746 const void *data,
5747 int data_len)
5748{
5749 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5750 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005751 hdd_adapter_t *adapter;
5752 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005753 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5754 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005755 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005756
Jeff Johnson1f61b612016-02-12 16:28:33 -08005757 ENTER_DEV(dev);
5758
Peng Xu4d67c8f2015-10-16 16:02:26 -07005759 ret = wlan_hdd_validate_context(hdd_ctx);
5760 if (ret)
5761 return ret;
5762
5763 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5764
5765 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5766 data, data_len, NULL)) {
5767 hdd_err("Invalid ATTR");
5768 return -EINVAL;
5769 }
5770
5771 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5772 hdd_err("attr tx power scale failed");
5773 return -EINVAL;
5774 }
5775
5776 scale_value = nla_get_u8(tb
5777 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5778
5779 if (scale_value > MAX_TXPOWER_SCALE) {
5780 hdd_err("Invalid tx power scale level");
5781 return -EINVAL;
5782 }
5783
Peng Xu62c8c432016-05-09 15:23:02 -07005784 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005785
Peng Xu62c8c432016-05-09 15:23:02 -07005786 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005787 hdd_err("Set tx power scale failed");
5788 return -EINVAL;
5789 }
5790
5791 return 0;
5792}
5793
5794/**
5795 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5796 * @wiphy: Pointer to wireless phy
5797 * @wdev: Pointer to wireless device
5798 * @data: Pointer to data
5799 * @data_len: Data length
5800 *
5801 * Return: 0 on success, negative errno on failure
5802 */
5803static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5804 struct wireless_dev *wdev,
5805 const void *data,
5806 int data_len)
5807{
Peng Xu62c8c432016-05-09 15:23:02 -07005808 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005809
5810 cds_ssr_protect(__func__);
5811 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5812 data, data_len);
5813 cds_ssr_unprotect(__func__);
5814
5815 return ret;
5816}
5817
5818/**
5819 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5820 * @wiphy: Pointer to wireless phy
5821 * @wdev: Pointer to wireless device
5822 * @data: Pointer to data
5823 * @data_len: Data length
5824 *
5825 * Return: 0 on success, negative errno on failure
5826 */
5827static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5828 struct wireless_dev *wdev,
5829 const void *data,
5830 int data_len)
5831{
5832 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5833 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005834 hdd_adapter_t *adapter;
5835 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005836 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5837 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005838 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005839
Jeff Johnson1f61b612016-02-12 16:28:33 -08005840 ENTER_DEV(dev);
5841
Peng Xu4d67c8f2015-10-16 16:02:26 -07005842 ret = wlan_hdd_validate_context(hdd_ctx);
5843 if (ret)
5844 return ret;
5845
5846 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5847
5848 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5849 data, data_len, NULL)) {
5850 hdd_err("Invalid ATTR");
5851 return -EINVAL;
5852 }
5853
5854 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5855 hdd_err("attr tx power decrease db value failed");
5856 return -EINVAL;
5857 }
5858
5859 scale_value = nla_get_u8(tb
5860 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5861
Peng Xu62c8c432016-05-09 15:23:02 -07005862 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5863 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005864
Peng Xu62c8c432016-05-09 15:23:02 -07005865 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005866 hdd_err("Set tx power decrease db failed");
5867 return -EINVAL;
5868 }
5869
5870 return 0;
5871}
5872
5873/**
5874 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5875 * @wiphy: Pointer to wireless phy
5876 * @wdev: Pointer to wireless device
5877 * @data: Pointer to data
5878 * @data_len: Data length
5879 *
5880 * Return: 0 on success, negative errno on failure
5881 */
5882static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5883 struct wireless_dev *wdev,
5884 const void *data,
5885 int data_len)
5886{
Peng Xu62c8c432016-05-09 15:23:02 -07005887 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005888
5889 cds_ssr_protect(__func__);
5890 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5891 data, data_len);
5892 cds_ssr_unprotect(__func__);
5893
5894 return ret;
5895}
Peng Xu8fdaa492016-06-22 10:20:47 -07005896
5897/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305898 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5899 * @wiphy: Pointer to wireless phy
5900 * @wdev: Pointer to wireless device
5901 * @data: Pointer to data
5902 * @data_len: Data length
5903 *
5904 * Processes the conditional channel switch request and invokes the helper
5905 * APIs to process the channel switch request.
5906 *
5907 * Return: 0 on success, negative errno on failure
5908 */
5909static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5910 struct wireless_dev *wdev,
5911 const void *data,
5912 int data_len)
5913{
5914 int ret;
5915 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5916 struct net_device *dev = wdev->netdev;
5917 hdd_adapter_t *adapter;
5918 struct nlattr
5919 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5920 uint32_t freq_len, i;
5921 uint32_t *freq;
5922 uint8_t chans[QDF_MAX_NUM_CHAN];
5923
5924 ENTER_DEV(dev);
5925
5926 ret = wlan_hdd_validate_context(hdd_ctx);
5927 if (ret)
5928 return ret;
5929
5930 if (!hdd_ctx->config->enableDFSMasterCap) {
5931 hdd_err("DFS master capability is not present in the driver");
5932 return -EINVAL;
5933 }
5934
5935 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5936 hdd_err("Command not allowed in FTM mode");
5937 return -EPERM;
5938 }
5939
5940 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5941 if (adapter->device_mode != QDF_SAP_MODE) {
5942 hdd_err("Invalid device mode %d", adapter->device_mode);
5943 return -EINVAL;
5944 }
5945
5946 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
5947 data, data_len, NULL)) {
5948 hdd_err("Invalid ATTR");
5949 return -EINVAL;
5950 }
5951
5952 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
5953 hdd_err("Frequency list is missing");
5954 return -EINVAL;
5955 }
5956
5957 freq_len = nla_len(
5958 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
5959 sizeof(uint32_t);
5960
5961 if (freq_len > QDF_MAX_NUM_CHAN) {
5962 hdd_err("insufficient space to hold channels");
5963 return -ENOMEM;
5964 }
5965
5966 hdd_debug("freq_len=%d", freq_len);
5967
5968 freq = nla_data(
5969 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
5970
5971
5972 for (i = 0; i < freq_len; i++) {
5973 if (freq[i] == 0)
5974 chans[i] = 0;
5975 else
5976 chans[i] = ieee80211_frequency_to_channel(freq[i]);
5977
5978 hdd_debug("freq[%d]=%d", i, freq[i]);
5979 }
5980
5981 /*
5982 * The input frequency list from user space is designed to be a
5983 * priority based frequency list. This is only to accommodate any
5984 * future request. But, current requirement is only to perform CAC
5985 * on a single channel. So, the first entry from the list is picked.
5986 *
5987 * If channel is zero, any channel in the available outdoor regulatory
5988 * domain will be selected.
5989 */
5990 ret = wlan_hdd_request_pre_cac(chans[0]);
5991 if (ret) {
5992 hdd_err("pre cac request failed with reason:%d", ret);
5993 return ret;
5994 }
5995
5996 return 0;
5997}
5998
5999/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006000 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6001 * @wiphy: Pointer to wireless phy
6002 * @wdev: Pointer to wireless device
6003 * @data: Pointer to data
6004 * @data_len: Data length
6005 *
6006 * This function is to process the p2p listen offload start vendor
6007 * command. It parses the input parameters and invoke WMA API to
6008 * send the command to firmware.
6009 *
6010 * Return: 0 on success, negative errno on failure
6011 */
6012static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6013 struct wireless_dev *wdev,
6014 const void *data,
6015 int data_len)
6016{
6017 int ret;
6018 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6019 struct net_device *dev = wdev->netdev;
6020 hdd_adapter_t *adapter;
6021 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6022 struct sir_p2p_lo_start params;
6023 QDF_STATUS status;
6024
6025 ENTER_DEV(dev);
6026
6027 ret = wlan_hdd_validate_context(hdd_ctx);
6028 if (ret)
6029 return ret;
6030
6031 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6032 hdd_err("Command not allowed in FTM mode");
6033 return -EPERM;
6034 }
6035
6036 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6037 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6038 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6039 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6040 hdd_err("Invalid device mode %d", adapter->device_mode);
6041 return -EINVAL;
6042 }
6043
6044 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6045 data, data_len, NULL)) {
6046 hdd_err("Invalid ATTR");
6047 return -EINVAL;
6048 }
6049
6050 memset(&params, 0, sizeof(params));
6051
6052 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6053 params.ctl_flags = 1; /* set to default value */
6054 else
6055 params.ctl_flags = nla_get_u32(tb
6056 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6057
6058 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6059 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6060 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6061 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6062 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6063 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6064 hdd_err("Attribute parsing failed");
6065 return -EINVAL;
6066 }
6067
6068 params.vdev_id = adapter->sessionId;
6069 params.freq = nla_get_u32(tb
6070 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6071 if ((params.freq != 2412) && (params.freq != 2437) &&
6072 (params.freq != 2462)) {
6073 hdd_err("Invalid listening channel: %d", params.freq);
6074 return -EINVAL;
6075 }
6076
6077 params.period = nla_get_u32(tb
6078 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6079 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6080 hdd_err("Invalid period: %d", params.period);
6081 return -EINVAL;
6082 }
6083
6084 params.interval = nla_get_u32(tb
6085 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6086 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6087 hdd_err("Invalid interval: %d", params.interval);
6088 return -EINVAL;
6089 }
6090
6091 params.count = nla_get_u32(tb
6092 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
6093 if (!((params.count > 0) && (params.count < UINT_MAX))) {
6094 hdd_err("Invalid count: %d", params.count);
6095 return -EINVAL;
6096 }
6097
6098 params.device_types = nla_data(tb
6099 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6100 if (params.device_types == NULL) {
6101 hdd_err("Invalid device types");
6102 return -EINVAL;
6103 }
6104
6105 params.dev_types_len = nla_len(tb
6106 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6107 if (params.dev_types_len < 8) {
6108 hdd_err("Invalid device type length: %d", params.dev_types_len);
6109 return -EINVAL;
6110 }
6111
6112 params.probe_resp_tmplt = nla_data(tb
6113 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6114 if (params.probe_resp_tmplt == NULL) {
6115 hdd_err("Invalid probe response template");
6116 return -EINVAL;
6117 }
6118
6119 params.probe_resp_len = nla_len(tb
6120 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6121 if (params.probe_resp_len == 0) {
6122 hdd_err("Invalid probe resp template length: %d",
6123 params.probe_resp_len);
6124 return -EINVAL;
6125 }
6126
6127 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6128 params.freq, params.period, params.interval, params.count);
6129
6130 status = wma_p2p_lo_start(&params);
6131
6132 if (!QDF_IS_STATUS_SUCCESS(status)) {
6133 hdd_err("P2P LO start failed");
6134 return -EINVAL;
6135 }
6136
6137 return 0;
6138}
6139
6140
6141/**
6142 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6143 * @wiphy: Pointer to wireless phy
6144 * @wdev: Pointer to wireless device
6145 * @data: Pointer to data
6146 * @data_len: Data length
6147 *
6148 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6149 * to process p2p listen offload start vendor command.
6150 *
6151 * Return: 0 on success, negative errno on failure
6152 */
6153static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6154 struct wireless_dev *wdev,
6155 const void *data,
6156 int data_len)
6157{
6158 int ret = 0;
6159
6160 cds_ssr_protect(__func__);
6161 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6162 data, data_len);
6163 cds_ssr_unprotect(__func__);
6164
6165 return ret;
6166}
6167
6168/**
6169 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6170 * @wiphy: Pointer to wireless phy
6171 * @wdev: Pointer to wireless device
6172 * @data: Pointer to data
6173 * @data_len: Data length
6174 *
6175 * This function is to process the p2p listen offload stop vendor
6176 * command. It invokes WMA API to send command to firmware.
6177 *
6178 * Return: 0 on success, negative errno on failure
6179 */
6180static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6181 struct wireless_dev *wdev,
6182 const void *data,
6183 int data_len)
6184{
6185 QDF_STATUS status;
6186 hdd_adapter_t *adapter;
6187 struct net_device *dev = wdev->netdev;
6188
6189 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6190 hdd_err("Command not allowed in FTM mode");
6191 return -EPERM;
6192 }
6193
6194 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6195 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6196 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6197 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6198 hdd_err("Invalid device mode");
6199 return -EINVAL;
6200 }
6201
6202 status = wma_p2p_lo_stop(adapter->sessionId);
6203
6204 if (!QDF_IS_STATUS_SUCCESS(status)) {
6205 hdd_err("P2P LO stop failed");
6206 return -EINVAL;
6207 }
6208
6209 return 0;
6210}
6211
6212/**
6213 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6214 * @wiphy: Pointer to wireless phy
6215 * @wdev: Pointer to wireless device
6216 * @data: Pointer to data
6217 * @data_len: Data length
6218 *
6219 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6220 * to process p2p listen offload stop vendor command.
6221 *
6222 * Return: 0 on success, negative errno on failure
6223 */
6224static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6225 struct wireless_dev *wdev,
6226 const void *data,
6227 int data_len)
6228{
6229 int ret = 0;
6230
6231 cds_ssr_protect(__func__);
6232 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6233 data, data_len);
6234 cds_ssr_unprotect(__func__);
6235
6236 return ret;
6237}
6238
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306239/**
6240 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6241 * @wiphy: Pointer to wireless phy
6242 * @wdev: Pointer to wireless device
6243 * @data: Pointer to data
6244 * @data_len: Data length
6245 *
6246 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6247 * to process the conditional channel switch request.
6248 *
6249 * Return: 0 on success, negative errno on failure
6250 */
6251static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6252 struct wireless_dev *wdev,
6253 const void *data,
6254 int data_len)
6255{
6256 int ret;
6257
6258 cds_ssr_protect(__func__);
6259 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6260 data, data_len);
6261 cds_ssr_unprotect(__func__);
6262
6263 return ret;
6264}
6265
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306266/*
6267 * define short names for the global vendor params
6268 * used by __wlan_hdd_cfg80211_bpf_offload()
6269 */
6270#define BPF_INVALID \
6271 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6272#define BPF_SET_RESET \
6273 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6274#define BPF_VERSION \
6275 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6276#define BPF_FILTER_ID \
6277 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6278#define BPF_PACKET_SIZE \
6279 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6280#define BPF_CURRENT_OFFSET \
6281 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6282#define BPF_PROGRAM \
6283 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6284#define BPF_MAX \
6285 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006286
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306287static const struct nla_policy
6288wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6289 [BPF_SET_RESET] = {.type = NLA_U32},
6290 [BPF_VERSION] = {.type = NLA_U32},
6291 [BPF_FILTER_ID] = {.type = NLA_U32},
6292 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6293 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6294 [BPF_PROGRAM] = {.type = NLA_U8},
6295};
6296
6297/**
6298 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6299 * @hdd_context: hdd_context
6300 * @bpf_get_offload: struct for get offload
6301 *
6302 * This function receives the response/data from the lower layer and
6303 * checks to see if the thread is still waiting then post the results to
6304 * upper layer, if the request has timed out then ignore.
6305 *
6306 * Return: None
6307 */
6308void hdd_get_bpf_offload_cb(void *hdd_context,
6309 struct sir_bpf_get_offload *data)
6310{
6311 hdd_context_t *hdd_ctx = hdd_context;
6312 struct hdd_bpf_context *context;
6313
6314 ENTER();
6315
6316 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006317 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306318 data);
6319 return;
6320 }
6321
6322 spin_lock(&hdd_context_lock);
6323
6324 context = &bpf_context;
6325 /* The caller presumably timed out so there is nothing we can do */
6326 if (context->magic != BPF_CONTEXT_MAGIC) {
6327 spin_unlock(&hdd_context_lock);
6328 return;
6329 }
6330
6331 /* context is valid so caller is still waiting */
6332 /* paranoia: invalidate the magic */
6333 context->magic = 0;
6334
6335 context->capability_response = *data;
6336 complete(&context->completion);
6337
6338 spin_unlock(&hdd_context_lock);
6339
6340 return;
6341}
6342
6343/**
6344 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6345 * @hdd_context: hdd_context
6346 * @bpf_get_offload: struct for get offload
6347 *
6348 * Return: 0 on success, error number otherwise.
6349 */
6350static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6351 struct sir_bpf_get_offload *bpf_get_offload)
6352{
6353 struct sk_buff *skb;
6354 uint32_t nl_buf_len;
6355
6356 ENTER();
6357
6358 nl_buf_len = NLMSG_HDRLEN;
6359 nl_buf_len +=
6360 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6361 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6362
6363 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6364 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006365 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306366 return -ENOMEM;
6367 }
6368
Jeff Johnson77848112016-06-29 14:52:06 -07006369 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306370 bpf_get_offload->bpf_version,
6371 bpf_get_offload->max_bytes_for_bpf_inst);
6372
6373 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6374 bpf_get_offload->max_bytes_for_bpf_inst) ||
6375 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006376 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306377 goto nla_put_failure;
6378 }
6379
6380 cfg80211_vendor_cmd_reply(skb);
6381 EXIT();
6382 return 0;
6383
6384nla_put_failure:
6385 kfree_skb(skb);
6386 return -EINVAL;
6387}
6388
6389/**
6390 * hdd_get_bpf_offload - Get BPF offload Capabilities
6391 * @hdd_ctx: Hdd context
6392 *
6393 * Return: 0 on success, errno on failure
6394 */
6395static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6396{
6397 unsigned long rc;
6398 struct hdd_bpf_context *context;
6399 QDF_STATUS status;
6400 int ret;
6401
6402 ENTER();
6403
6404 spin_lock(&hdd_context_lock);
6405 context = &bpf_context;
6406 context->magic = BPF_CONTEXT_MAGIC;
6407 INIT_COMPLETION(context->completion);
6408 spin_unlock(&hdd_context_lock);
6409
6410 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6411 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006412 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306413 return -EINVAL;
6414 }
6415 /* request was sent -- wait for the response */
6416 rc = wait_for_completion_timeout(&context->completion,
6417 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6418 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006419 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306420 spin_lock(&hdd_context_lock);
6421 context->magic = 0;
6422 spin_unlock(&hdd_context_lock);
6423
6424 return -ETIMEDOUT;
6425 }
6426 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6427 &bpf_context.capability_response);
6428 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006429 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306430
6431 EXIT();
6432 return ret;
6433}
6434
6435/**
6436 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6437 * @hdd_ctx: Hdd context
6438 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306439 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306440 *
6441 * Return: 0 on success; errno on failure
6442 */
6443static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6444 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306445 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306446{
6447 struct sir_bpf_set_offload *bpf_set_offload;
6448 QDF_STATUS status;
6449 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306450 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306451
6452 ENTER();
6453
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306454 if (adapter->device_mode == QDF_STA_MODE ||
6455 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6456 if (!hdd_conn_is_connected(
6457 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6458 hdd_err("Not in Connected state!");
6459 return -ENOTSUPP;
6460 }
6461 }
6462
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306463 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6464 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006465 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306466 return -ENOMEM;
6467 }
6468 qdf_mem_zero(bpf_set_offload, sizeof(*bpf_set_offload));
6469
6470 /* Parse and fetch bpf packet size */
6471 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006472 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306473 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306474 goto fail;
6475 }
6476 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6477
6478 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006479 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306480 goto post_sme;
6481 }
6482
6483 /* Parse and fetch bpf program */
6484 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006485 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306486 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306487 goto fail;
6488 }
6489
6490 prog_len = nla_len(tb[BPF_PROGRAM]);
6491 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306492
6493 if (bpf_set_offload->program == NULL) {
6494 hdd_err("qdf_mem_malloc failed for bpf offload program");
6495 ret = -ENOMEM;
6496 goto fail;
6497 }
6498
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306499 bpf_set_offload->current_length = prog_len;
6500 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306501 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306502
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306503 hdd_info("BPF set instructions");
6504 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6505 bpf_set_offload->program, prog_len);
6506
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306507 /* Parse and fetch filter Id */
6508 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006509 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306510 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306511 goto fail;
6512 }
6513 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6514
6515 /* Parse and fetch current offset */
6516 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006517 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306518 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306519 goto fail;
6520 }
6521 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6522
6523post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006524 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 +05306525 bpf_set_offload->session_id,
6526 bpf_set_offload->version,
6527 bpf_set_offload->filter_id,
6528 bpf_set_offload->total_length,
6529 bpf_set_offload->current_length,
6530 bpf_set_offload->current_offset);
6531
6532 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6533 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006534 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306535 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306536 goto fail;
6537 }
6538 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306539
6540fail:
6541 if (bpf_set_offload->current_length)
6542 qdf_mem_free(bpf_set_offload->program);
6543 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306544 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306545}
6546
6547/**
6548 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6549 * @wiphy: wiphy structure pointer
6550 * @wdev: Wireless device structure pointer
6551 * @data: Pointer to the data received
6552 * @data_len: Length of @data
6553 *
6554 * Return: 0 on success; errno on failure
6555 */
6556static int
6557__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6558 struct wireless_dev *wdev,
6559 const void *data, int data_len)
6560{
6561 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6562 struct net_device *dev = wdev->netdev;
6563 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6564 struct nlattr *tb[BPF_MAX + 1];
6565 int ret_val, packet_filter_subcmd;
6566
6567 ENTER();
6568
6569 ret_val = wlan_hdd_validate_context(hdd_ctx);
6570 if (ret_val)
6571 return ret_val;
6572
6573 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006574 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306575 return -EINVAL;
6576 }
6577
6578 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006579 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306580 return -ENOTSUPP;
6581 }
6582
6583 if (nla_parse(tb, BPF_MAX, data, data_len,
6584 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006585 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306586 return -EINVAL;
6587 }
6588
6589 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006590 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306591 return -EINVAL;
6592 }
6593
6594 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6595
6596 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6597 return hdd_get_bpf_offload(hdd_ctx);
6598 else
6599 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306600 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306601}
6602
6603/**
6604 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6605 * @wiphy: wiphy structure pointer
6606 * @wdev: Wireless device structure pointer
6607 * @data: Pointer to the data received
6608 * @data_len: Length of @data
6609 *
6610 * Return: 0 on success; errno on failure
6611 */
6612
6613static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6614 struct wireless_dev *wdev,
6615 const void *data, int data_len)
6616{
6617 int ret;
6618
6619 cds_ssr_protect(__func__);
6620 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6621 cds_ssr_unprotect(__func__);
6622
6623 return ret;
6624}
6625
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306626/**
6627 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6628 * @pre_cac_adapter: AP adapter used for pre cac
6629 * @status: Status (true or false)
6630 * @handle: Global handle
6631 *
6632 * Sets the status of pre cac i.e., whether the pre cac is active or not
6633 *
6634 * Return: Zero on success, non-zero on failure
6635 */
6636static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6637 bool status, tHalHandle handle)
6638{
6639 QDF_STATUS ret;
6640
6641 ret = wlan_sap_set_pre_cac_status(
6642 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6643 if (QDF_IS_STATUS_ERROR(ret))
6644 return -EINVAL;
6645
6646 return 0;
6647}
6648
6649/**
6650 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6651 * @ap_adapter: AP adapter
6652 * @chan_before_pre_cac: Channel
6653 *
6654 * Saves the channel which the AP was beaconing on before moving to the pre
6655 * cac channel. If radar is detected on the pre cac channel, this saved
6656 * channel will be used for AP operations.
6657 *
6658 * Return: Zero on success, non-zero on failure
6659 */
6660static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6661 uint8_t chan_before_pre_cac)
6662{
6663 QDF_STATUS ret;
6664
6665 ret = wlan_sap_set_chan_before_pre_cac(
6666 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6667 if (QDF_IS_STATUS_ERROR(ret))
6668 return -EINVAL;
6669
6670 return 0;
6671}
6672
6673/**
6674 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6675 * @ap_adapter: AP adapter
6676 * @nol: Non-occupancy list
6677 * @nol_len: Length of NOL
6678 *
6679 * Get the NOL for SAP
6680 *
6681 * Return: Zero on success, non-zero on failure
6682 */
6683static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6684 uint32_t *nol_len)
6685{
6686 QDF_STATUS ret;
6687
6688 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6689 nol, nol_len);
6690 if (QDF_IS_STATUS_ERROR(ret))
6691 return -EINVAL;
6692
6693 return 0;
6694}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306695
6696/**
6697 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6698 * @hdd_ctx: HDD context
6699 * @ap_adapter: AP adapter
6700 * @channel: Channel requested by userspace
6701 * @pre_cac_chan: Pointer to the pre CAC channel
6702 *
6703 * Validates the channel provided by userspace. If user provided channel 0,
6704 * a valid outdoor channel must be selected from the regulatory channel.
6705 *
6706 * Return: Zero on success and non zero value on error
6707 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006708static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6709 hdd_adapter_t *ap_adapter,
6710 uint8_t channel,
6711 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306712{
6713 uint32_t i, j;
6714 QDF_STATUS status;
6715 int ret;
6716 uint8_t nol[QDF_MAX_NUM_CHAN];
6717 uint32_t nol_len = 0, weight_len = 0;
6718 bool found;
6719 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6720 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6721 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6722
6723 if (0 == channel) {
6724 /* Channel is not obtained from PCL because PCL may not have
6725 * the entire channel list. For example: if SAP is up on
6726 * channel 6 and PCL is queried for the next SAP interface,
6727 * if SCC is preferred, the PCL will contain only the channel
6728 * 6. But, we are in need of a DFS channel. So, going with the
6729 * first channel from the valid channel list.
6730 */
6731 status = cds_get_valid_chans(channel_list, &len);
6732 if (QDF_IS_STATUS_ERROR(status)) {
6733 hdd_err("Failed to get channel list");
6734 return -EINVAL;
6735 }
6736 cds_update_with_safe_channel_list(channel_list, &len,
6737 pcl_weights, weight_len);
6738 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6739 for (i = 0; i < len; i++) {
6740 found = false;
6741 for (j = 0; j < nol_len; j++) {
6742 if (channel_list[i] == nol[j]) {
6743 found = true;
6744 break;
6745 }
6746 }
6747 if (found)
6748 continue;
6749 if (CDS_IS_DFS_CH(channel_list[i])) {
6750 *pre_cac_chan = channel_list[i];
6751 break;
6752 }
6753 }
6754 if (*pre_cac_chan == 0) {
6755 hdd_err("unable to find outdoor channel");
6756 return -EINVAL;
6757 }
6758 } else {
6759 /* Only when driver selects a channel, check is done for
6760 * unnsafe and NOL channels. When user provides a fixed channel
6761 * the user is expected to take care of this.
6762 */
6763 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6764 !CDS_IS_DFS_CH(channel)) {
6765 hdd_err("Invalid channel for pre cac:%d", channel);
6766 return -EINVAL;
6767 } else {
6768 *pre_cac_chan = channel;
6769 }
6770 }
6771 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6772 return 0;
6773}
6774
6775/**
6776 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6777 * @channel: Channel option provided by userspace
6778 *
6779 * Sets the driver to the required hardware mode and start an adapater for
6780 * pre CAC which will mimic an AP.
6781 *
6782 * Return: Zero on success, non-zero value on error
6783 */
6784int wlan_hdd_request_pre_cac(uint8_t channel)
6785{
6786 uint8_t pre_cac_chan = 0;
6787 hdd_context_t *hdd_ctx;
6788 int ret;
6789 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6790 hdd_ap_ctx_t *hdd_ap_ctx;
6791 QDF_STATUS status;
6792 struct wiphy *wiphy;
6793 struct net_device *dev;
6794 struct cfg80211_chan_def chandef;
6795 enum nl80211_channel_type channel_type;
6796 uint32_t freq;
6797 struct ieee80211_channel *chan;
6798 tHalHandle handle;
6799 bool val;
6800
6801 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6802 if (0 != wlan_hdd_validate_context(hdd_ctx))
6803 return -EINVAL;
6804
6805 if (cds_get_connection_count() > 1) {
6806 hdd_err("pre cac not allowed in concurrency");
6807 return -EINVAL;
6808 }
6809
6810 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6811 if (!ap_adapter) {
6812 hdd_err("unable to get SAP adapter");
6813 return -EINVAL;
6814 }
6815
6816 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6817 if (!handle) {
6818 hdd_err("Invalid handle");
6819 return -EINVAL;
6820 }
6821
6822 val = wlan_sap_is_pre_cac_active(handle);
6823 if (val) {
6824 hdd_err("pre cac is already in progress");
6825 return -EINVAL;
6826 }
6827
6828 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6829 if (!hdd_ap_ctx) {
6830 hdd_err("SAP context is NULL");
6831 return -EINVAL;
6832 }
6833
6834 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6835 hdd_err("SAP is already on DFS channel:%d",
6836 hdd_ap_ctx->operatingChannel);
6837 return -EINVAL;
6838 }
6839
6840 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6841 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6842 hdd_ap_ctx->operatingChannel);
6843 return -EINVAL;
6844 }
6845
6846 hdd_info("channel:%d", channel);
6847
6848 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6849 &pre_cac_chan);
6850 if (ret != 0)
6851 return ret;
6852
6853 /* Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
6854 * connection update should result in DBS mode
6855 */
6856 status = cds_update_and_wait_for_connection_update(
6857 ap_adapter->sessionId,
6858 pre_cac_chan,
6859 SIR_UPDATE_REASON_PRE_CAC);
6860 if (QDF_IS_STATUS_ERROR(status)) {
6861 hdd_err("error in moving to DBS mode");
6862 return -EINVAL;
6863 }
6864
6865 hdd_debug("starting pre cac SAP adapter");
6866
6867 /* Starting a SAP adapter:
6868 * Instead of opening an adapter, we could just do a SME open session
6869 * for AP type. But, start BSS would still need an adapter.
6870 * So, this option is not taken.
6871 *
6872 * hdd open adapter is going to register this precac interface with
6873 * user space. This interface though exposed to user space will be in
6874 * DOWN state. Consideration was done to avoid this registration to the
6875 * user space. But, as part of SAP operations multiple events are sent
6876 * to user space. Some of these events received from unregistered
6877 * interface was causing crashes. So, retaining the registration.
6878 *
6879 * So, this interface would remain registered and will remain in DOWN
6880 * state for the CAC duration. We will add notes in the feature
6881 * announcement to not use this temporary interface for any activity
6882 * from user space.
6883 */
6884 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
6885 wlan_hdd_get_intf_addr(hdd_ctx),
6886 NET_NAME_UNKNOWN, true);
6887 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306888 hdd_err("error opening the pre cac adapter");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306889 return -EINVAL;
6890 }
6891
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306892 /*
6893 * This interface is internally created by the driver. So, no interface
6894 * up comes for this interface from user space and hence starting
6895 * the adapter internally.
6896 */
6897 if (hdd_start_adapter(pre_cac_adapter)) {
6898 hdd_err("error starting the pre cac adapter");
6899 goto close_pre_cac_adapter;
6900 }
6901
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306902 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6903
6904 wiphy = hdd_ctx->wiphy;
6905 dev = pre_cac_adapter->dev;
6906
6907 /* Since this is only a dummy interface lets us use the IEs from the
6908 * other active SAP interface. In regular scenarios, these IEs would
6909 * come from the user space entity
6910 */
6911 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6912 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6913 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6914 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306915 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306916 }
6917 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6918 ap_adapter->sessionCtx.ap.beacon,
6919 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6920 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6921 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6922 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6923 ap_adapter->sessionCtx.ap.sapConfig.authType;
6924
6925 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6926 * to operate on the same bandwidth as that of the 2.4GHz operations.
6927 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6928 */
6929 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6930 case CH_WIDTH_20MHZ:
6931 channel_type = NL80211_CHAN_HT20;
6932 break;
6933 case CH_WIDTH_40MHZ:
6934 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6935 ap_adapter->sessionCtx.ap.sapConfig.channel)
6936 channel_type = NL80211_CHAN_HT40PLUS;
6937 else
6938 channel_type = NL80211_CHAN_HT40MINUS;
6939 break;
6940 default:
6941 channel_type = NL80211_CHAN_NO_HT;
6942 break;
6943 }
6944
6945 freq = cds_chan_to_freq(pre_cac_chan);
6946 chan = __ieee80211_get_channel(wiphy, freq);
6947 if (!chan) {
6948 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306949 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306950 }
6951
6952 cfg80211_chandef_create(&chandef, chan, channel_type);
6953
6954 hdd_debug("orig width:%d channel_type:%d freq:%d",
6955 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
6956 channel_type, freq);
6957
6958 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
6959 if (0 != ret) {
6960 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306961 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306962 }
6963
6964 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
6965 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
6966 eHIDDEN_SSID_NOT_IN_USE, false);
6967 if (QDF_IS_STATUS_ERROR(status)) {
6968 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306969 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306970 }
6971
6972 /*
6973 * The pre cac status is set here. But, it would not be reset explicitly
6974 * anywhere, since after the pre cac success/failure, the pre cac
6975 * adapter itself would be removed.
6976 */
6977 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
6978 if (0 != ret) {
6979 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306980 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306981 }
6982
6983 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
6984 hdd_ap_ctx->operatingChannel);
6985 if (0 != ret) {
6986 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306987 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306988 }
6989
6990 ap_adapter->pre_cac_chan = pre_cac_chan;
6991
6992 return 0;
6993
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306994stop_close_pre_cac_adapter:
6995 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306996 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
6997 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306998close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306999 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
7000 return -EINVAL;
7001}
7002
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307003/**
7004 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7005 *
7006 * Return: None
7007 */
7008void hdd_init_bpf_completion(void)
7009{
7010 init_completion(&bpf_context.completion);
7011}
7012
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307013static const struct nla_policy
7014wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7015 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7016};
7017
Agrawal Ashish65634612016-08-18 13:24:32 +05307018static const struct nla_policy
7019wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7020 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7021 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7022};
7023
7024/**
7025 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7026 * @wiphy: Pointer to wireless phy
7027 * @wdev: Pointer to wireless device
7028 * @data: Pointer to data
7029 * @data_len: Length of @data
7030 *
7031 * This function parses the incoming NL vendor command data attributes and
7032 * updates the SAP context about channel_hint and DFS mode.
7033 * If channel_hint is set, SAP will choose that channel
7034 * as operating channel.
7035 *
7036 * If DFS mode is enabled, driver will include DFS channels
7037 * in ACS else driver will skip DFS channels.
7038 *
7039 * Return: 0 on success, negative errno on failure
7040 */
7041static int
7042__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7043 struct wireless_dev *wdev,
7044 const void *data, int data_len)
7045{
7046 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7047 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7048 int ret;
7049 struct acs_dfs_policy *acs_policy;
7050 int mode = DFS_MODE_NONE;
7051 int channel_hint = 0;
7052
7053 ENTER_DEV(wdev->netdev);
7054
7055 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7056 hdd_err("Command not allowed in FTM mode");
7057 return -EINVAL;
7058 }
7059
7060 ret = wlan_hdd_validate_context(hdd_ctx);
7061 if (0 != ret)
7062 return ret;
7063
7064 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7065 data, data_len,
7066 wlan_hdd_set_acs_dfs_config_policy)) {
7067 hdd_err("invalid attr");
7068 return -EINVAL;
7069 }
7070
7071 acs_policy = &hdd_ctx->acs_policy;
7072 /*
7073 * SCM sends this attribute to restrict SAP from choosing
7074 * DFS channels from ACS.
7075 */
7076 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7077 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7078
7079 if (!IS_DFS_MODE_VALID(mode)) {
7080 hdd_err("attr acs dfs mode is not valid");
7081 return -EINVAL;
7082 }
7083 acs_policy->acs_dfs_mode = mode;
7084
7085 /*
7086 * SCM sends this attribute to provide an active channel,
7087 * to skip redundant ACS between drivers, and save driver start up time
7088 */
7089 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7090 channel_hint = nla_get_u8(
7091 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7092
7093 if (!IS_CHANNEL_VALID(channel_hint)) {
7094 hdd_err("acs channel is not valid");
7095 return -EINVAL;
7096 }
7097 acs_policy->acs_channel = channel_hint;
7098
7099 return 0;
7100}
7101
7102/**
7103 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7104 * @wiphy: wiphy structure pointer
7105 * @wdev: Wireless device structure pointer
7106 * @data: Pointer to the data received
7107 * @data_len: Length of @data
7108 *
7109 * This function parses the incoming NL vendor command data attributes and
7110 * updates the SAP context about channel_hint and DFS mode.
7111 *
7112 * Return: 0 on success; errno on failure
7113 */
7114static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7115 struct wireless_dev *wdev,
7116 const void *data, int data_len)
7117{
7118 int ret;
7119
7120 cds_ssr_protect(__func__);
7121 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7122 cds_ssr_unprotect(__func__);
7123
7124 return ret;
7125}
7126
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307127/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307128 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7129 * @mode : cfg80211 dfs mode
7130 *
7131 * Return: return csr sta roam dfs mode else return NONE
7132 */
7133static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7134 enum dfs_mode mode)
7135{
7136 switch (mode) {
7137 case DFS_MODE_ENABLE:
7138 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7139 break;
7140 case DFS_MODE_DISABLE:
7141 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7142 break;
7143 case DFS_MODE_DEPRIORITIZE:
7144 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7145 break;
7146 default:
7147 hdd_err("STA Roam policy dfs mode is NONE");
7148 return CSR_STA_ROAM_POLICY_NONE;
7149 }
7150}
7151
7152static const struct nla_policy
7153wlan_hdd_set_sta_roam_config_policy[
7154QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7155 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7156 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7157};
7158
7159/**
7160 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7161 * for station connection or roaming.
7162 * @wiphy: Pointer to wireless phy
7163 * @wdev: Pointer to wireless device
7164 * @data: Pointer to data
7165 * @data_len: Length of @data
7166 *
7167 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7168 * channels needs to be skipped in scanning or not.
7169 * If dfs_mode is disabled, driver will not scan DFS channels.
7170 * If skip_unsafe_channels is set, driver will skip unsafe channels
7171 * in Scanning.
7172 *
7173 * Return: 0 on success, negative errno on failure
7174 */
7175static int
7176__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7177 struct wireless_dev *wdev,
7178 const void *data, int data_len)
7179{
7180 struct net_device *dev = wdev->netdev;
7181 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7182 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7183 struct nlattr *tb[
7184 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7185 int ret;
7186 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7187 enum dfs_mode mode = DFS_MODE_NONE;
7188 bool skip_unsafe_channels = false;
7189 QDF_STATUS status;
7190
7191 ENTER_DEV(dev);
7192
7193 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7194 hdd_err("Command not allowed in FTM mode");
7195 return -EINVAL;
7196 }
7197
7198 ret = wlan_hdd_validate_context(hdd_ctx);
7199 if (0 != ret)
7200 return ret;
7201 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7202 data, data_len,
7203 wlan_hdd_set_sta_roam_config_policy)) {
7204 hdd_err("invalid attr");
7205 return -EINVAL;
7206 }
7207 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7208 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7209 if (!IS_DFS_MODE_VALID(mode)) {
7210 hdd_err("attr sta roam dfs mode policy is not valid");
7211 return -EINVAL;
7212 }
7213
7214 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7215
7216 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7217 skip_unsafe_channels = nla_get_u8(
7218 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7219
7220 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7221 skip_unsafe_channels, adapter->sessionId);
7222
7223 if (!QDF_IS_STATUS_SUCCESS(status)) {
7224 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7225 return -EINVAL;
7226 }
7227 return 0;
7228}
7229
7230/**
7231 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7232 * connection and roaming for station.
7233 * @wiphy: wiphy structure pointer
7234 * @wdev: Wireless device structure pointer
7235 * @data: Pointer to the data received
7236 * @data_len: Length of @data
7237 *
7238 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7239 * channels needs to be skipped in scanning or not.
7240 * If dfs_mode is disabled, driver will not scan DFS channels.
7241 * If skip_unsafe_channels is set, driver will skip unsafe channels
7242 * in Scanning.
7243 * Return: 0 on success; errno on failure
7244 */
7245static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7246 struct wireless_dev *wdev,
7247 const void *data, int data_len)
7248{
7249 int ret;
7250
7251 cds_ssr_protect(__func__);
7252 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7253 cds_ssr_unprotect(__func__);
7254
7255 return ret;
7256}
7257
Agrawal Ashish467dde42016-09-08 18:44:22 +05307258#ifdef FEATURE_WLAN_CH_AVOID
7259/**
7260 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7261 * is on unsafe channel.
7262 * @wiphy: wiphy structure pointer
7263 * @wdev: Wireless device structure pointer
7264 * @data: Pointer to the data received
7265 * @data_len: Length of @data
7266 *
7267 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7268 * on any of unsafe channels.
7269 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7270 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7271 *
7272 * Return: 0 on success; errno on failure
7273 */
7274static int
7275__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7276 struct wireless_dev *wdev,
7277 const void *data, int data_len)
7278{
7279 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7280 int ret;
7281 uint16_t unsafe_channel_count;
7282 int unsafe_channel_index;
7283 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7284
7285 ENTER_DEV(wdev->netdev);
7286
7287 if (!qdf_ctx) {
7288 cds_err("qdf_ctx is NULL");
7289 return -EINVAL;
7290 }
7291
7292 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7293 hdd_err("Command not allowed in FTM mode");
7294 return -EINVAL;
7295 }
7296
7297 ret = wlan_hdd_validate_context(hdd_ctx);
7298 if (0 != ret)
7299 return ret;
7300 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7301 &(hdd_ctx->unsafe_channel_count),
7302 sizeof(hdd_ctx->unsafe_channel_list));
7303
7304 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7305 (uint16_t)NUM_CHANNELS);
7306 for (unsafe_channel_index = 0;
7307 unsafe_channel_index < unsafe_channel_count;
7308 unsafe_channel_index++) {
7309 hdd_info("Channel %d is not safe",
7310 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7311 }
7312 hdd_unsafe_channel_restart_sap(hdd_ctx);
7313 return 0;
7314}
7315
7316/**
7317 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7318 * is on unsafe channel.
7319 * @wiphy: wiphy structure pointer
7320 * @wdev: Wireless device structure pointer
7321 * @data: Pointer to the data received
7322 * @data_len: Length of @data
7323 *
7324 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7325 * on any of unsafe channels.
7326 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7327 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7328 *
7329 * Return: 0 on success; errno on failure
7330 */
7331static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7332 struct wireless_dev *wdev,
7333 const void *data, int data_len)
7334{
7335 int ret;
7336
7337 cds_ssr_protect(__func__);
7338 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7339 cds_ssr_unprotect(__func__);
7340
7341 return ret;
7342}
7343
7344#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307345/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307346 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7347 * SAP is on unsafe channel.
7348 * @wiphy: wiphy structure pointer
7349 * @wdev: Wireless device structure pointer
7350 * @data: Pointer to the data received
7351 * @data_len: Length of @data
7352 *
7353 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7354 * driver.
7355 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7356 * will initiate restart of sap.
7357 *
7358 * Return: 0 on success; errno on failure
7359 */
7360static int
7361__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7362 struct wireless_dev *wdev,
7363 const void *data, int data_len)
7364{
7365 struct net_device *ndev = wdev->netdev;
7366 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7367 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7368 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7369 uint8_t config_channel = 0;
7370 hdd_ap_ctx_t *ap_ctx;
7371 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307372 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307373
7374 ENTER();
7375
7376 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007377 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307378 return -EINVAL;
7379 }
7380
7381 ret = wlan_hdd_validate_context(hdd_ctx);
7382 if (0 != ret)
7383 return -EINVAL;
7384
7385 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7386 data, data_len,
7387 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007388 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307389 return -EINVAL;
7390 }
7391
7392 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7393 if (!test_bit(SOFTAP_BSS_STARTED,
7394 &hostapd_adapter->event_flags)) {
7395 hdd_err("SAP is not started yet. Restart sap will be invalid");
7396 return -EINVAL;
7397 }
7398
7399 config_channel =
7400 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7401
7402 if (!((IS_24G_CH(config_channel)) ||
7403 (IS_5G_CH(config_channel)))) {
7404 hdd_err("Channel %d is not valid to restart SAP",
7405 config_channel);
7406 return -ENOTSUPP;
7407 }
7408
7409 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7410 ap_ctx->sapConfig.channel = config_channel;
7411 ap_ctx->sapConfig.ch_params.ch_width =
7412 ap_ctx->sapConfig.ch_width_orig;
7413
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007414 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307415 ap_ctx->sapConfig.sec_ch,
7416 &ap_ctx->sapConfig.ch_params);
7417
7418 cds_restart_sap(hostapd_adapter);
7419 }
7420
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307421 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7422 uint32_t freq_len, i;
7423 uint32_t *freq;
7424 uint8_t chans[QDF_MAX_NUM_CHAN];
7425
7426 hdd_debug("setting mandatory freq/chan list");
7427
7428 freq_len = nla_len(
7429 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7430 sizeof(uint32_t);
7431
7432 if (freq_len > QDF_MAX_NUM_CHAN) {
7433 hdd_err("insufficient space to hold channels");
7434 return -ENOMEM;
7435 }
7436
7437 freq = nla_data(
7438 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7439
7440 hdd_debug("freq_len=%d", freq_len);
7441
7442 for (i = 0; i < freq_len; i++) {
7443 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7444 hdd_debug("freq[%d]=%d", i, freq[i]);
7445 }
7446
7447 status = cds_set_sap_mandatory_channels(chans, freq_len);
7448 if (QDF_IS_STATUS_ERROR(status))
7449 return -EINVAL;
7450 }
7451
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307452 return 0;
7453}
7454
7455/**
7456 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7457 * @wiphy: wiphy structure pointer
7458 * @wdev: Wireless device structure pointer
7459 * @data: Pointer to the data received
7460 * @data_len: Length of @data
7461 *
7462 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7463 * driver.
7464 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7465 * will initiate restart of sap.
7466 *
7467 * Return: 0 on success; errno on failure
7468 */
7469static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7470 struct wireless_dev *wdev,
7471 const void *data, int data_len)
7472{
7473 int ret;
7474
7475 cds_ssr_protect(__func__);
7476 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7477 wdev, data, data_len);
7478 cds_ssr_unprotect(__func__);
7479
7480 return ret;
7481}
7482
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307483#undef BPF_INVALID
7484#undef BPF_SET_RESET
7485#undef BPF_VERSION
7486#undef BPF_ID
7487#undef BPF_PACKET_SIZE
7488#undef BPF_CURRENT_OFFSET
7489#undef BPF_PROGRAM
7490#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307491
7492/**
7493 * define short names for the global vendor params
7494 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7495 */
7496#define PARAM_TOTAL_CMD_EVENT_WAKE \
7497 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7498#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7499 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7500#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7501 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7502#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7503 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7504#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7505 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7506#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7507 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7508#define PARAM_TOTAL_RX_DATA_WAKE \
7509 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7510#define PARAM_RX_UNICAST_CNT \
7511 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7512#define PARAM_RX_MULTICAST_CNT \
7513 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7514#define PARAM_RX_BROADCAST_CNT \
7515 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7516#define PARAM_ICMP_PKT \
7517 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7518#define PARAM_ICMP6_PKT \
7519 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7520#define PARAM_ICMP6_RA \
7521 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7522#define PARAM_ICMP6_NA \
7523 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7524#define PARAM_ICMP6_NS \
7525 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7526#define PARAM_ICMP4_RX_MULTICAST_CNT \
7527 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7528#define PARAM_ICMP6_RX_MULTICAST_CNT \
7529 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7530#define PARAM_OTHER_RX_MULTICAST_CNT \
7531 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
7532
7533
7534/**
7535 * hdd_send_wakelock_stats() - API to send wakelock stats
7536 * @ctx: context to be passed to callback
7537 * @data: data passed to callback
7538 *
7539 * This function is used to send wake lock stats to HAL layer
7540 *
7541 * Return: 0 on success, error number otherwise.
7542 */
7543static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7544 const struct sir_wake_lock_stats *data)
7545{
7546 struct sk_buff *skb;
7547 uint32_t nl_buf_len;
7548 uint32_t total_rx_data_wake, rx_multicast_cnt;
7549 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307550 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307551
7552 ENTER();
7553
7554 nl_buf_len = NLMSG_HDRLEN;
7555 nl_buf_len +=
7556 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7557 (NLMSG_HDRLEN + sizeof(uint32_t));
7558
7559 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7560
7561 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007562 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307563 return -ENOMEM;
7564 }
7565
Jeff Johnson64943bd2016-08-23 13:14:06 -07007566 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307567 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007568 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307569 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007570 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307571 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007572 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307573 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007574 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307575 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007576 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307577 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007578 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307579 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007580 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7581 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307582 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307583
7584 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307585 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307586
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307587 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307588 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307589
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307590 rx_multicast_cnt =
7591 data->wow_ipv4_mcast_wake_up_count +
7592 ipv6_rx_multicast_addr_cnt;
7593
7594 total_rx_data_wake =
7595 data->wow_ucast_wake_up_count +
7596 data->wow_bcast_wake_up_count +
7597 rx_multicast_cnt;
7598
7599 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7600 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7601 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7602 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7603 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7604 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7605 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7606 total_rx_data_wake) ||
7607 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7608 data->wow_ucast_wake_up_count) ||
7609 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7610 rx_multicast_cnt) ||
7611 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7612 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307613 nla_put_u32(skb, PARAM_ICMP_PKT,
7614 data->wow_icmpv4_count) ||
7615 nla_put_u32(skb, PARAM_ICMP6_PKT,
7616 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307617 nla_put_u32(skb, PARAM_ICMP6_RA,
7618 data->wow_ipv6_mcast_ra_stats) ||
7619 nla_put_u32(skb, PARAM_ICMP6_NA,
7620 data->wow_ipv6_mcast_na_stats) ||
7621 nla_put_u32(skb, PARAM_ICMP6_NS,
7622 data->wow_ipv6_mcast_ns_stats) ||
7623 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7624 data->wow_ipv4_mcast_wake_up_count) ||
7625 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7626 ipv6_rx_multicast_addr_cnt) ||
7627 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007628 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307629 goto nla_put_failure;
7630 }
7631
7632 cfg80211_vendor_cmd_reply(skb);
7633
7634 EXIT();
7635 return 0;
7636
7637nla_put_failure:
7638 kfree_skb(skb);
7639 return -EINVAL;
7640}
7641
7642/**
7643 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7644 * @wiphy: wiphy pointer
7645 * @wdev: pointer to struct wireless_dev
7646 * @data: pointer to incoming NL vendor data
7647 * @data_len: length of @data
7648 *
7649 * This function parses the incoming NL vendor command data attributes and
7650 * invokes the SME Api and blocks on a completion variable.
7651 * WMA copies required data and invokes callback
7652 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7653 *
7654 * Return: 0 on success; error number otherwise.
7655 */
7656static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7657 struct wireless_dev *wdev,
7658 const void *data,
7659 int data_len)
7660{
7661 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7662 int status, ret;
7663 struct sir_wake_lock_stats wake_lock_stats;
7664 QDF_STATUS qdf_status;
7665
7666 ENTER();
7667
7668 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007669 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307670 return -EINVAL;
7671 }
7672
7673 status = wlan_hdd_validate_context(hdd_ctx);
7674 if (0 != status)
7675 return -EINVAL;
7676
7677 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7678 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007679 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307680 return -EINVAL;
7681 }
7682
7683 ret = hdd_send_wakelock_stats(hdd_ctx,
7684 &wake_lock_stats);
7685 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007686 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307687
7688 EXIT();
7689 return ret;
7690}
7691
7692/**
7693 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7694 * @wiphy: wiphy pointer
7695 * @wdev: pointer to struct wireless_dev
7696 * @data: pointer to incoming NL vendor data
7697 * @data_len: length of @data
7698 *
7699 * This function parses the incoming NL vendor command data attributes and
7700 * invokes the SME Api and blocks on a completion variable.
7701 * WMA copies required data and invokes callback
7702 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7703 *
7704 * Return: 0 on success; error number otherwise.
7705 */
7706static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7707 struct wireless_dev *wdev,
7708 const void *data, int data_len)
7709{
7710 int ret;
7711
7712 cds_ssr_protect(__func__);
7713 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7714 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007715 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307716
7717 return ret;
7718}
7719
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307720/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307721 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7722 * @wiphy: wiphy structure pointer
7723 * @wdev: Wireless device structure pointer
7724 * @data: Pointer to the data received
7725 * @data_len: Length of @data
7726 *
7727 * This function reads wmi max bus size and fill in the skb with
7728 * NL attributes and send up the NL event.
7729 * Return: 0 on success; errno on failure
7730 */
7731static int
7732__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7733 struct wireless_dev *wdev,
7734 const void *data, int data_len)
7735{
7736 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7737 int ret_val;
7738 struct sk_buff *skb;
7739 uint32_t nl_buf_len;
7740
7741 ENTER();
7742
7743 ret_val = wlan_hdd_validate_context(hdd_ctx);
7744 if (ret_val)
7745 return ret_val;
7746
7747 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7748 hdd_err("Command not allowed in FTM mode");
7749 return -EINVAL;
7750 }
7751
7752 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7753
7754 nl_buf_len = NLMSG_HDRLEN;
7755 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7756
7757 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7758 if (!skb) {
7759 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7760 return -ENOMEM;
7761 }
7762
7763 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7764 hdd_ctx->wmi_max_len)) {
7765 hdd_err("nla put failure");
7766 goto nla_put_failure;
7767 }
7768
7769 cfg80211_vendor_cmd_reply(skb);
7770
7771 EXIT();
7772
7773 return 0;
7774
7775nla_put_failure:
7776 kfree_skb(skb);
7777 return -EINVAL;
7778}
7779
7780/**
7781 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7782 * @wiphy: wiphy structure pointer
7783 * @wdev: Wireless device structure pointer
7784 * @data: Pointer to the data received
7785 * @data_len: Length of @data
7786 *
7787 * Return: 0 on success; errno on failure
7788 */
7789static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7790 struct wireless_dev *wdev,
7791 const void *data, int data_len)
7792{
7793 int ret;
7794
7795 cds_ssr_protect(__func__);
7796 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7797 cds_ssr_unprotect(__func__);
7798
7799 return ret;
7800}
7801
7802/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307803 *__wlan_hdd_cfg80211_setband() - set band
7804 * @wiphy: Pointer to wireless phy
7805 * @wdev: Pointer to wireless device
7806 * @data: Pointer to data
7807 * @data_len: Length of @data
7808 *
7809 * Return: 0 on success, negative errno on failure
7810 */
7811static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7812 struct wireless_dev *wdev,
7813 const void *data, int data_len)
7814{
7815 struct net_device *dev = wdev->netdev;
7816 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7817 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7818 int ret;
7819 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7820 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7821
7822 ENTER();
7823
7824 ret = wlan_hdd_validate_context(hdd_ctx);
7825 if (ret)
7826 return ret;
7827
7828 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7829 hdd_err(FL("Invalid ATTR"));
7830 return -EINVAL;
7831 }
7832
7833 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7834 hdd_err(FL("attr SETBAND_VALUE failed"));
7835 return -EINVAL;
7836 }
7837
7838 ret = hdd_set_band(dev,
7839 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7840
7841 EXIT();
7842 return ret;
7843}
7844
7845/**
7846 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7847 * @wiphy: wiphy structure pointer
7848 * @wdev: Wireless device structure pointer
7849 * @data: Pointer to the data received
7850 * @data_len: Length of @data
7851 *
7852 * Return: 0 on success; errno on failure
7853 */
7854static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7855 struct wireless_dev *wdev,
7856 const void *data, int data_len)
7857{
7858 int ret;
7859
7860 cds_ssr_protect(__func__);
7861 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7862 cds_ssr_unprotect(__func__);
7863
7864 return ret;
7865}
7866
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307867static const struct
7868nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7869 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7870 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7871 .len = QDF_MAC_ADDR_SIZE},
7872};
7873
7874/**
7875 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7876 * @wiphy: Pointer to wireless phy
7877 * @wdev: Pointer to wireless device
7878 * @data: Pointer to data
7879 * @data_len: Length of @data
7880 *
7881 * This function is used to enable/disable roaming using vendor commands
7882 *
7883 * Return: 0 on success, negative errno on failure
7884 */
7885static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7886 struct wireless_dev *wdev,
7887 const void *data, int data_len)
7888{
7889 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7890 struct net_device *dev = wdev->netdev;
7891 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7892 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7893 uint32_t is_fast_roam_enabled;
7894 int ret;
7895
7896 ENTER_DEV(dev);
7897
7898 ret = wlan_hdd_validate_context(hdd_ctx);
7899 if (0 != ret)
7900 return ret;
7901
7902 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7903 hdd_err("Command not allowed in FTM mode");
7904 return -EINVAL;
7905 }
7906
7907 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
7908 qca_wlan_vendor_attr);
7909 if (ret) {
7910 hdd_err("Invalid ATTR");
7911 return -EINVAL;
7912 }
7913
7914 /* Parse and fetch Enable flag */
7915 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
7916 hdd_err("attr enable failed");
7917 return -EINVAL;
7918 }
7919
7920 is_fast_roam_enabled = nla_get_u32(
7921 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
7922 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
7923
7924 /* Update roaming */
7925 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
7926 is_fast_roam_enabled);
7927 if (ret)
7928 hdd_err("sme_config_fast_roaming failed");
7929 EXIT();
7930 return ret;
7931}
7932
7933/**
7934 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7935 * @wiphy: Pointer to wireless phy
7936 * @wdev: Pointer to wireless device
7937 * @data: Pointer to data
7938 * @data_len: Length of @data
7939 *
7940 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
7941 *
7942 * Return: 0 on success, negative errno on failure
7943 */
7944static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7945 struct wireless_dev *wdev,
7946 const void *data, int data_len)
7947{
7948 int ret;
7949
7950 cds_ssr_protect(__func__);
7951 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
7952 cds_ssr_unprotect(__func__);
7953
7954 return ret;
7955}
7956
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007957const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
7958 {
7959 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7960 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
7961 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05307962 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007963 .doit = is_driver_dfs_capable
7964 },
7965
7966#ifdef WLAN_FEATURE_NAN
7967 {
7968 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7969 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
7970 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7971 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7972 .doit = wlan_hdd_cfg80211_nan_request
7973 },
7974#endif
7975
7976#ifdef WLAN_FEATURE_STATS_EXT
7977 {
7978 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7979 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
7980 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7981 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7982 .doit = wlan_hdd_cfg80211_stats_ext_request
7983 },
7984#endif
7985#ifdef FEATURE_WLAN_EXTSCAN
7986 {
7987 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7988 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
7989 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7990 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7991 .doit = wlan_hdd_cfg80211_extscan_start
7992 },
7993 {
7994 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7995 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
7996 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7997 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7998 .doit = wlan_hdd_cfg80211_extscan_stop
7999 },
8000 {
8001 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8002 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8003 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8004 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8005 },
8006 {
8007 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8008 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8009 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8010 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8011 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8012 },
8013 {
8014 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8015 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8016 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8017 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8018 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8019 },
8020 {
8021 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8022 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8023 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8024 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8025 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8026 },
8027 {
8028 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8029 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8030 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8031 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8032 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8033 },
8034 {
8035 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8036 .info.subcmd =
8037 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8038 .flags =
8039 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8040 WIPHY_VENDOR_CMD_NEED_RUNNING,
8041 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8042 },
8043 {
8044 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8045 .info.subcmd =
8046 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8047 .flags =
8048 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8049 WIPHY_VENDOR_CMD_NEED_RUNNING,
8050 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8051 },
8052 {
8053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8055 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8056 WIPHY_VENDOR_CMD_NEED_NETDEV |
8057 WIPHY_VENDOR_CMD_NEED_RUNNING,
8058 .doit = wlan_hdd_cfg80211_set_epno_list
8059 },
8060#endif /* FEATURE_WLAN_EXTSCAN */
8061
8062#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8063 {
8064 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8065 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8066 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8067 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8068 .doit = wlan_hdd_cfg80211_ll_stats_clear
8069 },
8070
8071 {
8072 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8073 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8074 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8075 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8076 .doit = wlan_hdd_cfg80211_ll_stats_set
8077 },
8078
8079 {
8080 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8081 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8082 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8083 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8084 .doit = wlan_hdd_cfg80211_ll_stats_get
8085 },
8086#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8087#ifdef FEATURE_WLAN_TDLS
8088 {
8089 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8090 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8091 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8092 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8093 .doit = wlan_hdd_cfg80211_exttdls_enable
8094 },
8095 {
8096 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8097 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8098 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8099 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8100 .doit = wlan_hdd_cfg80211_exttdls_disable
8101 },
8102 {
8103 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8104 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8105 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8106 .doit = wlan_hdd_cfg80211_exttdls_get_status
8107 },
8108#endif
8109 {
8110 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8111 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8112 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8113 .doit = wlan_hdd_cfg80211_get_supported_features
8114 },
8115 {
8116 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8117 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8118 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8119 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8120 },
8121 {
8122 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8123 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8124 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308125 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008126 },
8127 {
8128 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8129 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8130 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8131 WIPHY_VENDOR_CMD_NEED_NETDEV,
8132 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8133 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008134 {
8135 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8136 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8137 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8138 WIPHY_VENDOR_CMD_NEED_NETDEV,
8139 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8140 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008141 {
8142 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308143 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8144 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8145 WIPHY_VENDOR_CMD_NEED_NETDEV |
8146 WIPHY_VENDOR_CMD_NEED_RUNNING,
8147 .doit = hdd_cfg80211_get_station_cmd
8148 },
8149 {
8150 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008151 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8152 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8153 WIPHY_VENDOR_CMD_NEED_NETDEV |
8154 WIPHY_VENDOR_CMD_NEED_RUNNING,
8155 .doit = wlan_hdd_cfg80211_do_acs
8156 },
8157
8158 {
8159 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8160 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8161 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8162 WIPHY_VENDOR_CMD_NEED_NETDEV,
8163 .doit = wlan_hdd_cfg80211_get_features
8164 },
8165#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8166 {
8167 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8168 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8169 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8170 WIPHY_VENDOR_CMD_NEED_NETDEV |
8171 WIPHY_VENDOR_CMD_NEED_RUNNING,
8172 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8173 },
8174#endif
8175#ifdef FEATURE_WLAN_EXTSCAN
8176 {
8177 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8178 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8179 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8180 WIPHY_VENDOR_CMD_NEED_NETDEV |
8181 WIPHY_VENDOR_CMD_NEED_RUNNING,
8182 .doit = wlan_hdd_cfg80211_set_passpoint_list
8183 },
8184 {
8185 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8186 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8187 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8188 WIPHY_VENDOR_CMD_NEED_NETDEV |
8189 WIPHY_VENDOR_CMD_NEED_RUNNING,
8190 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8191 },
8192 {
8193 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8194 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8195 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8196 WIPHY_VENDOR_CMD_NEED_NETDEV |
8197 WIPHY_VENDOR_CMD_NEED_RUNNING,
8198 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8199 },
8200 {
8201 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8202 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8203 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8204 WIPHY_VENDOR_CMD_NEED_NETDEV |
8205 WIPHY_VENDOR_CMD_NEED_RUNNING,
8206 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8207 },
8208#endif /* FEATURE_WLAN_EXTSCAN */
8209 {
8210 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8211 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8212 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8213 WIPHY_VENDOR_CMD_NEED_NETDEV,
8214 .doit = wlan_hdd_cfg80211_get_wifi_info
8215 },
8216 {
8217 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8218 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8219 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8220 WIPHY_VENDOR_CMD_NEED_NETDEV |
8221 WIPHY_VENDOR_CMD_NEED_RUNNING,
8222 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8223 },
8224 {
8225 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8226 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8227 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8228 WIPHY_VENDOR_CMD_NEED_NETDEV,
8229 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8230 },
8231 {
8232 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8233 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8234 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8235 WIPHY_VENDOR_CMD_NEED_NETDEV,
8236 .doit = wlan_hdd_cfg80211_wifi_logger_start
8237 },
8238 {
8239 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8240 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8241 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8242 WIPHY_VENDOR_CMD_NEED_NETDEV,
8243 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8244 },
8245 {
8246 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8247 .info.subcmd =
8248 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8249 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8250 WIPHY_VENDOR_CMD_NEED_NETDEV |
8251 WIPHY_VENDOR_CMD_NEED_RUNNING,
8252 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8253 },
8254 {
8255 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8256 .info.subcmd =
8257 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8258 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8259 WIPHY_VENDOR_CMD_NEED_NETDEV |
8260 WIPHY_VENDOR_CMD_NEED_RUNNING,
8261 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8262 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008263#ifdef WLAN_FEATURE_TSF
8264 {
8265 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8266 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8267 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8268 WIPHY_VENDOR_CMD_NEED_NETDEV |
8269 WIPHY_VENDOR_CMD_NEED_RUNNING,
8270 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8271 },
8272#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008273#ifdef FEATURE_WLAN_TDLS
8274 {
8275 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8276 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8277 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8278 WIPHY_VENDOR_CMD_NEED_NETDEV |
8279 WIPHY_VENDOR_CMD_NEED_RUNNING,
8280 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8281 },
8282#endif
8283#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8284 {
8285 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8286 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8287 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8288 WIPHY_VENDOR_CMD_NEED_NETDEV |
8289 WIPHY_VENDOR_CMD_NEED_RUNNING,
8290 .doit = wlan_hdd_cfg80211_offloaded_packets
8291 },
8292#endif
8293 {
8294 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8295 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8296 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8297 WIPHY_VENDOR_CMD_NEED_NETDEV |
8298 WIPHY_VENDOR_CMD_NEED_RUNNING,
8299 .doit = wlan_hdd_cfg80211_monitor_rssi
8300 },
8301 {
8302 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308303 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8304 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8305 WIPHY_VENDOR_CMD_NEED_NETDEV |
8306 WIPHY_VENDOR_CMD_NEED_RUNNING,
8307 .doit = wlan_hdd_cfg80211_set_ns_offload
8308 },
8309 {
8310 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008311 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8312 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8313 WIPHY_VENDOR_CMD_NEED_NETDEV |
8314 WIPHY_VENDOR_CMD_NEED_RUNNING,
8315 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8316 },
8317#ifdef WLAN_FEATURE_MEMDUMP
8318 {
8319 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8320 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8321 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8322 WIPHY_VENDOR_CMD_NEED_NETDEV |
8323 WIPHY_VENDOR_CMD_NEED_RUNNING,
8324 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8325 },
8326#endif /* WLAN_FEATURE_MEMDUMP */
8327 {
8328 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8329 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8330 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8331 WIPHY_VENDOR_CMD_NEED_NETDEV |
8332 WIPHY_VENDOR_CMD_NEED_RUNNING,
8333 .doit = wlan_hdd_cfg80211_vendor_scan
8334 },
8335
8336 /* OCB commands */
8337 {
8338 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8339 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8340 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8341 WIPHY_VENDOR_CMD_NEED_NETDEV |
8342 WIPHY_VENDOR_CMD_NEED_RUNNING,
8343 .doit = wlan_hdd_cfg80211_ocb_set_config
8344 },
8345 {
8346 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8347 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8348 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8349 WIPHY_VENDOR_CMD_NEED_NETDEV |
8350 WIPHY_VENDOR_CMD_NEED_RUNNING,
8351 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8352 },
8353 {
8354 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8355 .info.subcmd =
8356 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8357 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8358 WIPHY_VENDOR_CMD_NEED_NETDEV |
8359 WIPHY_VENDOR_CMD_NEED_RUNNING,
8360 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8361 },
8362 {
8363 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8364 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8365 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8366 WIPHY_VENDOR_CMD_NEED_NETDEV |
8367 WIPHY_VENDOR_CMD_NEED_RUNNING,
8368 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8369 },
8370 {
8371 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8372 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8373 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8374 WIPHY_VENDOR_CMD_NEED_NETDEV |
8375 WIPHY_VENDOR_CMD_NEED_RUNNING,
8376 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8377 },
8378 {
8379 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8380 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8381 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8382 WIPHY_VENDOR_CMD_NEED_NETDEV |
8383 WIPHY_VENDOR_CMD_NEED_RUNNING,
8384 .doit = wlan_hdd_cfg80211_dcc_get_stats
8385 },
8386 {
8387 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8388 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8389 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8390 WIPHY_VENDOR_CMD_NEED_NETDEV |
8391 WIPHY_VENDOR_CMD_NEED_RUNNING,
8392 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8393 },
8394 {
8395 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8396 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8397 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8398 WIPHY_VENDOR_CMD_NEED_NETDEV |
8399 WIPHY_VENDOR_CMD_NEED_RUNNING,
8400 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8401 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308402 {
8403 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8404 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8405 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8406 WIPHY_VENDOR_CMD_NEED_NETDEV |
8407 WIPHY_VENDOR_CMD_NEED_RUNNING,
8408 .doit = wlan_hdd_cfg80211_get_link_properties
8409 },
Peng Xu278d0122015-09-24 16:34:17 -07008410 {
Peng Xud2220962016-07-11 17:59:17 -07008411 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008412 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8413 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8414 WIPHY_VENDOR_CMD_NEED_NETDEV |
8415 WIPHY_VENDOR_CMD_NEED_RUNNING,
8416 .doit = wlan_hdd_cfg80211_set_ota_test
8417 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008418#ifdef FEATURE_LFR_SUBNET_DETECTION
8419 {
8420 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8421 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8422 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8423 WIPHY_VENDOR_CMD_NEED_NETDEV |
8424 WIPHY_VENDOR_CMD_NEED_RUNNING,
8425 .doit = wlan_hdd_cfg80211_set_gateway_params
8426 },
8427#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008428 {
Peng Xud2220962016-07-11 17:59:17 -07008429 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008430 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8431 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8432 WIPHY_VENDOR_CMD_NEED_NETDEV |
8433 WIPHY_VENDOR_CMD_NEED_RUNNING,
8434 .doit = wlan_hdd_cfg80211_txpower_scale
8435 },
8436 {
8437 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8438 .info.subcmd =
8439 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8440 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8441 WIPHY_VENDOR_CMD_NEED_NETDEV |
8442 WIPHY_VENDOR_CMD_NEED_RUNNING,
8443 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8444 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308445 {
8446 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8447 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8448 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8449 WIPHY_VENDOR_CMD_NEED_NETDEV |
8450 WIPHY_VENDOR_CMD_NEED_RUNNING,
8451 .doit = wlan_hdd_cfg80211_bpf_offload
8452 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308453 {
8454 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308455 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8456 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8457 WIPHY_VENDOR_CMD_NEED_NETDEV |
8458 WIPHY_VENDOR_CMD_NEED_RUNNING,
8459 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8460 },
8461 {
8462 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308463 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8464 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8465 WIPHY_VENDOR_CMD_NEED_NETDEV |
8466 WIPHY_VENDOR_CMD_NEED_RUNNING,
8467 .doit = wlan_hdd_cfg80211_sta_roam_policy
8468 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308469#ifdef FEATURE_WLAN_CH_AVOID
8470 {
8471 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8472 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8473 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8474 WIPHY_VENDOR_CMD_NEED_NETDEV |
8475 WIPHY_VENDOR_CMD_NEED_RUNNING,
8476 .doit = wlan_hdd_cfg80211_avoid_freq
8477 },
8478#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308479 {
8480 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308481 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8482 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8483 WIPHY_VENDOR_CMD_NEED_NETDEV |
8484 WIPHY_VENDOR_CMD_NEED_RUNNING,
8485 .doit = wlan_hdd_cfg80211_sap_configuration_set
8486 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008487 {
Peng Xu4225c152016-07-14 21:18:14 -07008488 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008489 .info.subcmd =
8490 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8491 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8492 WIPHY_VENDOR_CMD_NEED_NETDEV |
8493 WIPHY_VENDOR_CMD_NEED_RUNNING,
8494 .doit = wlan_hdd_cfg80211_p2p_lo_start
8495 },
8496 {
8497 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8498 .info.subcmd =
8499 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8500 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8501 WIPHY_VENDOR_CMD_NEED_NETDEV |
8502 WIPHY_VENDOR_CMD_NEED_RUNNING,
8503 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8504 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308505 {
8506 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8507 .info.subcmd =
8508 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8509 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8510 WIPHY_VENDOR_CMD_NEED_NETDEV |
8511 WIPHY_VENDOR_CMD_NEED_RUNNING,
8512 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8513 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008514#ifdef WLAN_FEATURE_NAN_DATAPATH
8515 {
8516 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8517 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8518 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8519 WIPHY_VENDOR_CMD_NEED_NETDEV |
8520 WIPHY_VENDOR_CMD_NEED_RUNNING,
8521 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8522 },
8523#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308524 {
8525 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8526 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8527 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8528 WIPHY_VENDOR_CMD_NEED_NETDEV |
8529 WIPHY_VENDOR_CMD_NEED_RUNNING,
8530 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8531 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308532 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308533 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8534 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8535 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8536 WIPHY_VENDOR_CMD_NEED_NETDEV |
8537 WIPHY_VENDOR_CMD_NEED_RUNNING,
8538 .doit = wlan_hdd_cfg80211_get_bus_size
8539 },
8540 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308541 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8542 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8543 WIPHY_VENDOR_CMD_NEED_NETDEV |
8544 WIPHY_VENDOR_CMD_NEED_RUNNING,
8545 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308546 },
8547 {
8548 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8549 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8550 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8551 WIPHY_VENDOR_CMD_NEED_NETDEV |
8552 WIPHY_VENDOR_CMD_NEED_RUNNING,
8553 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308554 },
8555#ifdef WLAN_FEATURE_DISA
8556 {
8557 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8558 .info.subcmd =
8559 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8560 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8561 WIPHY_VENDOR_CMD_NEED_NETDEV |
8562 WIPHY_VENDOR_CMD_NEED_RUNNING,
8563 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8564 },
8565#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008566};
8567
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008568/**
8569 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8570 * @priv_size: Size of the hdd context.
8571 *
8572 * Allocate wiphy context and hdd context.
8573 *
8574 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008575 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008576hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008577{
8578 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008579 hdd_context_t *hdd_ctx;
8580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008581 ENTER();
8582
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008583 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8584
8585 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008586 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008587 return NULL;
8588 }
8589
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008590 hdd_ctx = wiphy_priv(wiphy);
8591
8592 hdd_ctx->wiphy = wiphy;
8593
8594 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008595}
8596
8597/*
8598 * FUNCTION: wlan_hdd_cfg80211_update_band
8599 * This function is called from the supplicant through a
8600 * private ioctl to change the band value
8601 */
8602int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8603{
8604 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008605 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008606
8607 ENTER();
8608
8609 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8610
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008611 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008612 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008613
8614 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8615 struct ieee80211_supported_band *band = wiphy->bands[i];
8616
8617 channelEnabledState =
8618 cds_get_channel_state(band->channels[j].
8619 hw_value);
8620
8621 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
8622 /* 5G only */
8623#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8624 /* Enable Social channels for P2P */
8625 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8626 (band->channels[j].center_freq)
8627 && CHANNEL_STATE_ENABLE ==
8628 channelEnabledState)
8629 band->channels[j].flags &=
8630 ~IEEE80211_CHAN_DISABLED;
8631 else
8632#endif
8633 band->channels[j].flags |=
8634 IEEE80211_CHAN_DISABLED;
8635 continue;
8636 } else if (IEEE80211_BAND_5GHZ == i &&
8637 eCSR_BAND_24 == eBand) {
8638 /* 2G only */
8639 band->channels[j].flags |=
8640 IEEE80211_CHAN_DISABLED;
8641 continue;
8642 }
8643
Amar Singhal6842e8f2016-02-23 16:30:32 -08008644 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008645 band->channels[j].flags &=
8646 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008647 }
8648 }
8649 return 0;
8650}
8651
8652/*
8653 * FUNCTION: wlan_hdd_cfg80211_init
8654 * This function is called by hdd_wlan_startup()
8655 * during initialization.
8656 * This function is used to initialize and register wiphy structure.
8657 */
8658int wlan_hdd_cfg80211_init(struct device *dev,
8659 struct wiphy *wiphy, struct hdd_config *pCfg)
8660{
8661 int i, j;
8662 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8663
8664 ENTER();
8665
8666 /* Now bind the underlying wlan device with wiphy */
8667 set_wiphy_dev(wiphy, dev);
8668
8669 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8670
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008671#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8672 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008673 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008674#else
8675 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008676 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008677#endif
8678
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008679 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8680 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8681 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8682#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8683 | WIPHY_FLAG_4ADDR_STATION
8684#endif
8685 | WIPHY_FLAG_OFFCHAN_TX;
8686
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008687#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8688 wiphy->wowlan = &wowlan_support_cfg80211_init;
8689#else
8690 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8691 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8692 wiphy->wowlan.pattern_min_len = 1;
8693 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8694#endif
8695
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008696 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008697#ifdef FEATURE_WLAN_ESE
8698 || pCfg->isEseIniFeatureEnabled
8699#endif
8700 ) {
8701 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8702 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008703#ifdef FEATURE_WLAN_TDLS
8704 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8705 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8706#endif
8707
8708 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8709
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008710#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8711 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8712#endif
8713
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008714#ifdef FEATURE_WLAN_SCAN_PNO
8715 if (pCfg->configPNOScanSupport) {
8716 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8717 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8718 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8719 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008720#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8721 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8722#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008723 }
8724#endif /*FEATURE_WLAN_SCAN_PNO */
8725
8726#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308727 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008728#endif
8729
8730 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8731 driver can still register regulatory callback and
8732 it will get regulatory settings in wiphy->band[], but
8733 driver need to determine what to do with both
8734 regulatory settings */
8735
8736 wiphy->reg_notifier = hdd_reg_notifier;
8737
8738#if defined QCA_WIFI_FTM
8739}
8740#endif
8741
8742 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8743
8744 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8745
8746 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8747
Arun Khandavallifae92942016-08-01 13:31:08 +05308748 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8749 | BIT(NL80211_IFTYPE_ADHOC)
8750 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8751 | BIT(NL80211_IFTYPE_P2P_GO)
8752 | BIT(NL80211_IFTYPE_AP)
8753 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008754
Arun Khandavallifae92942016-08-01 13:31:08 +05308755 if (pCfg->advertiseConcurrentOperation) {
8756 if (pCfg->enableMCC) {
8757 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008758
Arun Khandavallifae92942016-08-01 13:31:08 +05308759 for (i = 0;
8760 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8761 i++) {
8762 if (!pCfg->allowMCCGODiffBI)
8763 wlan_hdd_iface_combination[i].
8764 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008765 }
8766 }
8767 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308768 ARRAY_SIZE(wlan_hdd_iface_combination);
8769 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008770 }
8771
8772 /* Before registering we need to update the ht capabilitied based
8773 * on ini values*/
8774 if (!pCfg->ShortGI20MhzEnable) {
8775 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8776 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008777 }
8778
8779 if (!pCfg->ShortGI40MhzEnable) {
8780 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8781 }
8782
8783 if (!pCfg->nChannelBondingMode5GHz) {
8784 wlan_hdd_band_5_ghz.ht_cap.cap &=
8785 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8786 }
8787
Abhishek Singhf512bf32016-05-04 16:47:46 +05308788 /*
8789 * In case of static linked driver at the time of driver unload,
8790 * module exit doesn't happens. Module cleanup helps in cleaning
8791 * of static memory.
8792 * If driver load happens statically, at the time of driver unload,
8793 * wiphy flags don't get reset because of static memory.
8794 * It's better not to store channel in static memory.
8795 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008796 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308797 wiphy->bands[IEEE80211_BAND_2GHZ]->channels =
8798 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
8799 if (wiphy->bands[IEEE80211_BAND_2GHZ]->channels == NULL) {
8800 hdd_err("Not enough memory to allocate channels");
8801 return -ENOMEM;
8802 }
8803 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_2GHZ]->channels,
8804 &hdd_channels_2_4_ghz[0],
8805 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308806 if ((hdd_is_5g_supported(pHddCtx)) &&
8807 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8808 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8809 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8810 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008811 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308812 wiphy->bands[IEEE80211_BAND_5GHZ]->channels =
8813 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
8814 if (wiphy->bands[IEEE80211_BAND_5GHZ]->channels == NULL) {
8815 hdd_err("Not enough memory to allocate channels");
8816 qdf_mem_free(wiphy->
8817 bands[IEEE80211_BAND_2GHZ]->channels);
8818 wiphy->bands[IEEE80211_BAND_2GHZ]->channels = NULL;
8819 return -ENOMEM;
8820 }
8821 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_5GHZ]->channels,
8822 &hdd_channels_5_ghz[0],
8823 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008824 }
8825
8826 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8827
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008828 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008829 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008830
8831 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8832 struct ieee80211_supported_band *band = wiphy->bands[i];
8833
8834 if (IEEE80211_BAND_2GHZ == i &&
8835 eCSR_BAND_5G == pCfg->nBandCapability) {
8836 /* 5G only */
8837#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8838 /* Enable social channels for P2P */
8839 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8840 (band->channels[j].center_freq))
8841 band->channels[j].flags &=
8842 ~IEEE80211_CHAN_DISABLED;
8843 else
8844#endif
8845 band->channels[j].flags |=
8846 IEEE80211_CHAN_DISABLED;
8847 continue;
8848 } else if (IEEE80211_BAND_5GHZ == i &&
8849 eCSR_BAND_24 == pCfg->nBandCapability) {
8850 /* 2G only */
8851 band->channels[j].flags |=
8852 IEEE80211_CHAN_DISABLED;
8853 continue;
8854 }
8855 }
8856 }
8857 /*Initialise the supported cipher suite details */
8858 wiphy->cipher_suites = hdd_cipher_suites;
8859 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8860
8861 /*signal strength in mBm (100*dBm) */
8862 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8863 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8864
Anurag Chouhan6d760662016-02-20 16:05:43 +05308865 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008866 wiphy->n_vendor_commands =
8867 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8868 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8869
8870 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8871 wiphy->n_vendor_events =
8872 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8873 }
8874
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008875 if (pCfg->enableDFSMasterCap) {
8876 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8877 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008878
8879 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8880
8881#ifdef QCA_HT_2040_COEX
8882 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8883#endif
8884
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308885 hdd_add_channel_switch_support(&wiphy->flags);
8886
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008887 EXIT();
8888 return 0;
8889}
8890
Abhishek Singhf512bf32016-05-04 16:47:46 +05308891/**
8892 * wlan_hdd_cfg80211_deinit - Deinit cfg80211
8893 * @ wiphy: the wiphy to validate against
8894 *
8895 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308896 * memory allocated in wlan_hdd_cfg80211_init also
8897 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308898 *
8899 * Return: void
8900 */
8901void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8902{
8903 int i;
8904
8905 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8906 if (NULL != wiphy->bands[i] &&
8907 (NULL != wiphy->bands[i]->channels)) {
8908 qdf_mem_free(wiphy->bands[i]->channels);
8909 wiphy->bands[i]->channels = NULL;
8910 }
8911 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308912 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05308913}
8914
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008915/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308916 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008917 * initialization. In wlan_hdd_cfg80211_init, only the
8918 * default values will be initialized. The final initialization
8919 * of all required members can be done here.
8920 */
8921void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
8922{
8923 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8924}
8925
8926/* In this function we are registering wiphy. */
8927int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
8928{
8929 ENTER();
8930 /* Register our wiphy dev with cfg80211 */
8931 if (0 > wiphy_register(wiphy)) {
8932 /* print error */
Jeff Johnson77848112016-06-29 14:52:06 -07008933 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008934 return -EIO;
8935 }
8936
8937 EXIT();
8938 return 0;
8939}
8940
8941/*
8942 HDD function to update wiphy capability based on target offload status.
8943
8944 wlan_hdd_cfg80211_init() does initialization of all wiphy related
8945 capability even before downloading firmware to the target. In discrete
8946 case, host will get know certain offload capability (say sched_scan
8947 caps) only after downloading firmware to the target and target boots up.
8948 This function is used to override setting done in wlan_hdd_cfg80211_init()
8949 based on target capability.
8950 */
8951void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
8952{
8953#ifdef FEATURE_WLAN_SCAN_PNO
8954 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8955 struct hdd_config *pCfg = pHddCtx->config;
8956
8957 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
8958 * control comes here. Here just we need to clear it if firmware doesn't
8959 * have PNO support. */
8960 if (!pCfg->PnoOffload) {
8961 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8962 wiphy->max_sched_scan_ssids = 0;
8963 wiphy->max_match_sets = 0;
8964 wiphy->max_sched_scan_ie_len = 0;
8965 }
8966#endif
8967}
8968
8969/* This function registers for all frame which supplicant is interested in */
8970void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
8971{
8972 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8973 /* Register for all P2P action, public action etc frames */
8974 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8975
8976 ENTER();
8977
Abhishek Singh7996eb72015-12-30 17:24:02 +05308978 /* Register frame indication call back */
8979 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
8980
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05308981 /* Register for p2p ack indication */
8982 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
8983
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008984 /* Right now we are registering these frame when driver is getting
8985 initialized. Once we will move to 2.6.37 kernel, in which we have
8986 frame register ops, we will move this code as a part of that */
8987 /* GAS Initial Request */
8988 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8989 (uint8_t *) GAS_INITIAL_REQ,
8990 GAS_INITIAL_REQ_SIZE);
8991
8992 /* GAS Initial Response */
8993 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8994 (uint8_t *) GAS_INITIAL_RSP,
8995 GAS_INITIAL_RSP_SIZE);
8996
8997 /* GAS Comeback Request */
8998 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8999 (uint8_t *) GAS_COMEBACK_REQ,
9000 GAS_COMEBACK_REQ_SIZE);
9001
9002 /* GAS Comeback Response */
9003 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9004 (uint8_t *) GAS_COMEBACK_RSP,
9005 GAS_COMEBACK_RSP_SIZE);
9006
9007 /* P2P Public Action */
9008 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9009 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9010 P2P_PUBLIC_ACTION_FRAME_SIZE);
9011
9012 /* P2P Action */
9013 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9014 (uint8_t *) P2P_ACTION_FRAME,
9015 P2P_ACTION_FRAME_SIZE);
9016
9017 /* WNM BSS Transition Request frame */
9018 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9019 (uint8_t *) WNM_BSS_ACTION_FRAME,
9020 WNM_BSS_ACTION_FRAME_SIZE);
9021
9022 /* WNM-Notification */
9023 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9024 (uint8_t *) WNM_NOTIFICATION_FRAME,
9025 WNM_NOTIFICATION_FRAME_SIZE);
9026}
9027
9028void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9029{
9030 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9031 /* Register for all P2P action, public action etc frames */
9032 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9033
9034 ENTER();
9035
9036 /* Right now we are registering these frame when driver is getting
9037 initialized. Once we will move to 2.6.37 kernel, in which we have
9038 frame register ops, we will move this code as a part of that */
9039 /* GAS Initial Request */
9040
9041 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9042 (uint8_t *) GAS_INITIAL_REQ,
9043 GAS_INITIAL_REQ_SIZE);
9044
9045 /* GAS Initial Response */
9046 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9047 (uint8_t *) GAS_INITIAL_RSP,
9048 GAS_INITIAL_RSP_SIZE);
9049
9050 /* GAS Comeback Request */
9051 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9052 (uint8_t *) GAS_COMEBACK_REQ,
9053 GAS_COMEBACK_REQ_SIZE);
9054
9055 /* GAS Comeback Response */
9056 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9057 (uint8_t *) GAS_COMEBACK_RSP,
9058 GAS_COMEBACK_RSP_SIZE);
9059
9060 /* P2P Public Action */
9061 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9062 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9063 P2P_PUBLIC_ACTION_FRAME_SIZE);
9064
9065 /* P2P Action */
9066 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9067 (uint8_t *) P2P_ACTION_FRAME,
9068 P2P_ACTION_FRAME_SIZE);
9069
9070 /* WNM-Notification */
9071 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9072 (uint8_t *) WNM_NOTIFICATION_FRAME,
9073 WNM_NOTIFICATION_FRAME_SIZE);
9074}
9075
9076#ifdef FEATURE_WLAN_WAPI
9077void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9078 const uint8_t *mac_addr, const uint8_t *key,
9079 int key_Len)
9080{
9081 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9082 tCsrRoamSetKey setKey;
9083 bool isConnected = true;
9084 int status = 0;
9085 uint32_t roamId = 0xFF;
9086 uint8_t *pKeyPtr = NULL;
9087 int n = 0;
9088
Jeff Johnson46b40792016-06-29 14:03:14 -07009089 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009090 hdd_device_mode_to_string(pAdapter->device_mode),
9091 pAdapter->device_mode);
9092
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309093 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009094 setKey.keyId = key_index; /* Store Key ID */
9095 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9096 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9097 setKey.paeRole = 0; /* the PAE role */
9098 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309099 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009100 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309101 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009102 }
9103 setKey.keyLength = key_Len;
9104 pKeyPtr = setKey.Key;
9105 memcpy(pKeyPtr, key, key_Len);
9106
Jeff Johnson46b40792016-06-29 14:03:14 -07009107 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009108 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009109 hdd_notice("WAPI KEY Data[%d]:%02x ",
9110 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009111
9112 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9113 if (isConnected) {
9114 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9115 pAdapter->sessionId, &setKey, &roamId);
9116 }
9117 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009118 hdd_err("sme_roam_set_key returned ERROR status= %d",
9119 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009120 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9121 }
9122}
9123#endif /* FEATURE_WLAN_WAPI */
9124
9125uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9126 uint8_t eid)
9127{
9128 int left = length;
9129 uint8_t *ptr = (uint8_t *)ies_ptr;
9130 uint8_t elem_id, elem_len;
9131
9132 while (left >= 2) {
9133 elem_id = ptr[0];
9134 elem_len = ptr[1];
9135 left -= 2;
9136 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009137 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009138 eid, elem_len, left);
9139 return NULL;
9140 }
9141 if (elem_id == eid) {
9142 return ptr;
9143 }
9144
9145 left -= elem_len;
9146 ptr += (elem_len + 2);
9147 }
9148 return NULL;
9149}
9150
9151/*
9152 * FUNCTION: wlan_hdd_validate_operation_channel
9153 * called by wlan_hdd_cfg80211_start_bss() and
9154 * wlan_hdd_set_channel()
9155 * This function validates whether given channel is part of valid
9156 * channel list.
9157 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309158QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009159 int channel)
9160{
9161
9162 uint32_t num_ch = 0;
9163 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9164 u32 indx = 0;
9165 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9166 uint8_t fValidChannel = false, count = 0;
9167 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9168
9169 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9170
9171 if (hdd_pConfig_ini->sapAllowAllChannel) {
9172 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009173 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009174 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009175 fValidChannel = true;
9176 break;
9177 }
9178 }
9179 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009180 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309181 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009182 }
9183 } else {
9184 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9185 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009186 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309187 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009188 }
9189 for (indx = 0; indx < num_ch; indx++) {
9190 if (channel == valid_ch[indx]) {
9191 break;
9192 }
9193 }
9194
9195 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009196 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309197 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009198 }
9199 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309200 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009201
9202}
9203
9204#ifdef DHCP_SERVER_OFFLOAD
9205static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9206{
9207 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9208 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9209 uint8_t numEntries = 0;
9210 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9211 uint8_t num;
9212 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309213 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009214 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009215 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009216 return;
9217 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309218 qdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009219 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9220 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9221 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9222 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9223 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9224 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009225 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009226 goto end;
9227 }
9228 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009229 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009230 goto end;
9231 }
9232 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009233 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009234 goto end;
9235 }
9236 for (num = 0; num < numEntries; num++) {
9237 temp = srv_ip[num];
9238 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9239 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309240 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009241 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009242 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009243 goto end;
9244 }
Jeff Johnson77848112016-06-29 14:52:06 -07009245 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009246end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309247 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009248 return;
9249}
9250#endif /* DHCP_SERVER_OFFLOAD */
9251
9252static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9253 struct net_device *dev,
9254 struct bss_parameters *params)
9255{
9256 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9257 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9258 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309259 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009260
9261 ENTER();
9262
Anurag Chouhan6d760662016-02-20 16:05:43 +05309263 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009264 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009265 return -EINVAL;
9266 }
9267
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309268 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009269 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9270 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009271 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009272 hdd_device_mode_to_string(pAdapter->device_mode),
9273 pAdapter->device_mode, params->ap_isolate);
9274
9275 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9276 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309277 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009278 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009279
Krunal Sonib4326f22016-03-10 13:05:51 -08009280 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9281 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009282 return -EOPNOTSUPP;
9283 }
9284
9285 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9286 * want to update this parameter */
9287 if (-1 != params->ap_isolate) {
9288 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9289 !!params->ap_isolate;
9290
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309291 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009292 pAdapter->sessionId,
9293 pAdapter->sessionCtx.
9294 ap.
9295 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309296 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009297 ret = -EINVAL;
9298 }
9299 }
9300
9301 EXIT();
9302 return ret;
9303}
9304
Krunal Soni8c37e322016-02-03 16:08:37 -08009305/**
9306 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9307 * @ndev: pointer to net device provided by supplicant
9308 * @type: type of the interface, upper layer wanted to change
9309 *
9310 * Upper layer provides the new interface mode that needs to be changed
9311 * for given net device
9312 *
9313 * Return: success or failure in terms of integer value
9314 */
9315static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009316 enum nl80211_iftype type)
9317{
Krunal Soni8c37e322016-02-03 16:08:37 -08009318 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9319 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9320 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009321 hdd_wext_state_t *wext;
9322 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309323 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009324
9325 ENTER();
9326
Krunal Soni8c37e322016-02-03 16:08:37 -08009327 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009328 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009329 return 0;
9330 }
9331
9332 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009333 hdd_stop_adapter(hdd_ctx, adapter, true);
9334 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009335 wdev->iftype = type;
9336 /*Check for sub-string p2p to confirm its a p2p interface */
9337 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009338 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009339 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009340 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009341 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009342 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009343 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009344 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009345 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009346 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009347 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009348 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9349 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009350 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9351 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009352 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009353 adapter->scan_info.scanAddIE.length;
9354 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309355 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009356 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9357 wext->roamProfile.phyMode =
9358 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9359 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009360 EXIT();
9361 return status;
9362}
9363
9364static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9365 struct net_device *dev,
9366 struct bss_parameters *params)
9367{
9368 int ret;
9369
9370 cds_ssr_protect(__func__);
9371 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9372 cds_ssr_unprotect(__func__);
9373
9374 return ret;
9375}
9376
9377/* FUNCTION: wlan_hdd_change_country_code_cd
9378 * to wait for contry code completion
9379 */
9380void *wlan_hdd_change_country_code_cb(void *pAdapter)
9381{
9382 hdd_adapter_t *call_back_pAdapter = pAdapter;
9383 complete(&call_back_pAdapter->change_country_code);
9384 return NULL;
9385}
9386
Rajeev Kumar98edb772016-01-19 12:42:19 -08009387/**
9388 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9389 * @wiphy: Pointer to the wiphy structure
9390 * @ndev: Pointer to the net device
9391 * @type: Interface type
9392 * @flags: Flags for change interface
9393 * @params: Pointer to change interface parameters
9394 *
9395 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009396 */
9397static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9398 struct net_device *ndev,
9399 enum nl80211_iftype type,
9400 u32 *flags,
9401 struct vif_params *params)
9402{
9403 struct wireless_dev *wdev;
9404 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9405 hdd_context_t *pHddCtx;
9406 tCsrRoamProfile *pRoamProfile = NULL;
9407 eCsrRoamBssType LastBSSType;
9408 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309409 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009410 int status;
9411
9412 ENTER();
9413
Anurag Chouhan6d760662016-02-20 16:05:43 +05309414 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009415 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009416 return -EINVAL;
9417 }
9418
9419 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9420 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309421 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009422 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009423
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309424 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009425 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9426 pAdapter->sessionId, type));
9427
Jeff Johnson77848112016-06-29 14:52:06 -07009428 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009429 pAdapter->device_mode, type);
9430
Arun Khandavallifae92942016-08-01 13:31:08 +05309431 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9432 if (status) {
9433 hdd_err("Failed to start modules");
9434 return -EINVAL;
9435 }
9436
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009437 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009438 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9439 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009440 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009441 return -EINVAL;
9442 }
9443
9444 pConfig = pHddCtx->config;
9445 wdev = ndev->ieee80211_ptr;
9446
9447 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009448 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009449
9450 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9451
Krunal Sonib4326f22016-03-10 13:05:51 -08009452 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9453 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9454 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9455 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009456 hdd_wext_state_t *pWextState =
9457 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9458
9459 pRoamProfile = &pWextState->roamProfile;
9460 LastBSSType = pRoamProfile->BSSType;
9461
9462 switch (type) {
9463 case NL80211_IFTYPE_STATION:
9464 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009465 case NL80211_IFTYPE_ADHOC:
9466 if (type == NL80211_IFTYPE_ADHOC) {
9467 wlan_hdd_tdls_exit(pAdapter);
9468 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009469 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009470 }
9471 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9472 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309473 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009474 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309475 if (hdd_start_adapter(pAdapter)) {
9476 hdd_err("Failed to start adapter :%d",
9477 pAdapter->device_mode);
9478 return -EINVAL;
9479 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009480 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009481 case NL80211_IFTYPE_AP:
9482 case NL80211_IFTYPE_P2P_GO:
9483 {
Jeff Johnson77848112016-06-29 14:52:06 -07009484 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009485 (type ==
9486 NL80211_IFTYPE_AP) ? "SoftAP" :
9487 "P2pGo");
9488
9489 /* Cancel any remain on channel for GO mode */
9490 if (NL80211_IFTYPE_P2P_GO == type) {
9491 wlan_hdd_cancel_existing_remain_on_channel
9492 (pAdapter);
9493 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009494
Arun Khandavallifae92942016-08-01 13:31:08 +05309495 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009496 /* De-init the adapter */
9497 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9498 memset(&pAdapter->sessionCtx, 0,
9499 sizeof(pAdapter->sessionCtx));
9500 pAdapter->device_mode =
9501 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009502 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9503 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009504
9505 /*
9506 * Fw will take care incase of concurrency
9507 */
9508
Krunal Sonib4326f22016-03-10 13:05:51 -08009509 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009510 && (pConfig->apRandomBssidEnabled)) {
9511 /* To meet Android requirements create a randomized
9512 MAC address of the form 02:1A:11:Fx:xx:xx */
9513 get_random_bytes(&ndev->dev_addr[3], 3);
9514 ndev->dev_addr[0] = 0x02;
9515 ndev->dev_addr[1] = 0x1A;
9516 ndev->dev_addr[2] = 0x11;
9517 ndev->dev_addr[3] |= 0xF0;
9518 memcpy(pAdapter->macAddressCurrent.
9519 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309520 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009521 pr_info("wlan: Generated HotSpot BSSID "
9522 MAC_ADDRESS_STR "\n",
9523 MAC_ADDR_ARRAY(ndev->dev_addr));
9524 }
9525
9526 hdd_set_ap_ops(pAdapter->dev);
9527
Arun Khandavallifae92942016-08-01 13:31:08 +05309528 if (hdd_start_adapter(pAdapter)) {
9529 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009530 return -EINVAL;
9531 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009532 /* Interface type changed update in wiphy structure */
9533 if (wdev) {
9534 wdev->iftype = type;
9535 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009536 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009537 return -EINVAL;
9538 }
9539 goto done;
9540 }
9541
9542 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009543 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009544 type);
9545 return -EOPNOTSUPP;
9546 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009547 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9548 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009549 switch (type) {
9550 case NL80211_IFTYPE_STATION:
9551 case NL80211_IFTYPE_P2P_CLIENT:
9552 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009553 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9554 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309555 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009556 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309557 if (hdd_start_adapter(pAdapter)) {
9558 hdd_err("Failed to start adapter :%d",
9559 pAdapter->device_mode);
9560 return -EINVAL;
9561 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009562 goto done;
9563
9564 case NL80211_IFTYPE_AP:
9565 case NL80211_IFTYPE_P2P_GO:
9566 wdev->iftype = type;
9567 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009568 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009569 goto done;
9570
9571 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009572 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009573 type);
9574 return -EOPNOTSUPP;
9575 }
9576 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009577 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009578 pAdapter->device_mode);
9579 return -EOPNOTSUPP;
9580 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009581done:
9582 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009583 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009584
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009585 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009586
9587 EXIT();
9588 return 0;
9589}
9590
Rajeev Kumar98edb772016-01-19 12:42:19 -08009591/**
9592 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9593 * @wiphy: Pointer to the wiphy structure
9594 * @ndev: Pointer to the net device
9595 * @type: Interface type
9596 * @flags: Flags for change interface
9597 * @params: Pointer to change interface parameters
9598 *
9599 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009600 */
9601static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9602 struct net_device *ndev,
9603 enum nl80211_iftype type,
9604 u32 *flags,
9605 struct vif_params *params)
9606{
9607 int ret;
9608
9609 cds_ssr_protect(__func__);
9610 ret =
9611 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9612 cds_ssr_unprotect(__func__);
9613
9614 return ret;
9615}
9616
9617#ifdef FEATURE_WLAN_TDLS
9618static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9619 int index, uint8_t match)
9620{
9621 int i;
9622 for (i = 0; i < index; i++) {
9623 if (arr[i] == match)
9624 return true;
9625 }
9626 return false;
9627}
9628#endif
9629
9630/**
9631 * __wlan_hdd_change_station() - change station
9632 * @wiphy: Pointer to the wiphy structure
9633 * @dev: Pointer to the net device.
9634 * @mac: bssid
9635 * @params: Pointer to station parameters
9636 *
9637 * Return: 0 for success, error number on failure.
9638 */
9639#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9640static int __wlan_hdd_change_station(struct wiphy *wiphy,
9641 struct net_device *dev,
9642 const uint8_t *mac,
9643 struct station_parameters *params)
9644#else
9645static int __wlan_hdd_change_station(struct wiphy *wiphy,
9646 struct net_device *dev,
9647 uint8_t *mac,
9648 struct station_parameters *params)
9649#endif
9650{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309651 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009652 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9653 hdd_context_t *pHddCtx;
9654 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309655 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009656#ifdef FEATURE_WLAN_TDLS
9657 tCsrStaParams StaParams = { 0 };
9658 uint8_t isBufSta = 0;
9659 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309660 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009661#endif
9662 int ret;
9663
9664 ENTER();
9665
Anurag Chouhan6d760662016-02-20 16:05:43 +05309666 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009667 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009668 return -EINVAL;
9669 }
9670
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309671 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009672 TRACE_CODE_HDD_CHANGE_STATION,
9673 pAdapter->sessionId, params->listen_interval));
9674
9675 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9676 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309677 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009678 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009679
9680 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9681
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309682 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009683
Krunal Sonib4326f22016-03-10 13:05:51 -08009684 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9685 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009686 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9687 status =
9688 hdd_softap_change_sta_state(pAdapter,
9689 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009690 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009691
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309692 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009693 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009694 return -EINVAL;
9695 }
9696 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009697 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9698 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009699#ifdef FEATURE_WLAN_TDLS
9700 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009701
9702 if (cds_is_sub_20_mhz_enabled()) {
9703 hdd_err("TDLS not allowed with sub 20 MHz");
9704 return -EINVAL;
9705 }
9706
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009707 StaParams.capability = params->capability;
9708 StaParams.uapsd_queues = params->uapsd_queues;
9709 StaParams.max_sp = params->max_sp;
9710
9711 /* Convert (first channel , number of channels) tuple to
9712 * the total list of channels. This goes with the assumption
9713 * that if the first channel is < 14, then the next channels
9714 * are an incremental of 1 else an incremental of 4 till the number
9715 * of channels.
9716 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009717 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009718 if (0 != params->supported_channels_len) {
9719 int i = 0, j = 0, k = 0, no_of_channels = 0;
9720 int num_unique_channels;
9721 int next;
9722 for (i = 0;
9723 i < params->supported_channels_len
9724 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9725 int wifi_chan_index;
9726 if (!wlan_hdd_is_duplicate_channel
9727 (StaParams.supported_channels, j,
9728 params->supported_channels[i])) {
9729 StaParams.
9730 supported_channels[j] =
9731 params->
9732 supported_channels[i];
9733 } else {
9734 continue;
9735 }
9736 wifi_chan_index =
9737 ((StaParams.supported_channels[j] <=
9738 HDD_CHANNEL_14) ? 1 : 4);
9739 no_of_channels =
9740 params->supported_channels[i + 1];
9741
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009742 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 -08009743 StaParams.
9744 supported_channels[j],
9745 wifi_chan_index,
9746 no_of_channels);
9747 for (k = 1; k <= no_of_channels &&
9748 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9749 k++) {
9750 next =
9751 StaParams.
9752 supported_channels[j] +
9753 wifi_chan_index;
9754 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9755 StaParams.
9756 supported_channels[j
9757 +
9758 1]
9759 = next;
9760 } else {
9761 continue;
9762 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009763 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009764 j + 1,
9765 StaParams.
9766 supported_channels[j +
9767 1]);
9768 j += 1;
9769 }
9770 }
9771 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009772 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009773 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009774 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009775 StaParams.
9776 supported_channels[i]);
9777 }
9778 if (MAX_CHANNEL < num_unique_channels)
9779 num_unique_channels = MAX_CHANNEL;
9780 StaParams.supported_channels_len =
9781 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009782 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009783 StaParams.supported_channels_len);
9784 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309785 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009786 params->supported_oper_classes,
9787 params->supported_oper_classes_len);
9788 StaParams.supported_oper_classes_len =
9789 params->supported_oper_classes_len;
9790
9791 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309792 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009793 params->ext_capab,
9794 sizeof(StaParams.extn_capability));
9795
9796 if (NULL != params->ht_capa) {
9797 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309798 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009799 sizeof(tSirHTCap));
9800 }
9801
9802 StaParams.supported_rates_len =
9803 params->supported_rates_len;
9804
9805 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9806 * The supported_rates array , for all the structures propogating till Add Sta
9807 * to the firmware has to be modified , if the supplicant (ieee80211) is
9808 * modified to send more rates.
9809 */
9810
9811 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
9812 */
9813 if (StaParams.supported_rates_len >
9814 SIR_MAC_MAX_SUPP_RATES)
9815 StaParams.supported_rates_len =
9816 SIR_MAC_MAX_SUPP_RATES;
9817
9818 if (0 != StaParams.supported_rates_len) {
9819 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309820 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009821 params->supported_rates,
9822 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009823 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009824 StaParams.supported_rates_len);
9825 for (i = 0; i < StaParams.supported_rates_len;
9826 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009827 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009828 StaParams.supported_rates[i]);
9829 }
9830
9831 if (NULL != params->vht_capa) {
9832 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309833 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009834 params->vht_capa,
9835 sizeof(tSirVHTCap));
9836 }
9837
9838 if (0 != params->ext_capab_len) {
9839 /*Define A Macro : TODO Sunil */
9840 if ((1 << 4) & StaParams.extn_capability[3]) {
9841 isBufSta = 1;
9842 }
9843 /* TDLS Channel Switching Support */
9844 if ((1 << 6) & StaParams.extn_capability[3]) {
9845 isOffChannelSupported = 1;
9846 }
9847 }
9848
Nitesh Shah99934ac2016-09-05 15:54:08 +05309849 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +05309850 (params->ht_capa || params->vht_capa ||
9851 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +05309852 is_qos_wmm_sta = true;
9853
9854 hdd_notice("%s: TDLS Peer is QOS capable"
9855 " is_qos_wmm_sta= %d HTcapPresent = %d",
9856 __func__, is_qos_wmm_sta,
9857 StaParams.htcap_present);
9858
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009859 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +05309860 &StaParams,
9861 isBufSta,
9862 isOffChannelSupported,
9863 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309864 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009865 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009866 return -EINVAL;
9867 }
9868
9869 status =
9870 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
9871 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309872 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009873 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009874 return -EINVAL;
9875 }
9876 }
9877#endif
9878 }
9879 EXIT();
9880 return ret;
9881}
9882
9883/**
9884 * wlan_hdd_change_station() - cfg80211 change station handler function
9885 * @wiphy: Pointer to the wiphy structure
9886 * @dev: Pointer to the net device.
9887 * @mac: bssid
9888 * @params: Pointer to station parameters
9889 *
9890 * This is the cfg80211 change station handler function which invokes
9891 * the internal function @__wlan_hdd_change_station with
9892 * SSR protection.
9893 *
9894 * Return: 0 for success, error number on failure.
9895 */
9896#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
9897static int wlan_hdd_change_station(struct wiphy *wiphy,
9898 struct net_device *dev,
9899 const u8 *mac,
9900 struct station_parameters *params)
9901#else
9902static int wlan_hdd_change_station(struct wiphy *wiphy,
9903 struct net_device *dev,
9904 u8 *mac,
9905 struct station_parameters *params)
9906#endif
9907{
9908 int ret;
9909
9910 cds_ssr_protect(__func__);
9911 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
9912 cds_ssr_unprotect(__func__);
9913
9914 return ret;
9915}
9916
9917/*
9918 * FUNCTION: __wlan_hdd_cfg80211_add_key
9919 * This function is used to initialize the key information
9920 */
9921static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
9922 struct net_device *ndev,
9923 u8 key_index, bool pairwise,
9924 const u8 *mac_addr,
9925 struct key_params *params)
9926{
9927 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9928 tCsrRoamSetKey setKey;
9929 int status;
9930 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009931 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309932 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009933 hdd_context_t *pHddCtx;
9934 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9935
9936 ENTER();
9937
Anurag Chouhan6d760662016-02-20 16:05:43 +05309938 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009939 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009940 return -EINVAL;
9941 }
9942
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309943 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009944 TRACE_CODE_HDD_CFG80211_ADD_KEY,
9945 pAdapter->sessionId, params->key_len));
9946 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9947 status = wlan_hdd_validate_context(pHddCtx);
9948
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309949 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009950 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009951
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009952 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009953 hdd_device_mode_to_string(pAdapter->device_mode),
9954 pAdapter->device_mode);
9955
9956 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009957 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009958
9959 return -EINVAL;
9960 }
9961
9962 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009963 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009964
9965 return -EINVAL;
9966 }
9967
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009968 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009969
9970 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309971 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009972 setKey.keyId = key_index;
9973 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309974 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009975
9976 switch (params->cipher) {
9977 case WLAN_CIPHER_SUITE_WEP40:
9978 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9979 break;
9980
9981 case WLAN_CIPHER_SUITE_WEP104:
9982 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
9983 break;
9984
9985 case WLAN_CIPHER_SUITE_TKIP:
9986 {
9987 u8 *pKey = &setKey.Key[0];
9988 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
9989
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309990 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009991
9992 /*Supplicant sends the 32bytes key in this order
9993
9994 |--------------|----------|----------|
9995 | Tk1 |TX-MIC | RX Mic |
9996 |||--------------|----------|----------|
9997 <---16bytes---><--8bytes--><--8bytes-->
9998
9999 */
10000 /*Sme expects the 32 bytes key to be in the below order
10001
10002 |--------------|----------|----------|
10003 | Tk1 |RX-MIC | TX Mic |
10004 |||--------------|----------|----------|
10005 <---16bytes---><--8bytes--><--8bytes-->
10006 */
10007 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010008 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010009
10010 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010011 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010012
10013 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010014 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010015
10016 break;
10017 }
10018
10019 case WLAN_CIPHER_SUITE_CCMP:
10020 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10021 break;
10022
10023#ifdef FEATURE_WLAN_WAPI
10024 case WLAN_CIPHER_SUITE_SMS4:
10025 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010026 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010027 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10028 mac_addr, params->key,
10029 params->key_len);
10030 return 0;
10031 }
10032#endif
10033
10034#ifdef FEATURE_WLAN_ESE
10035 case WLAN_CIPHER_SUITE_KRK:
10036 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10037 break;
10038#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10039 case WLAN_CIPHER_SUITE_BTK:
10040 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10041 break;
10042#endif
10043#endif
10044
10045#ifdef WLAN_FEATURE_11W
10046 case WLAN_CIPHER_SUITE_AES_CMAC:
10047 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10048 break;
10049#endif
10050
10051 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010052 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010053 return -EOPNOTSUPP;
10054 }
10055
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010056 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010057
10058 if (!pairwise) {
10059 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010060 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010061 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010062 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010063 } else {
10064 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010065 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010066 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010067 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010068 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010069 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010070 /* if a key is already installed, block all subsequent ones */
10071 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010072 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010073 return 0;
10074 }
10075
10076 setKey.keyDirection = eSIR_TX_RX;
10077 /*Set the group key */
10078 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10079 pAdapter->sessionId, &setKey, &roamId);
10080
10081 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010082 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010083 return -EINVAL;
10084 }
10085 /*Save the keys here and call sme_roam_set_key for setting
10086 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010087 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010088 &setKey, sizeof(tCsrRoamSetKey));
10089
10090 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10091 return status;
10092 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010093 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10094 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010095 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10096 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010097 status = wlansap_set_key_sta(
10098 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010099 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010100 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010101 __LINE__, status);
10102 }
10103 }
10104
10105 /* Save the key in ap ctx for use on START_BASS and restart */
10106 if (pairwise ||
10107 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10108 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010109 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010110 sizeof(tCsrRoamSetKey));
10111 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010112 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010113 sizeof(tCsrRoamSetKey));
10114
Krunal Sonib4326f22016-03-10 13:05:51 -080010115 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10116 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010117 hdd_wext_state_t *pWextState =
10118 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10119 hdd_station_ctx_t *pHddStaCtx =
10120 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10121
10122 if (!pairwise) {
10123 /* set group key */
10124 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010125 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010126 __func__, __LINE__);
10127 hdd_perform_roam_set_key_complete(pAdapter);
10128 }
10129 }
10130
10131 pWextState->roamProfile.Keys.KeyLength[key_index] =
10132 (u8) params->key_len;
10133
10134 pWextState->roamProfile.Keys.defaultIndex = key_index;
10135
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010136 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010137 KeyMaterial[key_index][0], params->key,
10138 params->key_len);
10139
10140 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10141
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010142 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010143 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10144 setKey.keyDirection);
10145
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010146 /* The supplicant may attempt to set the PTK once pre-authentication
10147 is done. Save the key in the UMAC and include it in the ADD BSS
10148 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010149 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010150 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010151 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010152 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010153 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010154 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010155 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010156 return -EINVAL;
10157 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010158
10159 /* issue set key request to SME */
10160 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10161 pAdapter->sessionId, &setKey, &roamId);
10162
10163 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010164 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010165 pHddStaCtx->roam_info.roamingState =
10166 HDD_ROAM_STATE_NONE;
10167 return -EINVAL;
10168 }
10169
10170 /* in case of IBSS as there was no information available about WEP keys during
10171 * IBSS join, group key intialized with NULL key, so re-initialize group key
10172 * with correct value*/
10173 if ((eCSR_BSS_TYPE_START_IBSS ==
10174 pWextState->roamProfile.BSSType)
10175 &&
10176 !((IW_AUTH_KEY_MGMT_802_1X ==
10177 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10178 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10179 pHddStaCtx->conn_info.authType)
10180 )
10181 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10182 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10183 )
10184 ) {
10185 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010186 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010187
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010188 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010189 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10190 setKey.keyDirection);
10191
10192 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10193 pAdapter->sessionId, &setKey,
10194 &roamId);
10195
10196 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010197 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010198 pHddStaCtx->roam_info.roamingState =
10199 HDD_ROAM_STATE_NONE;
10200 return -EINVAL;
10201 }
10202 }
10203 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010204 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010205 return 0;
10206}
10207
10208static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10209 struct net_device *ndev,
10210 u8 key_index, bool pairwise,
10211 const u8 *mac_addr,
10212 struct key_params *params)
10213{
10214 int ret;
10215 cds_ssr_protect(__func__);
10216 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10217 mac_addr, params);
10218 cds_ssr_unprotect(__func__);
10219
10220 return ret;
10221}
10222
10223/*
10224 * FUNCTION: __wlan_hdd_cfg80211_get_key
10225 * This function is used to get the key information
10226 */
10227static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10228 struct net_device *ndev,
10229 u8 key_index, bool pairwise,
10230 const u8 *mac_addr, void *cookie,
10231 void (*callback)(void *cookie,
10232 struct key_params *)
10233 )
10234{
10235 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10236 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10237 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10238 struct key_params params;
10239
10240 ENTER();
10241
Anurag Chouhan6d760662016-02-20 16:05:43 +053010242 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010243 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010244 return -EINVAL;
10245 }
10246
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010247 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010248 hdd_device_mode_to_string(pAdapter->device_mode),
10249 pAdapter->device_mode);
10250
10251 memset(&params, 0, sizeof(params));
10252
10253 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010254 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010255 key_index);
10256 return -EINVAL;
10257 }
10258
10259 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10260 case eCSR_ENCRYPT_TYPE_NONE:
10261 params.cipher = IW_AUTH_CIPHER_NONE;
10262 break;
10263
10264 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10265 case eCSR_ENCRYPT_TYPE_WEP40:
10266 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10267 break;
10268
10269 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10270 case eCSR_ENCRYPT_TYPE_WEP104:
10271 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10272 break;
10273
10274 case eCSR_ENCRYPT_TYPE_TKIP:
10275 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10276 break;
10277
10278 case eCSR_ENCRYPT_TYPE_AES:
10279 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10280 break;
10281
10282 default:
10283 params.cipher = IW_AUTH_CIPHER_NONE;
10284 break;
10285 }
10286
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010287 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010288 TRACE_CODE_HDD_CFG80211_GET_KEY,
10289 pAdapter->sessionId, params.cipher));
10290
10291 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10292 params.seq_len = 0;
10293 params.seq = NULL;
10294 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10295 callback(cookie, &params);
10296
10297 EXIT();
10298 return 0;
10299}
10300
10301static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10302 struct net_device *ndev,
10303 u8 key_index, bool pairwise,
10304 const u8 *mac_addr, void *cookie,
10305 void (*callback)(void *cookie,
10306 struct key_params *)
10307 )
10308{
10309 int ret;
10310
10311 cds_ssr_protect(__func__);
10312 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10313 mac_addr, cookie, callback);
10314 cds_ssr_unprotect(__func__);
10315
10316 return ret;
10317}
10318
10319/**
10320 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10321 * @wiphy: wiphy interface context
10322 * @ndev: pointer to net device
10323 * @key_index: Key index used in 802.11 frames
10324 * @unicast: true if it is unicast key
10325 * @multicast: true if it is multicast key
10326 *
10327 * This function is required for cfg80211_ops API.
10328 * It is used to delete the key information
10329 * Underlying hardware implementation does not have API to delete the
10330 * encryption key. It is automatically deleted when the peer is
10331 * removed. Hence this function currently does nothing.
10332 * Future implementation may interprete delete key operation to
10333 * replacing the key with a random junk value, effectively making it
10334 * useless.
10335 *
10336 * Return: status code, always 0.
10337 */
10338
10339static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10340 struct net_device *ndev,
10341 u8 key_index,
10342 bool pairwise, const u8 *mac_addr)
10343{
10344 EXIT();
10345 return 0;
10346}
10347
10348/**
10349 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10350 * @wiphy: Pointer to wiphy structure.
10351 * @dev: Pointer to net_device structure.
10352 * @key_index: key index
10353 * @pairwise: pairwise
10354 * @mac_addr: mac address
10355 *
10356 * This is the cfg80211 delete key handler function which invokes
10357 * the internal function @__wlan_hdd_cfg80211_del_key with
10358 * SSR protection.
10359 *
10360 * Return: 0 for success, error number on failure.
10361 */
10362static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10363 struct net_device *dev,
10364 u8 key_index,
10365 bool pairwise, const u8 *mac_addr)
10366{
10367 int ret;
10368
10369 cds_ssr_protect(__func__);
10370 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10371 pairwise, mac_addr);
10372 cds_ssr_unprotect(__func__);
10373
10374 return ret;
10375}
10376
10377/*
10378 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10379 * This function is used to set the default tx key index
10380 */
10381static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10382 struct net_device *ndev,
10383 u8 key_index,
10384 bool unicast, bool multicast)
10385{
10386 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10387 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10388 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10389 hdd_context_t *pHddCtx;
10390 int status;
10391
10392 ENTER();
10393
Anurag Chouhan6d760662016-02-20 16:05:43 +053010394 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010395 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010396 return -EINVAL;
10397 }
10398
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010399 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010400 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10401 pAdapter->sessionId, key_index));
10402
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010403 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010404 hdd_device_mode_to_string(pAdapter->device_mode),
10405 pAdapter->device_mode, key_index);
10406
10407 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010408 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010409 return -EINVAL;
10410 }
10411
10412 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10413 status = wlan_hdd_validate_context(pHddCtx);
10414
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010415 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010416 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010417
Krunal Sonib4326f22016-03-10 13:05:51 -080010418 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10419 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010420 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10421 pHddStaCtx->conn_info.ucEncryptionType) &&
10422 (eCSR_ENCRYPT_TYPE_AES !=
10423 pHddStaCtx->conn_info.ucEncryptionType)) {
10424 /* If default key index is not same as previous one,
10425 * then update the default key index */
10426
10427 tCsrRoamSetKey setKey;
10428 uint32_t roamId = 0xFF;
10429 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10430
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010431 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010432
10433 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010434 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010435 setKey.keyId = key_index;
10436 setKey.keyLength = Keys->KeyLength[key_index];
10437
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010438 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010439 &Keys->KeyMaterial[key_index][0],
10440 Keys->KeyLength[key_index]);
10441
10442 setKey.keyDirection = eSIR_TX_RX;
10443
Anurag Chouhanc5548422016-02-24 18:33:27 +053010444 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010445 &pHddStaCtx->conn_info.bssId);
10446
10447 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10448 pWextState->roamProfile.EncryptionType.
10449 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10450 /* In the case of dynamic wep supplicant hardcodes DWEP type
10451 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10452 * WEP-40 encryption. In this canse the key length is 5 but the
10453 * encryption type is 104 hence checking the key langht(5) and
10454 * encryption type(104) and switching encryption type to 40*/
10455 pWextState->roamProfile.EncryptionType.
10456 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10457 pWextState->roamProfile.mcEncryptionType.
10458 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10459 }
10460
10461 setKey.encType =
10462 pWextState->roamProfile.EncryptionType.
10463 encryptionType[0];
10464
10465 /* Issue set key request */
10466 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10467 pAdapter->sessionId, &setKey,
10468 &roamId);
10469
10470 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010471 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010472 status);
10473 return -EINVAL;
10474 }
10475 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010476 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010477 /* In SoftAp mode setting key direction for default mode */
10478 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10479 pWextState->roamProfile.EncryptionType.encryptionType[0])
10480 && (eCSR_ENCRYPT_TYPE_AES !=
10481 pWextState->roamProfile.EncryptionType.
10482 encryptionType[0])) {
10483 /* Saving key direction for default key index to TX default */
10484 hdd_ap_ctx_t *pAPCtx =
10485 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10486 pAPCtx->wepKey[key_index].keyDirection =
10487 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010488 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010489 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010490 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010491 }
10492 }
10493
10494 EXIT();
10495 return status;
10496}
10497
10498static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10499 struct net_device *ndev,
10500 u8 key_index,
10501 bool unicast, bool multicast)
10502{
10503 int ret;
10504 cds_ssr_protect(__func__);
10505 ret =
10506 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10507 multicast);
10508 cds_ssr_unprotect(__func__);
10509
10510 return ret;
10511}
10512
Abhishek Singhc9941602016-08-09 16:06:22 +053010513/*
10514 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10515 * @wiphy: wiphy pointer
10516 * @channel: channel of the BSS
10517 * @bssid: Bssid of BSS
10518 * @ssid: Ssid of the BSS
10519 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010520 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010521 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010522 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010523#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010524static
Abhishek Singhc9941602016-08-09 16:06:22 +053010525struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10526 struct ieee80211_channel *channel, const u8 *bssid,
10527 const u8 *ssid, size_t ssid_len)
10528{
10529 return cfg80211_get_bss(wiphy, channel, bssid,
10530 ssid,
10531 ssid_len,
10532 WLAN_CAPABILITY_ESS,
10533 WLAN_CAPABILITY_ESS);
10534}
10535#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010536static
Abhishek Singhc9941602016-08-09 16:06:22 +053010537struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10538 struct ieee80211_channel *channel, const u8 *bssid,
10539 const u8 *ssid, size_t ssid_len)
10540{
10541 return cfg80211_get_bss(wiphy, channel, bssid,
10542 ssid,
10543 ssid_len,
10544 IEEE80211_BSS_TYPE_ESS,
10545 IEEE80211_PRIVACY_ANY);
10546}
10547#endif
10548
10549
10550/*
10551 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10552 * interface that BSS might have been lost.
10553 * @pAdapter: adaptor
10554 * @bssid: bssid which might have been lost
10555 *
10556 * Return: bss which is unlinked from kernel cache
10557 */
10558struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10559 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010560{
10561 struct net_device *dev = pAdapter->dev;
10562 struct wireless_dev *wdev = dev->ieee80211_ptr;
10563 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010564 struct cfg80211_bss *bss = NULL;
10565
Abhishek Singhc9941602016-08-09 16:06:22 +053010566 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10567 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010568 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010569 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010570 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010571 hdd_info("cfg80211_unlink_bss called for BSSID "
10572 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010573 cfg80211_unlink_bss(wiphy, bss);
10574 }
10575 return bss;
10576}
10577
Abhishek Singhc9941602016-08-09 16:06:22 +053010578
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010579/**
10580 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10581 * @pAdapter: Pointer to adapter
10582 * @bss_desc: Pointer to bss descriptor
10583 *
10584 * This function is used to inform the BSS details to nl80211 interface.
10585 *
10586 * Return: struct cfg80211_bss pointer
10587 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010588struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10589 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010590{
10591 /*
10592 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10593 * already exists in bss data base of cfg80211 for that particular BSS
10594 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10595 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10596 * As of now there is no possibility to get the mgmt(probe response)
10597 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10598 * and passing to cfg80211_inform_bss_frame.
10599 */
10600 struct net_device *dev = pAdapter->dev;
10601 struct wireless_dev *wdev = dev->ieee80211_ptr;
10602 struct wiphy *wiphy = wdev->wiphy;
10603 int chan_no = bss_desc->channelId;
10604#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10605 qcom_ie_age *qie_age = NULL;
10606 int ie_length =
10607 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10608#else
10609 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10610#endif
10611 const char *ie =
10612 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10613 unsigned int freq;
10614 struct ieee80211_channel *chan;
10615 struct ieee80211_mgmt *mgmt = NULL;
10616 struct cfg80211_bss *bss_status = NULL;
10617 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10618 int rssi = 0;
10619 hdd_context_t *pHddCtx;
10620 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010621 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010622 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010623
10624 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10625 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010626 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010627 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010628
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010629 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010630 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10631 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010632 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010633 return NULL;
10634 }
10635
10636 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10637
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010638 /* Android does not want the timestamp from the frame.
10639 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010640 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010641 mgmt->u.probe_resp.timestamp =
10642 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010643
10644 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10645 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10646
10647#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10648 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10649 /* Assuming this is the last IE, copy at the end */
10650 ie_length -= sizeof(qcom_ie_age);
10651 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10652 qie_age->element_id = QCOM_VENDOR_IE_ID;
10653 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10654 qie_age->oui_1 = QCOM_OUI1;
10655 qie_age->oui_2 = QCOM_OUI2;
10656 qie_age->oui_3 = QCOM_OUI3;
10657 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowrie2e3dfd2016-10-17 16:37:52 +053010658 /*
10659 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
10660 * all bss related timestamp is in units of ms. Due to this when scan
10661 * results are sent to lowi the scan age is high.To address this,
10662 * send age in units of 1/10 ms.
10663 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010664 qie_age->age =
Deepthi Gowrie2e3dfd2016-10-17 16:37:52 +053010665 (qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010666 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010667 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10668 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010669 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10670 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010671#endif
10672
10673 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10674 if (bss_desc->fProbeRsp) {
10675 mgmt->frame_control |=
10676 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10677 } else {
10678 mgmt->frame_control |=
10679 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10680 }
10681
10682 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
10683 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
10684 freq =
10685 ieee80211_channel_to_frequency(chan_no,
10686 IEEE80211_BAND_2GHZ);
10687 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
10688 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
10689 freq =
10690 ieee80211_channel_to_frequency(chan_no,
10691 IEEE80211_BAND_5GHZ);
10692 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010693 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010694 kfree(mgmt);
10695 return NULL;
10696 }
10697
10698 chan = __ieee80211_get_channel(wiphy, freq);
10699 /* When the band is changed on the fly using the GUI, three things are done
10700 * 1. scan abort
10701 * 2. flush scan results from cache
10702 * 3. update the band with the new band user specified (refer to the
10703 * hdd_set_band_helper function) as part of the scan abort, message will be
10704 * queued to PE and we proceed with flushing and changinh the band.
10705 * PE will stop the scanning further and report back the results what ever
10706 * it had till now by calling the call back function.
10707 * if the time between update band and scandone call back is sufficient
10708 * enough the band change reflects in SME, SME validates the channels
10709 * and discards the channels correponding to previous band and calls back
10710 * with zero bss results. but if the time between band update and scan done
10711 * callback is very small then band change will not reflect in SME and SME
10712 * reports to HDD all the channels correponding to previous band.this is due
10713 * to race condition.but those channels are invalid to the new band and so
10714 * this function __ieee80211_get_channel will return NULL.Each time we
10715 * report scan result with this pointer null warning kernel trace is printed.
10716 * if the scan results contain large number of APs continuosly kernel
10717 * warning trace is printed and it will lead to apps watch dog bark.
10718 * So drop the bss and continue to next bss.
10719 */
10720 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010721 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10722 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010723 kfree(mgmt);
10724 return NULL;
10725 }
10726
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010727 /* Based on .ini configuration, raw rssi can be reported for bss.
10728 * Raw rssi is typically used for estimating power.
10729 */
10730
10731 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10732 bss_desc->rssi;
10733
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010734 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010735 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010736
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010737 hdd_notice("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010738 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010739 (int)(rssi / 100),
10740 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010741
10742 bss_status =
10743 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10744 GFP_KERNEL);
10745 kfree(mgmt);
10746 return bss_status;
10747}
10748
10749/**
10750 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10751 * @pAdapter: Pointer to adapter
10752 * @pRoamInfo: Pointer to roam info
10753 *
10754 * This function is used to update the BSS data base of CFG8011
10755 *
10756 * Return: struct cfg80211_bss pointer
10757 */
10758struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10759 tCsrRoamInfo *pRoamInfo)
10760{
10761 tCsrRoamConnectedProfile roamProfile;
10762 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10763 struct cfg80211_bss *bss = NULL;
10764
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010765 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10766 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10767
10768 if (NULL != roamProfile.pBssDesc) {
10769 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10770 roamProfile.pBssDesc);
10771
10772 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010773 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010774
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010775 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010776 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010777 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010778 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010779 return bss;
10780}
10781/**
10782 * wlan_hdd_cfg80211_update_bss() - update bss
10783 * @wiphy: Pointer to wiphy
10784 * @pAdapter: Pointer to adapter
10785 * @scan_time: scan request timestamp
10786 *
10787 * Return: zero if success, non-zero otherwise
10788 */
10789int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10790 hdd_adapter_t *pAdapter,
10791 uint32_t scan_time)
10792{
10793 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10794 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010795 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010796 tScanResultHandle pResult;
10797 struct cfg80211_bss *bss_status = NULL;
10798 hdd_context_t *pHddCtx;
10799 int ret;
10800
10801 ENTER();
10802
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010803 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010804 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10805 NO_SESSION, pAdapter->sessionId));
10806
10807 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10808 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010809 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010810 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010811
10812 /* start getting scan results and populate cgf80211 BSS database */
10813 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
10814
10815 /* no scan results */
10816 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010817 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053010818 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010819 }
10820
10821 pScanResult = sme_scan_result_get_first(hHal, pResult);
10822
10823 while (pScanResult) {
10824 /*
10825 * - cfg80211_inform_bss() is not updating ie field of bss
10826 * entry if entry already exists in bss data base of cfg80211
10827 * for that particular BSS ID. Using cfg80211_inform_bss_frame
10828 * to update thebss entry instead of cfg80211_inform_bss,
10829 * But this call expects mgmt packet as input. As of now
10830 * there is no possibility to get the mgmt(probe response)
10831 * frame from PE, converting bss_desc to
10832 * ieee80211_mgmt(probe response) and passing to c
10833 * fg80211_inform_bss_frame.
10834 * - Update BSS only if beacon timestamp is later than
10835 * scan request timestamp.
10836 */
10837 if ((scan_time == 0) ||
10838 (scan_time <
Deepthi Gowrie2e3dfd2016-10-17 16:37:52 +053010839 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010840 bss_status =
10841 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10842 &pScanResult->BssDescriptor);
10843
10844 if (NULL == bss_status) {
10845 hdd_info("NULL returned by cfg80211_inform_bss_frame");
10846 } else {
10847 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010848 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010849 bss_status);
10850 }
10851 } else {
10852 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
10853 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
10854 }
10855 pScanResult = sme_scan_result_get_next(hHal, pResult);
10856 }
10857
10858 sme_scan_result_purge(hHal, pResult);
10859 /*
10860 * For SAP mode, scan is invoked by hostapd during SAP start
10861 * if hostapd is restarted, we need to flush previous scan
10862 * result so that it will reflect environment change
10863 */
Krunal Sonib4326f22016-03-10 13:05:51 -080010864 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010865#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
10866 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
10867#endif
10868 )
10869 sme_scan_flush_result(hHal);
10870
10871 EXIT();
10872 return 0;
10873}
10874
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010875/**
10876 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
10877 * @pAdapter: Pointer to adapter
10878 * @pRoamInfo: Pointer to roam info
10879 * @index: Index
10880 * @preauth: Preauth flag
10881 *
10882 * This function is used to notify the supplicant of a new PMKSA candidate.
10883 *
10884 * Return: 0 for success, non-zero for failure
10885 */
10886int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
10887 tCsrRoamInfo *pRoamInfo,
10888 int index, bool preauth)
10889{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010890 struct net_device *dev = pAdapter->dev;
10891 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
10892
10893 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010894 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010895
10896 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010897 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010898 return -EINVAL;
10899 }
10900
10901 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010902 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010903 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
10904 cfg80211_pmksa_candidate_notify(dev, index,
10905 pRoamInfo->bssid.bytes,
10906 preauth, GFP_KERNEL);
10907 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010908 return 0;
10909}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010910
10911#ifdef FEATURE_WLAN_LFR_METRICS
10912/**
10913 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
10914 * @pAdapter: Pointer to adapter
10915 * @pRoamInfo: Pointer to roam info
10916 *
10917 * 802.11r/LFR metrics reporting function to report preauth initiation
10918 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010919 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010920 */
10921#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010922QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010923 tCsrRoamInfo *pRoamInfo)
10924{
10925 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10926 union iwreq_data wrqu;
10927
10928 ENTER();
10929
10930 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010931 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010932 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010933 }
10934
10935 /* create the event */
10936 memset(&wrqu, 0, sizeof(wrqu));
10937 memset(metrics_notification, 0, sizeof(metrics_notification));
10938
10939 wrqu.data.pointer = metrics_notification;
10940 wrqu.data.length = scnprintf(metrics_notification,
10941 sizeof(metrics_notification),
10942 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
10943 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10944
10945 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10946 metrics_notification);
10947
10948 EXIT();
10949
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010950 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010951}
10952
10953/**
10954 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10955 * @pAdapter: Pointer to adapter
10956 * @pRoamInfo: Pointer to roam info
10957 * @preauth_status: Preauth status
10958 *
10959 * 802.11r/LFR metrics reporting function to report handover initiation
10960 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010961 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010962 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010963QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010964wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
10965 tCsrRoamInfo *pRoamInfo,
10966 bool preauth_status)
10967{
10968 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10969 union iwreq_data wrqu;
10970
10971 ENTER();
10972
10973 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010974 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010975 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010976 }
10977
10978 /* create the event */
10979 memset(&wrqu, 0, sizeof(wrqu));
10980 memset(metrics_notification, 0, sizeof(metrics_notification));
10981
10982 scnprintf(metrics_notification, sizeof(metrics_notification),
10983 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
10984 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10985
10986 if (1 == preauth_status)
10987 strlcat(metrics_notification, " true",
10988 sizeof(metrics_notification));
10989 else
10990 strlcat(metrics_notification, " false",
10991 sizeof(metrics_notification));
10992
10993 wrqu.data.pointer = metrics_notification;
10994 wrqu.data.length = strlen(metrics_notification);
10995
10996 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10997 metrics_notification);
10998
10999 EXIT();
11000
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011001 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002}
11003
11004/**
11005 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11006 * @pAdapter: Pointer to adapter
11007 * @pRoamInfo: Pointer to roam info
11008 *
11009 * 802.11r/LFR metrics reporting function to report handover initiation
11010 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011011 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011012 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011013QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011014 tCsrRoamInfo *pRoamInfo)
11015{
11016 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11017 union iwreq_data wrqu;
11018
11019 ENTER();
11020
11021 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011022 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011023 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011024 }
11025
11026 /* create the event */
11027 memset(&wrqu, 0, sizeof(wrqu));
11028 memset(metrics_notification, 0, sizeof(metrics_notification));
11029
11030 wrqu.data.pointer = metrics_notification;
11031 wrqu.data.length = scnprintf(metrics_notification,
11032 sizeof(metrics_notification),
11033 "QCOM: LFR_PREAUTH_HANDOVER "
11034 MAC_ADDRESS_STR,
11035 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11036
11037 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11038 metrics_notification);
11039
11040 EXIT();
11041
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011042 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011043}
11044#endif
11045
11046/**
11047 * hdd_select_cbmode() - select channel bonding mode
11048 * @pAdapter: Pointer to adapter
11049 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011050 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011051 *
11052 * Return: none
11053 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011054void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11055 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011056{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011057 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011058 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011059 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011060
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011061 /*
11062 * CDS api expects secondary channel for calculating
11063 * the channel params
11064 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011065 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011066 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11067 if (operationChannel >= 1 && operationChannel <= 5)
11068 sec_ch = operationChannel + 4;
11069 else if (operationChannel >= 6 && operationChannel <= 13)
11070 sec_ch = operationChannel - 4;
11071 }
11072
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011073 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011074 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011075
11076 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011077 eHddDot11Mode hdd_dot11_mode;
11078 uint8_t iniDot11Mode =
11079 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11080
11081 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11082 switch (iniDot11Mode) {
11083 case eHDD_DOT11_MODE_AUTO:
11084 case eHDD_DOT11_MODE_11ac:
11085 case eHDD_DOT11_MODE_11ac_ONLY:
11086 if (sme_is_feature_supported_by_fw(DOT11AC))
11087 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11088 else
11089 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11090 break;
11091 case eHDD_DOT11_MODE_11n:
11092 case eHDD_DOT11_MODE_11n_ONLY:
11093 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11094 break;
11095 default:
11096 hdd_dot11_mode = iniDot11Mode;
11097 break;
11098 }
11099 ch_info->channel_width = ch_params->ch_width;
11100 ch_info->phy_mode =
11101 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011102 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011103 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011104 hdd_info("ch_info width %d, phymode %d channel %d",
11105 ch_info->channel_width, ch_info->phy_mode,
11106 ch_info->channel);
11107 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011108}
11109
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011110/**
11111 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11112 * @adapter: STA adapter
11113 * @roam_profile: STA roam profile
11114 *
11115 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11116 *
11117 * Return: false if sta-sap conc is not allowed, else return true
11118 */
11119static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11120 tCsrRoamProfile *roam_profile)
11121{
11122 hdd_context_t *hdd_ctx;
11123 hdd_adapter_t *ap_adapter;
11124 hdd_ap_ctx_t *hdd_ap_ctx;
11125 hdd_hostapd_state_t *hostapd_state;
11126 uint8_t channel = 0;
11127 QDF_STATUS status;
11128
11129 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11130 if (!hdd_ctx) {
11131 hdd_err("HDD context is NULL");
11132 return true;
11133 }
11134
11135 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11136 /* probably no sap running, no handling required */
11137 if (ap_adapter == NULL)
11138 return true;
11139
11140 /*
11141 * sap is not in started state, so it is fine to go ahead with sta.
11142 * if sap is currently doing CAC then don't allow sta to go further.
11143 */
11144 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11145 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11146 return true;
11147
11148 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11149 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11150 return false;
11151 }
11152
11153 /*
11154 * log and return error, if we allow STA to go through, we don't
11155 * know what is going to happen better stop sta connection
11156 */
11157 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11158 if (NULL == hdd_ap_ctx) {
11159 hdd_err("AP context not found");
11160 return false;
11161 }
11162
11163 /* sap is on non-dfs channel, nothing to handle */
11164 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11165 hdd_info("sap is on non-dfs channel, sta is allowed");
11166 return true;
11167 }
11168 /*
11169 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011170 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011171 */
11172 status = cds_get_channel_from_scan_result(adapter,
11173 roam_profile, &channel);
11174
Nitesh Shah59774522016-09-16 15:14:21 +053011175 /*
11176 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11177 * channels for roaming case.
11178 */
11179 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11180 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11181 return true;
11182 }
11183
11184 /*
11185 * If channel is 0 or DFS then better to call pcl and find out the
11186 * best channel. If channel is non-dfs 5 GHz then better move SAP
11187 * to STA's channel to make scc, so we have room for 3port MCC
11188 * scenario.
11189 */
11190 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011191 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11192 true);
11193
11194 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11195 qdf_event_reset(&hostapd_state->qdf_event);
11196 status = wlansap_set_channel_change_with_csa(
11197 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11198 hdd_ap_ctx->sapConfig.ch_width_orig);
11199
11200 if (QDF_STATUS_SUCCESS != status) {
11201 hdd_err("Set channel with CSA IE failed, can't allow STA");
11202 return false;
11203 }
11204
11205 /*
11206 * wait here for SAP to finish the channel switch. When channel
11207 * switch happens, SAP sends few beacons with CSA_IE. After
11208 * successfully Transmission of those beacons, it will move its
11209 * state from started to disconnected and move to new channel.
11210 * once it moves to new channel, sap again moves its state
11211 * machine from disconnected to started and set this event.
11212 * wait for 10 secs to finish this.
11213 */
11214 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11215 if (!QDF_IS_STATUS_SUCCESS(status)) {
11216 hdd_err("wait for qdf_event failed, STA not allowed!!");
11217 return false;
11218 }
11219
11220 return true;
11221}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011222
Krunal Soni31949422016-07-29 17:17:53 -070011223/**
11224 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011225 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011226 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011227 * @ssid_len: Length of ssid
11228 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011229 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011230 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011231 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011232 *
11233 * This function is used to start the association process
11234 *
11235 * Return: 0 for success, non-zero for failure
11236 */
Krunal Soni31949422016-07-29 17:17:53 -070011237static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011239 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011240 u8 operatingChannel,
11241 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011242{
11243 int status = 0;
11244 hdd_wext_state_t *pWextState;
11245 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011246 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011247 uint32_t roamId;
11248 tCsrRoamProfile *pRoamProfile;
11249 eCsrAuthType RSNAuthType;
11250 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011251 uint8_t channel = 0;
11252 struct sir_hw_mode_params hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011253
11254 ENTER();
11255
11256 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11257 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011258 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011259
11260 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011261 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011262 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011263
11264 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011265 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011266 return -EINVAL;
11267 }
11268
11269 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011270 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11271 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011272
11273 if (pRoamProfile) {
11274 hdd_station_ctx_t *pHddStaCtx;
11275 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11276
11277 if (HDD_WMM_USER_MODE_NO_QOS ==
11278 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11279 /*QoS not enabled in cfg file */
11280 pRoamProfile->uapsd_mask = 0;
11281 } else {
11282 /*QoS enabled, update uapsd mask from cfg file */
11283 pRoamProfile->uapsd_mask =
11284 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11285 }
11286
11287 pRoamProfile->SSIDs.numOfSSIDs = 1;
11288 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011289 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011290 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011291 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011292 ssid, ssid_len);
11293
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011294 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011295 if (bssid) {
11296 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011297 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011298 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011299 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011300 /*
11301 * Save BSSID in seperate variable as
11302 * pRoamProfile's BSSID is getting zeroed out in the
11303 * association process. In case of join failure
11304 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011305 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011306 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011307 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011308 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011309 } else if (bssid_hint) {
11310 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011311 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011312 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011313 /*
11314 * Save BSSID in a separate variable as
11315 * pRoamProfile's BSSID is getting zeroed out in the
11316 * association process. In case of join failure
11317 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011318 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011319 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011320 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011321 hdd_info("bssid_hint is given by upper layer %pM",
11322 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011323 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011324 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011325 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011326 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011327 }
11328
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011329 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011330 pRoamProfile->SSIDs.SSIDList->SSID.length,
11331 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11332 operatingChannel);
11333
11334 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11335 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011336 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011337 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11338 }
11339#ifdef FEATURE_WLAN_WAPI
11340 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011341 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011342 switch (pAdapter->wapi_info.wapiAuthMode) {
11343 case WAPI_AUTH_MODE_PSK:
11344 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011345 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011346 pAdapter->wapi_info.wapiAuthMode);
11347 pRoamProfile->AuthType.authType[0] =
11348 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11349 break;
11350 }
11351 case WAPI_AUTH_MODE_CERT:
11352 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011353 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011354 pAdapter->wapi_info.wapiAuthMode);
11355 pRoamProfile->AuthType.authType[0] =
11356 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11357 break;
11358 }
11359 } /* End of switch */
11360 if (pAdapter->wapi_info.wapiAuthMode ==
11361 WAPI_AUTH_MODE_PSK
11362 || pAdapter->wapi_info.wapiAuthMode ==
11363 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011364 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011365 pRoamProfile->AuthType.numEntries = 1;
11366 pRoamProfile->EncryptionType.numEntries = 1;
11367 pRoamProfile->EncryptionType.encryptionType[0] =
11368 eCSR_ENCRYPT_TYPE_WPI;
11369 pRoamProfile->mcEncryptionType.numEntries = 1;
11370 pRoamProfile->mcEncryptionType.
11371 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11372 }
11373 }
Krunal Soni31949422016-07-29 17:17:53 -070011374#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011375#ifdef WLAN_FEATURE_GTK_OFFLOAD
11376 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011377 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11378 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011379 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11380 sizeof(tSirGtkOffloadParams));
11381 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11382 GTK_OFFLOAD_DISABLE;
11383 }
11384#endif
11385 pRoamProfile->csrPersona = pAdapter->device_mode;
11386
11387 if (operatingChannel) {
11388 pRoamProfile->ChannelInfo.ChannelList =
11389 &operatingChannel;
11390 pRoamProfile->ChannelInfo.numOfChannels = 1;
11391 } else {
11392 pRoamProfile->ChannelInfo.ChannelList = NULL;
11393 pRoamProfile->ChannelInfo.numOfChannels = 0;
11394 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011395 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011396 && operatingChannel) {
11397 /*
11398 * Need to post the IBSS power save parameters
11399 * to WMA. WMA will configure this parameters
11400 * to firmware if power save is enabled by the
11401 * firmware.
11402 */
11403 status = hdd_set_ibss_power_save_params(pAdapter);
11404
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011405 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011406 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011407 return -EINVAL;
11408 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011409 pRoamProfile->ch_params.ch_width =
11410 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011411 /*
11412 * In IBSS mode while operating in 2.4 GHz,
11413 * the device supports only 20 MHz.
11414 */
11415 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11416 pRoamProfile->ch_params.ch_width =
11417 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011418 hdd_select_cbmode(pAdapter, operatingChannel,
11419 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011420 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011421 /*
11422 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11423 * or pmf=2 is an explicit configuration in the supplicant
11424 * configuration, drop the connection request.
11425 */
11426 if (pWextState->roamProfile.MFPEnabled &&
11427 !(pWextState->roamProfile.MFPRequired ||
11428 pWextState->roamProfile.MFPCapable)) {
11429 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11430 pWextState->roamProfile.MFPEnabled,
11431 pWextState->roamProfile.MFPRequired,
11432 pWextState->roamProfile.MFPCapable);
11433 return -EINVAL;
11434 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011435
Krunal Soni3091bcc2016-06-23 12:28:21 -070011436 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011437 hdd_err("Connection refused: conn in progress");
11438 return -EINVAL;
11439 }
11440
Krunal Soni31949422016-07-29 17:17:53 -070011441 /*
11442 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011443 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011444 * enhancements, the supplicant is not issuing the scan command
11445 * now. So the unicast frames which are sent from the host are
11446 * not having the additional IEs. If it is P2P CLIENT and there
11447 * is no additional IE present in roamProfile, then use the
11448 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011449 */
11450
Krunal Sonib4326f22016-03-10 13:05:51 -080011451 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011452 (!pRoamProfile->pAddIEScan)) {
11453 pRoamProfile->pAddIEScan =
11454 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11455 pRoamProfile->nAddIEScanLength =
11456 pAdapter->scan_info.scanAddIE.length;
11457 }
11458 /*
11459 * When policy manager is enabled from ini file, we shouldn't
11460 * check for other concurrency rules.
11461 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011462 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011463 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011464 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011465 pAdapter, pRoamProfile, &roamId))
11466 return 0;
11467 }
11468
Krunal Soni3091bcc2016-06-23 12:28:21 -070011469 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011470 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11471 pRoamProfile))) {
11472 hdd_err("sap-sta conc will fail, can't allow sta");
11473 hdd_conn_set_connection_state(pAdapter,
11474 eConnectionState_NotConnected);
11475 return -ENOMEM;
11476 }
11477
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011478 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011479 if (!sme_config) {
11480 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011481 hdd_conn_set_connection_state(pAdapter,
11482 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011483 return -ENOMEM;
11484 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011485 qdf_mem_zero(sme_config, sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011486 sme_get_config_param(pHddCtx->hHal, sme_config);
11487 /* These values are not sessionized. So, any change in these SME
11488 * configs on an older or parallel interface will affect the
11489 * cb mode. So, restoring the default INI params before starting
11490 * interfaces such as sta, cli etc.,
11491 */
11492 sme_config->csrConfig.channelBondingMode5GHz =
11493 pHddCtx->config->nChannelBondingMode5GHz;
11494 sme_config->csrConfig.channelBondingMode24GHz =
11495 pHddCtx->config->nChannelBondingMode24GHz;
11496 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011497 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011498 /*
11499 * Change conn_state to connecting before sme_roam_connect(),
11500 * because sme_roam_connect() has a direct path to call
11501 * hdd_sme_roam_callback(), which will change the conn_state
11502 * If direct path, conn_state will be accordingly changed to
11503 * NotConnected or Associated by either
11504 * hdd_association_completion_handler() or
11505 * hdd_dis_connect_handler() in sme_RoamCallback()if
11506 * sme_RomConnect is to be queued,
11507 * Connecting state will remain until it is completed.
11508 *
11509 * If connection state is not changed, connection state will
11510 * remain in eConnectionState_NotConnected state.
11511 * In hdd_association_completion_handler, "hddDisconInProgress"
11512 * is set to true if conn state is
11513 * eConnectionState_NotConnected.
11514 * If "hddDisconInProgress" is set to true then cfg80211 layer
11515 * is not informed of connect result indication which
11516 * is an issue.
11517 */
11518 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011519 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011520 hdd_conn_set_connection_state(pAdapter,
11521 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011522
Komal Seelama89be8d2016-09-29 11:09:26 +053011523 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
11524 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011525 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11526 pAdapter->sessionId, pRoamProfile,
11527 &roamId);
11528
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011529 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011530 (QDF_STA_MODE == pAdapter->device_mode ||
11531 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011532 hdd_err("sme_roam_connect (session %d) failed with "
11533 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011534 pAdapter->sessionId, status);
11535 /* change back to NotAssociated */
11536 hdd_conn_set_connection_state(pAdapter,
11537 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053011538 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
11539 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011540 }
11541
11542 pRoamProfile->ChannelInfo.ChannelList = NULL;
11543 pRoamProfile->ChannelInfo.numOfChannels = 0;
11544
Nitesh Shah044fd672016-10-13 18:53:25 +053011545 if (!QDF_IS_STATUS_SUCCESS(
11546 wma_get_current_hw_mode(&hw_mode))) {
11547 hdd_err("wma_get_current_hw_mode failed");
11548 return status;
11549 }
11550
11551 if ((QDF_STA_MODE == pAdapter->device_mode)
11552 && hw_mode.dbs_cap) {
11553 cds_get_channel_from_scan_result(pAdapter,
11554 pRoamProfile, &channel);
11555 if (channel)
11556 cds_checkn_update_hw_mode_single_mac_mode
11557 (channel);
11558 }
11559
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011560 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011561 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011562 return -EINVAL;
11563 }
11564 EXIT();
11565 return status;
11566}
11567
11568/**
11569 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11570 * @pAdapter: Pointer to adapter
11571 * @auth_type: Auth type
11572 *
11573 * This function is used to set the authentication type (OPEN/SHARED).
11574 *
11575 * Return: 0 for success, non-zero for failure
11576 */
11577static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11578 enum nl80211_auth_type auth_type)
11579{
11580 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11581 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11582
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011583 /*set authentication type */
11584 switch (auth_type) {
11585 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011586 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11588 break;
11589
11590 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011591 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011592 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011593 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11594 break;
11595
11596 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011597 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011598 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11599 break;
11600#ifdef FEATURE_WLAN_ESE
11601 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011602 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011603 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11604 break;
11605#endif
11606
11607 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011608 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011609 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11610 return -EINVAL;
11611 }
11612
11613 pWextState->roamProfile.AuthType.authType[0] =
11614 pHddStaCtx->conn_info.authType;
11615 return 0;
11616}
11617
11618/**
11619 * wlan_hdd_set_akm_suite() - set key management type
11620 * @pAdapter: Pointer to adapter
11621 * @key_mgmt: Key management type
11622 *
11623 * This function is used to set the key mgmt type(PSK/8021x).
11624 *
11625 * Return: 0 for success, non-zero for failure
11626 */
11627static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11628{
11629 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11630
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011631#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11632#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11633 /*set key mgmt type */
11634 switch (key_mgmt) {
11635 case WLAN_AKM_SUITE_PSK:
11636 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011637 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011638 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011639 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11640 break;
11641
11642 case WLAN_AKM_SUITE_8021X_SHA256:
11643 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011644 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011645 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011646 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11647 break;
11648#ifdef FEATURE_WLAN_ESE
11649#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11650#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11651 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011652 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011653 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11654 break;
11655#endif
11656#ifndef WLAN_AKM_SUITE_OSEN
11657#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11658#endif
11659 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011660 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011661 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11662 break;
11663
11664 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011665 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011666 return -EINVAL;
11667
11668 }
11669 return 0;
11670}
11671
11672/**
11673 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11674 * @pAdapter: Pointer to adapter
11675 * @cipher: Cipher type
11676 * @ucast: Unicast flag
11677 *
11678 * This function is used to set the encryption type
11679 * (NONE/WEP40/WEP104/TKIP/CCMP).
11680 *
11681 * Return: 0 for success, non-zero for failure
11682 */
11683static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11684 u32 cipher, bool ucast)
11685{
11686 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11687 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11688 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11689
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011690 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011691 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011692 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11693 } else {
11694
11695 /*set encryption method */
11696 switch (cipher) {
11697 case IW_AUTH_CIPHER_NONE:
11698 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11699 break;
11700
11701 case WLAN_CIPHER_SUITE_WEP40:
11702 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11703 break;
11704
11705 case WLAN_CIPHER_SUITE_WEP104:
11706 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11707 break;
11708
11709 case WLAN_CIPHER_SUITE_TKIP:
11710 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11711 break;
11712
11713 case WLAN_CIPHER_SUITE_CCMP:
11714 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11715 break;
11716#ifdef FEATURE_WLAN_WAPI
11717 case WLAN_CIPHER_SUITE_SMS4:
11718 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11719 break;
11720#endif
11721
11722#ifdef FEATURE_WLAN_ESE
11723 case WLAN_CIPHER_SUITE_KRK:
11724 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11725 break;
11726#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11727 case WLAN_CIPHER_SUITE_BTK:
11728 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11729 break;
11730#endif
11731#endif
11732 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011733 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011734 return -EOPNOTSUPP;
11735 }
11736 }
11737
11738 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011739 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011740 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11741 pWextState->roamProfile.EncryptionType.numEntries = 1;
11742 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11743 encryptionType;
11744 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011745 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011746 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11747 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11748 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11749 encryptionType;
11750 }
11751
11752 return 0;
11753}
11754
11755/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011756 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11757 * @wext_state: Pointer to wext state
11758 * @gen_ie: Pointer to IE data
11759 * @len: length of IE data
11760 *
11761 * Return: 0 for success, non-zero for failure
11762 */
11763static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11764 const uint8_t *gen_ie, uint16_t len)
11765{
11766 uint16_t cur_add_ie_len =
11767 wext_state->assocAddIE.length;
11768
11769 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11770 (wext_state->assocAddIE.length + len)) {
11771 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11772 QDF_ASSERT(0);
11773 return -ENOMEM;
11774 }
11775 memcpy(wext_state->assocAddIE.addIEdata +
11776 cur_add_ie_len, gen_ie, len);
11777 wext_state->assocAddIE.length += len;
11778
11779 wext_state->roamProfile.pAddIEAssoc =
11780 wext_state->assocAddIE.addIEdata;
11781 wext_state->roamProfile.nAddIEAssocLength =
11782 wext_state->assocAddIE.length;
11783 return 0;
11784}
11785
11786/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011787 * wlan_hdd_cfg80211_set_ie() - set IEs
11788 * @pAdapter: Pointer to adapter
11789 * @ie: Pointer ot ie
11790 * @ie: IE length
11791 *
11792 * Return: 0 for success, non-zero for failure
11793 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011794static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011795 size_t ie_len)
11796{
11797 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11798 const uint8_t *genie = ie;
11799 uint16_t remLen = ie_len;
11800#ifdef FEATURE_WLAN_WAPI
11801 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
11802 u16 *tmp;
11803 uint16_t akmsuiteCount;
11804 int *akmlist;
11805#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011806 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011807
11808 /* clear previous assocAddIE */
11809 pWextState->assocAddIE.length = 0;
11810 pWextState->roamProfile.bWPSAssociation = false;
11811 pWextState->roamProfile.bOSENAssociation = false;
11812
11813 while (remLen >= 2) {
11814 uint16_t eLen = 0;
11815 uint8_t elementId;
11816 elementId = *genie++;
11817 eLen = *genie++;
11818 remLen -= 2;
11819
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011820 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011821
11822 switch (elementId) {
11823 case DOT11F_EID_WPA:
11824 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 -070011825 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011826 return -EINVAL;
11827 } else if (0 ==
11828 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
11829 uint16_t curAddIELen =
11830 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011831 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011832
11833 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11834 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011835 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011836 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011837 return -ENOMEM;
11838 }
11839 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11840 memcpy(pWextState->assocAddIE.addIEdata +
11841 curAddIELen, genie - 2, eLen + 2);
11842 pWextState->assocAddIE.length += eLen + 2;
11843
11844 pWextState->roamProfile.bWPSAssociation = true;
11845 pWextState->roamProfile.pAddIEAssoc =
11846 pWextState->assocAddIE.addIEdata;
11847 pWextState->roamProfile.nAddIEAssocLength =
11848 pWextState->assocAddIE.length;
11849 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011850 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011851 memset(pWextState->WPARSNIE, 0,
11852 MAX_WPA_RSN_IE_LEN);
11853 memcpy(pWextState->WPARSNIE, genie - 2,
11854 (eLen + 2));
11855 pWextState->roamProfile.pWPAReqIE =
11856 pWextState->WPARSNIE;
11857 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
11858 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
11859 P2P_OUI_TYPE_SIZE))) {
11860 uint16_t curAddIELen =
11861 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011862 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011863
11864 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11865 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011866 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011867 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011868 return -ENOMEM;
11869 }
11870 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11871 memcpy(pWextState->assocAddIE.addIEdata +
11872 curAddIELen, genie - 2, eLen + 2);
11873 pWextState->assocAddIE.length += eLen + 2;
11874
11875 pWextState->roamProfile.pAddIEAssoc =
11876 pWextState->assocAddIE.addIEdata;
11877 pWextState->roamProfile.nAddIEAssocLength =
11878 pWextState->assocAddIE.length;
11879 }
11880#ifdef WLAN_FEATURE_WFD
11881 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
11882 WFD_OUI_TYPE_SIZE)) &&
11883 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080011884 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011885 pAdapter->device_mode)) {
11886 uint16_t curAddIELen =
11887 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011888 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011889
11890 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11891 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011892 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011893 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011894 return -ENOMEM;
11895 }
11896 /* WFD IE is saved to Additional IE ; it should
11897 * be accumulated to handle WPS IE + P2P IE +
11898 * WFD IE */
11899 memcpy(pWextState->assocAddIE.addIEdata +
11900 curAddIELen, genie - 2, eLen + 2);
11901 pWextState->assocAddIE.length += eLen + 2;
11902
11903 pWextState->roamProfile.pAddIEAssoc =
11904 pWextState->assocAddIE.addIEdata;
11905 pWextState->roamProfile.nAddIEAssocLength =
11906 pWextState->assocAddIE.length;
11907 }
11908#endif
11909 /* Appending HS 2.0 Indication Element in Assiciation Request */
11910 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
11911 HS20_OUI_TYPE_SIZE))) {
11912 uint16_t curAddIELen =
11913 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011914 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011915
11916 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11917 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011918 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011919 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011920 return -ENOMEM;
11921 }
11922 memcpy(pWextState->assocAddIE.addIEdata +
11923 curAddIELen, genie - 2, eLen + 2);
11924 pWextState->assocAddIE.length += eLen + 2;
11925
11926 pWextState->roamProfile.pAddIEAssoc =
11927 pWextState->assocAddIE.addIEdata;
11928 pWextState->roamProfile.nAddIEAssocLength =
11929 pWextState->assocAddIE.length;
11930 }
11931 /* Appending OSEN Information Element in Assiciation Request */
11932 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
11933 OSEN_OUI_TYPE_SIZE))) {
11934 uint16_t curAddIELen =
11935 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011936 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011937
11938 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11939 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011940 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011941 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011942 return -ENOMEM;
11943 }
11944 memcpy(pWextState->assocAddIE.addIEdata +
11945 curAddIELen, genie - 2, eLen + 2);
11946 pWextState->assocAddIE.length += eLen + 2;
11947
11948 pWextState->roamProfile.bOSENAssociation = true;
11949 pWextState->roamProfile.pAddIEAssoc =
11950 pWextState->assocAddIE.addIEdata;
11951 pWextState->roamProfile.nAddIEAssocLength =
11952 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011953 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
11954 MBO_OUI_TYPE_SIZE))){
11955 hdd_info("Set MBO IE(len %d)", eLen + 2);
11956 status = wlan_hdd_add_assoc_ie(pWextState,
11957 genie - 2, eLen + 2);
11958 if (status)
11959 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011960 } else {
11961 uint16_t add_ie_len =
11962 pWextState->assocAddIE.length;
11963
11964 hdd_info("Set OSEN IE(len %d)", eLen + 2);
11965
11966 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11967 (pWextState->assocAddIE.length + eLen)) {
11968 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011969 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011970 return -ENOMEM;
11971 }
11972
11973 memcpy(pWextState->assocAddIE.addIEdata +
11974 add_ie_len, genie - 2, eLen + 2);
11975 pWextState->assocAddIE.length += eLen + 2;
11976
11977 pWextState->roamProfile.pAddIEAssoc =
11978 pWextState->assocAddIE.addIEdata;
11979 pWextState->roamProfile.nAddIEAssocLength =
11980 pWextState->assocAddIE.length;
11981 }
11982 break;
11983 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011984 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011985 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
11986 memcpy(pWextState->WPARSNIE, genie - 2,
11987 (eLen + 2));
11988 pWextState->roamProfile.pRSNReqIE =
11989 pWextState->WPARSNIE;
11990 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
11991 break;
11992 /*
11993 * Appending Extended Capabilities with Interworking bit set
11994 * in Assoc Req.
11995 *
11996 * In assoc req this EXT Cap will only be taken into account if
11997 * interworkingService bit is set to 1. Currently
11998 * driver is only interested in interworkingService capability
11999 * from supplicant. If in future any other EXT Cap info is
12000 * required from supplicat, it needs to be handled while
12001 * sending Assoc Req in LIM.
12002 */
12003 case DOT11F_EID_EXTCAP:
12004 {
12005 uint16_t curAddIELen =
12006 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012007 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012008
12009 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12010 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012011 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012012 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012013 return -ENOMEM;
12014 }
12015 memcpy(pWextState->assocAddIE.addIEdata +
12016 curAddIELen, genie - 2, eLen + 2);
12017 pWextState->assocAddIE.length += eLen + 2;
12018
12019 pWextState->roamProfile.pAddIEAssoc =
12020 pWextState->assocAddIE.addIEdata;
12021 pWextState->roamProfile.nAddIEAssocLength =
12022 pWextState->assocAddIE.length;
12023 break;
12024 }
12025#ifdef FEATURE_WLAN_WAPI
12026 case WLAN_EID_WAPI:
12027 /* Setting WAPI Mode to ON=1 */
12028 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012029 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012030 tmp = (u16 *) ie;
12031 tmp = tmp + 2; /* Skip element Id and Len, Version */
12032 akmsuiteCount = WPA_GET_LE16(tmp);
12033 tmp = tmp + 1;
12034 akmlist = (int *)(tmp);
12035 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12036 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12037 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012038 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012039 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012040 return -EINVAL;
12041 }
12042
12043 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012044 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012045 pAdapter->wapi_info.wapiAuthMode =
12046 WAPI_AUTH_MODE_PSK;
12047 }
12048 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012049 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012050 pAdapter->wapi_info.wapiAuthMode =
12051 WAPI_AUTH_MODE_CERT;
12052 }
12053 break;
12054#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012055 case DOT11F_EID_SUPPOPERATINGCLASSES:
12056 {
12057 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12058 status = wlan_hdd_add_assoc_ie(pWextState,
12059 genie - 2, eLen + 2);
12060 if (status)
12061 return status;
12062 break;
12063 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012064 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012065 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012066 /* when Unknown IE is received we should break and continue
12067 * to the next IE in the buffer instead we were returning
12068 * so changing this to break */
12069 break;
12070 }
12071 genie += eLen;
12072 remLen -= eLen;
12073 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012074 return 0;
12075}
12076
12077/**
12078 * hdd_is_wpaie_present() - check for WPA ie
12079 * @ie: Pointer to ie
12080 * @ie_len: Ie length
12081 *
12082 * Parse the received IE to find the WPA IE
12083 *
12084 * Return: true if wpa ie is found else false
12085 */
12086static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12087{
12088 uint8_t eLen = 0;
12089 uint16_t remLen = ie_len;
12090 uint8_t elementId = 0;
12091
12092 while (remLen >= 2) {
12093 elementId = *ie++;
12094 eLen = *ie++;
12095 remLen -= 2;
12096 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012097 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012098 return false;
12099 }
12100 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12101 /* OUI - 0x00 0X50 0XF2
12102 * WPA Information Element - 0x01
12103 * WPA version - 0x01
12104 */
12105 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12106 return true;
12107 }
12108 ie += eLen;
12109 remLen -= eLen;
12110 }
12111 return false;
12112}
12113
12114/**
12115 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12116 * @pAdapter: Pointer to adapter
12117 * @req: Pointer to security parameters
12118 *
12119 * Return: 0 for success, non-zero for failure
12120 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012121static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12122 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012123{
12124 int status = 0;
12125 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12126 ENTER();
12127
12128 /*set wpa version */
12129 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12130
12131 if (req->crypto.wpa_versions) {
12132 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12133 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12134 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12135 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12136 }
12137 }
12138
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012139 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012140
12141 /*set authentication type */
12142 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12143
12144 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012145 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012146 return status;
12147 }
12148
12149 /*set key mgmt type */
12150 if (req->crypto.n_akm_suites) {
12151 status =
12152 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12153 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012154 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012155 return status;
12156 }
12157 }
12158
12159 /*set pairwise cipher type */
12160 if (req->crypto.n_ciphers_pairwise) {
12161 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12162 req->crypto.
12163 ciphers_pairwise[0],
12164 true);
12165 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012166 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012167 return status;
12168 }
12169 } else {
12170 /*Reset previous cipher suite to none */
12171 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12172 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012173 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 return status;
12175 }
12176 }
12177
12178 /*set group cipher type */
12179 status =
12180 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12181 false);
12182
12183 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012184 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012185 return status;
12186 }
12187#ifdef WLAN_FEATURE_11W
12188 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12189#endif
12190
12191 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12192 if (req->ie_len) {
12193 status =
12194 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12195 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012196 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012197 return status;
12198 }
12199 }
12200
12201 /*incase of WEP set default key information */
12202 if (req->key && req->key_len) {
12203 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12204 || (WLAN_CIPHER_SUITE_WEP104 ==
12205 req->crypto.ciphers_pairwise[0])
12206 ) {
12207 if (IW_AUTH_KEY_MGMT_802_1X
12208 ==
12209 (pWextState->
12210 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012211 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012212 return -EOPNOTSUPP;
12213 } else {
12214 u8 key_len = req->key_len;
12215 u8 key_idx = req->key_idx;
12216
12217 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12218 key_len)
12219 && (CSR_MAX_NUM_KEY > key_idx)
12220 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012221 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012222 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012223 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012224 Keys.
12225 KeyMaterial[key_idx][0],
12226 req->key, key_len);
12227 pWextState->roamProfile.Keys.
12228 KeyLength[key_idx] = (u8) key_len;
12229 pWextState->roamProfile.Keys.
12230 defaultIndex = (u8) key_idx;
12231 }
12232 }
12233 }
12234 }
12235
12236 return status;
12237}
12238
12239/**
12240 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12241 * @pAdapter: Pointer to adapter
12242 *
12243 * This function is used to disconnect from previous connection
12244 *
12245 * Return: 0 for success, non-zero for failure
12246 */
12247static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12248{
12249 unsigned long rc;
12250 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012251 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012252
12253 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12254
Jeff Johnson9edf9572016-10-03 15:24:49 -070012255 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012256 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12257 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12258 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012259 hdd_conn_set_connection_state(pAdapter,
12260 eConnectionState_Disconnecting);
12261 /* Issue disconnect to CSR */
12262 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012263
12264 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12265 pAdapter->sessionId,
12266 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12267 /*
12268 * Wait here instead of returning directly, this will block the
12269 * next connect command and allow processing of the scan for
12270 * ssid and the previous connect command in CSR. Else we might
12271 * hit some race conditions leading to SME and HDD out of sync.
12272 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012273 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012274 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12275 } else if (0 != status) {
12276 hdd_err("csrRoamDisconnect failure, returned %d",
12277 (int)status);
12278 pHddStaCtx->staDebugState = status;
12279 result = -EINVAL;
12280 goto disconnected;
12281 }
12282
12283 rc = wait_for_completion_timeout(
12284 &pAdapter->disconnect_comp_var,
12285 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012286 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012287 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12288 pAdapter->sessionId, pHddStaCtx->staDebugState);
12289 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012290 }
12291 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012292 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012293 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012294 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012295 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012296 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012297 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012298 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012299 }
12300 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012301disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012302 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12303 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012304}
12305
12306/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012307 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12308 * @adapter: Pointer to the HDD adapter
12309 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012310 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012311 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012312 * This function will start reassociation if prev_bssid is set and bssid/
12313 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012314 *
Naveen Rawat07332902016-07-27 09:13:17 -070012315 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012316 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012317#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12318 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012319static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12320 struct cfg80211_connect_params *req,
12321 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012322{
Naveen Rawat07332902016-07-27 09:13:17 -070012323 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012324 const uint8_t *bssid = NULL;
12325 uint16_t channel = 0;
12326
12327 if (req->bssid)
12328 bssid = req->bssid;
12329 else if (req->bssid_hint)
12330 bssid = req->bssid_hint;
12331
12332 if (req->channel)
12333 channel = req->channel->hw_value;
12334 else if (req->channel_hint)
12335 channel = req->channel_hint->hw_value;
12336
12337 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012338 reassoc = true;
12339 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012340 channel, MAC_ADDR_ARRAY(bssid));
12341 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012342 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012343 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012344 }
Naveen Rawat07332902016-07-27 09:13:17 -070012345 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012346}
12347#else
Naveen Rawat07332902016-07-27 09:13:17 -070012348static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12349 struct cfg80211_connect_params *req,
12350 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012351{
Naveen Rawat07332902016-07-27 09:13:17 -070012352 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012353}
12354#endif
12355
12356/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012357 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12358 * @wiphy: Pointer to wiphy
12359 * @dev: Pointer to network device
12360 * @req: Pointer to cfg80211 connect request
12361 *
12362 * This function is used to start the association process
12363 *
12364 * Return: 0 for success, non-zero for failure
12365 */
12366static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12367 struct net_device *ndev,
12368 struct cfg80211_connect_params *req)
12369{
12370 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012371 u16 channel;
12372#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12373 const u8 *bssid_hint = req->bssid_hint;
12374#else
12375 const u8 *bssid_hint = NULL;
12376#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012377 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12378 hdd_context_t *pHddCtx;
12379
12380 ENTER();
12381
Anurag Chouhan6d760662016-02-20 16:05:43 +053012382 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012383 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012384 return -EINVAL;
12385 }
12386
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012387 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012388 TRACE_CODE_HDD_CFG80211_CONNECT,
12389 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012390 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012391 hdd_device_mode_to_string(pAdapter->device_mode),
12392 pAdapter->device_mode);
12393
Krunal Sonib4326f22016-03-10 13:05:51 -080012394 if (pAdapter->device_mode != QDF_STA_MODE &&
12395 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012396 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012397 hdd_device_mode_to_string(pAdapter->device_mode),
12398 pAdapter->device_mode);
12399 return -EINVAL;
12400 }
12401
12402 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12403 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012404 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012405 return -EINVAL;
12406 }
12407
12408 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012409 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012410 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012411
Naveen Rawat07332902016-07-27 09:13:17 -070012412 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012413 return status;
12414
Agrawal Ashishf156e942016-08-04 14:54:47 +053012415 wlan_hdd_disable_roaming(pAdapter);
12416
12417 /* Try disconnecting if already in connected state */
12418 status = wlan_hdd_try_disconnect(pAdapter);
12419 if (0 > status) {
12420 hdd_err("Failed to disconnect the existing connection");
12421 return -EALREADY;
12422 }
12423
12424 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012425 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012426 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012427 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012428 pAdapter->device_mode),
12429 req->channel->hw_value, HW_MODE_20_MHZ)) {
12430 hdd_err("This concurrency combination is not allowed");
12431 return -ECONNREFUSED;
12432 }
12433 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012434 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012435 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012436 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12437 hdd_err("This concurrency combination is not allowed");
12438 return -ECONNREFUSED;
12439 }
12440 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012441
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012442 /*initialise security parameters */
12443 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12444
12445 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012446 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012447 return status;
12448 }
12449
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012450 if (req->channel)
12451 channel = req->channel->hw_value;
12452 else
12453 channel = 0;
12454 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12455 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012456 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012457 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012458 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012459 return status;
12460 }
12461 EXIT();
12462 return status;
12463}
12464
12465/**
12466 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12467 * @wiphy: Pointer to wiphy
12468 * @dev: Pointer to network device
12469 * @req: Pointer to cfg80211 connect request
12470 *
12471 * Return: 0 for success, non-zero for failure
12472 */
12473static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12474 struct net_device *ndev,
12475 struct cfg80211_connect_params *req)
12476{
12477 int ret;
12478 cds_ssr_protect(__func__);
12479 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12480 cds_ssr_unprotect(__func__);
12481
12482 return ret;
12483}
12484
12485/**
12486 * wlan_hdd_disconnect() - hdd disconnect api
12487 * @pAdapter: Pointer to adapter
12488 * @reason: Disconnect reason code
12489 *
12490 * This function is used to issue a disconnect request to SME
12491 *
12492 * Return: 0 for success, non-zero for failure
12493 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012494static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012495{
12496 int status, result = 0;
12497 unsigned long rc;
12498 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12499 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12500
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012501 ENTER();
12502
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012503 status = wlan_hdd_validate_context(pHddCtx);
12504
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012505 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012506 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012507
12508 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012509 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012510 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12511 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012512 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012513 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12514 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12515
12516 /*issue disconnect */
12517
12518 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12519 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012520 /*
12521 * Wait here instead of returning directly, this will block the next
12522 * connect command and allow processing of the scan for ssid and
12523 * the previous connect command in CSR. Else we might hit some
12524 * race conditions leading to SME and HDD out of sync.
12525 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012526 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012527 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012528 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012529 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012530 (int)status);
12531 pHddStaCtx->staDebugState = status;
12532 result = -EINVAL;
12533 goto disconnected;
12534 }
12535 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12536 msecs_to_jiffies
12537 (WLAN_WAIT_TIME_DISCONNECT));
12538
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012539 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012540 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012541 result = -ETIMEDOUT;
12542 }
12543disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012544 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12545#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12546 /* Sending disconnect event to userspace for kernel version < 3.11
12547 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12548 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012549 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012550 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12551 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012552#endif
12553
12554 return result;
12555}
12556
12557/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012558 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12559 * @reason: ieee80211 reason code.
12560 *
12561 * This utility function helps log string conversion of reason code.
12562 *
12563 * Return: string conversion of reason code, if match found;
12564 * "Unknown" otherwise.
12565 */
12566static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12567{
12568 switch (reason) {
12569 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12570 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12571 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12572 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12573 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12574 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12575 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12576 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12577 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12578 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12579 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12580 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12581 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12582 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12583 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12584 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12585 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12586 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12587 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12588 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12589 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12590 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12591 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12592 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12593 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12594 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12595 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12596 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12597 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12598 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12599 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12600 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12601 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12602 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12603 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12604 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12605 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12606 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12607 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12608 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12609 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12610 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12611 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12612 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12613 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12614 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12615 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12616 default:
12617 return "Unknown";
12618 }
12619}
12620
12621/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012622 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12623 * @wiphy: Pointer to wiphy
12624 * @dev: Pointer to network device
12625 * @reason: Disconnect reason code
12626 *
12627 * This function is used to issue a disconnect request to SME
12628 *
12629 * Return: 0 for success, non-zero for failure
12630 */
12631static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12632 struct net_device *dev, u16 reason)
12633{
12634 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12635 int status;
12636 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12637 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12638#ifdef FEATURE_WLAN_TDLS
12639 uint8_t staIdx;
12640#endif
12641
12642 ENTER();
12643
Anurag Chouhan6d760662016-02-20 16:05:43 +053012644 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012645 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012646 return -EINVAL;
12647 }
12648
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012649 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012650 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12651 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012652 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012653 hdd_device_mode_to_string(pAdapter->device_mode),
12654 pAdapter->device_mode, reason);
12655
12656 status = wlan_hdd_validate_context(pHddCtx);
12657
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012658 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012659 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012660
12661 /* Issue disconnect request to SME, if station is in connected state */
12662 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12663 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12664 eCsrRoamDisconnectReason reasonCode =
12665 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12666 hdd_scaninfo_t *pScanInfo;
12667
12668 switch (reason) {
12669 case WLAN_REASON_MIC_FAILURE:
12670 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12671 break;
12672
12673 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12674 case WLAN_REASON_DISASSOC_AP_BUSY:
12675 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12676 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12677 break;
12678
12679 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12680 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12681 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12682 break;
12683
12684 case WLAN_REASON_DEAUTH_LEAVING:
12685 reasonCode =
12686 pHddCtx->config->
12687 gEnableDeauthToDisassocMap ?
12688 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12689 eCSR_DISCONNECT_REASON_DEAUTH;
12690 break;
12691 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12692 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12693 break;
12694 default:
12695 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12696 break;
12697 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012698 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012699 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012700 pScanInfo = &pAdapter->scan_info;
12701 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012702 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012703 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12704 eCSR_SCAN_ABORT_DEFAULT);
12705 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012706 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012707#ifdef FEATURE_WLAN_TDLS
12708 /* First clean up the tdls peers if any */
12709 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12710 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12711 pAdapter->sessionId)
12712 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12713 uint8_t *mac;
12714 mac =
12715 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012716 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12717 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012718 pHddCtx->tdlsConnInfo[staIdx].staId,
12719 pAdapter->sessionId,
12720 MAC_ADDR_ARRAY(mac));
12721 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12722 (pAdapter),
12723 pAdapter->sessionId, mac);
12724 }
12725 }
12726#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012727 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012728 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012729 hdd_info("Disconnect request from user space with reason: %s",
12730 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012731 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12732 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012733 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012734 return -EINVAL;
12735 }
12736 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012737 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012738 pHddStaCtx->conn_info.connState);
12739 }
12740
12741 return status;
12742}
12743
12744/**
12745 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12746 * @wiphy: Pointer to wiphy
12747 * @dev: Pointer to network device
12748 * @reason: Disconnect reason code
12749 *
12750 * Return: 0 for success, non-zero for failure
12751 */
12752static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12753 struct net_device *dev, u16 reason)
12754{
12755 int ret;
12756 cds_ssr_protect(__func__);
12757 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12758 cds_ssr_unprotect(__func__);
12759
12760 return ret;
12761}
12762
12763/**
12764 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12765 * @pAdapter: Pointer to adapter
12766 * @param: Pointer to IBSS parameters
12767 *
12768 * This function is used to initialize the security settings in IBSS mode
12769 *
12770 * Return: 0 for success, non-zero for failure
12771 */
12772static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12773 struct cfg80211_ibss_params
12774 *params)
12775{
12776 int status = 0;
12777 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12778 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12779 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12780
12781 ENTER();
12782
12783 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012784 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012785 pHddStaCtx->ibss_enc_key_installed = 0;
12786
12787 if (params->ie_len && (NULL != params->ie)) {
12788 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12789 params->ie_len, WLAN_EID_RSN)) {
12790 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12791 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12792 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
12793 tDot11fIEWPA dot11WPAIE;
12794 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12795 u8 *ie;
12796
12797 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12798 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12799 params->ie_len,
12800 DOT11F_EID_WPA);
12801 if (NULL != ie) {
12802 pWextState->wpaVersion =
12803 IW_AUTH_WPA_VERSION_WPA;
12804 /* Unpack the WPA IE */
12805 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
12806 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
12807 &ie[2 + 4],
12808 ie[1] - 4, &dot11WPAIE);
12809 /*Extract the multicast cipher, the encType for unicast
12810 cipher for wpa-none is none */
12811 encryptionType =
12812 hdd_translate_wpa_to_csr_encryption_type
12813 (dot11WPAIE.multicast_cipher);
12814 }
12815 }
12816
12817 status =
12818 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
12819 params->ie_len);
12820
12821 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012822 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012823 return status;
12824 }
12825 }
12826
12827 pWextState->roamProfile.AuthType.authType[0] =
12828 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12829
12830 if (params->privacy) {
12831 /* Security enabled IBSS, At this time there is no information
12832 * available about the security paramters, so initialise the
12833 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
12834 * The correct security parameters will be updated later in
12835 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
12836 * set inorder enable privacy bit in beacons
12837 */
12838
12839 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12840 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012841 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012842 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12843 pWextState->roamProfile.EncryptionType.numEntries = 1;
12844 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12845 encryptionType;
12846 return status;
12847}
12848
12849/**
12850 * __wlan_hdd_cfg80211_join_ibss() - join ibss
12851 * @wiphy: Pointer to wiphy
12852 * @dev: Pointer to network device
12853 * @param: Pointer to IBSS join parameters
12854 *
12855 * This function is used to create/join an IBSS network
12856 *
12857 * Return: 0 for success, non-zero for failure
12858 */
12859static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12860 struct net_device *dev,
12861 struct cfg80211_ibss_params *params)
12862{
12863 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12864 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12865 tCsrRoamProfile *pRoamProfile;
12866 int status;
12867 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12868 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053012869 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012870 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012871
12872 ENTER();
12873
Anurag Chouhan6d760662016-02-20 16:05:43 +053012874 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012875 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012876 return -EINVAL;
12877 }
12878
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012879 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012880 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
12881 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012882 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012883 hdd_device_mode_to_string(pAdapter->device_mode),
12884 pAdapter->device_mode);
12885
12886 status = wlan_hdd_validate_context(pHddCtx);
12887
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012888 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012889 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012890
12891 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053012892 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012893 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12894 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
12895 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12896 int indx;
12897
12898 /* Get channel number */
12899 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012900 params->
12901 chandef.
12902 chan->
12903 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012904
12905 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12906 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012907 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012908 return -EOPNOTSUPP;
12909 }
12910
12911 for (indx = 0; indx < numChans; indx++) {
12912 if (channelNum == validChan[indx]) {
12913 break;
12914 }
12915 }
12916 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012917 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012918 return -EINVAL;
12919 }
12920 }
12921
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012922 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012923 HW_MODE_20_MHZ)) {
12924 hdd_err("This concurrency combination is not allowed");
12925 return -ECONNREFUSED;
12926 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012927
Krunal Soni3091bcc2016-06-23 12:28:21 -070012928 status = qdf_reset_connection_update();
12929 if (!QDF_IS_STATUS_SUCCESS(status))
12930 hdd_err("ERR: clear event failed");
12931
12932 status = cds_current_connections_update(pAdapter->sessionId,
12933 channelNum,
12934 SIR_UPDATE_REASON_JOIN_IBSS);
12935 if (QDF_STATUS_E_FAILURE == status) {
12936 hdd_err("ERROR: connections update failed!!");
12937 return -EINVAL;
12938 }
12939
12940 if (QDF_STATUS_SUCCESS == status) {
12941 status = qdf_wait_for_connection_update();
12942 if (!QDF_IS_STATUS_SUCCESS(status)) {
12943 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012944 return -EINVAL;
12945 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012946 }
12947
12948 /*Try disconnecting if already in connected state */
12949 status = wlan_hdd_try_disconnect(pAdapter);
12950 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012951 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012952 return -EALREADY;
12953 }
12954
12955 pRoamProfile = &pWextState->roamProfile;
12956
12957 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012958 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012959 return -EINVAL;
12960 }
12961
12962 /* enable selected protection checks in IBSS mode */
12963 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
12964
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012965 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012966 WNI_CFG_IBSS_ATIM_WIN_SIZE,
12967 pHddCtx->config->
12968 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012969 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012970 }
12971
12972 /* BSSID is provided by upper layers hence no need to AUTO generate */
12973 if (NULL != params->bssid) {
12974 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012975 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012976 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012977 return -EIO;
12978 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012979 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012980 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
12981 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012982 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012983 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012984 return -EIO;
12985 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053012986 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012987 }
12988 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
12989 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
12990 pRoamProfile->beaconInterval = params->beacon_interval;
12991 else {
12992 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012993 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012994 params->beacon_interval, pRoamProfile->beaconInterval);
12995 }
12996
12997 /* Set Channel */
12998 if (channelNum) {
12999 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013000 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013001 pRoamProfile->ChannelInfo.numOfChannels = 1;
13002 pHddStaCtx->conn_info.operationChannel = channelNum;
13003 pRoamProfile->ChannelInfo.ChannelList =
13004 &pHddStaCtx->conn_info.operationChannel;
13005 }
13006
13007 /* Initialize security parameters */
13008 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13009 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013010 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013011 return status;
13012 }
13013
13014 /* Issue connect start */
13015 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13016 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013017 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013018 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013019 operationChannel,
13020 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013021
13022 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013023 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013024 return status;
13025 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013026 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013027 return 0;
13028}
13029
13030/**
13031 * wlan_hdd_cfg80211_join_ibss() - join ibss
13032 * @wiphy: Pointer to wiphy
13033 * @dev: Pointer to network device
13034 * @param: Pointer to IBSS join parameters
13035 *
13036 * This function is used to create/join an IBSS network
13037 *
13038 * Return: 0 for success, non-zero for failure
13039 */
13040static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13041 struct net_device *dev,
13042 struct cfg80211_ibss_params *params)
13043{
13044 int ret = 0;
13045
13046 cds_ssr_protect(__func__);
13047 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13048 cds_ssr_unprotect(__func__);
13049
13050 return ret;
13051}
13052
13053/**
13054 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13055 * @wiphy: Pointer to wiphy
13056 * @dev: Pointer to network device
13057 *
13058 * This function is used to leave an IBSS network
13059 *
13060 * Return: 0 for success, non-zero for failure
13061 */
13062static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13063 struct net_device *dev)
13064{
13065 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13066 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13067 tCsrRoamProfile *pRoamProfile;
13068 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13069 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013070 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013071 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013072 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013073
13074 ENTER();
13075
Anurag Chouhan6d760662016-02-20 16:05:43 +053013076 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013077 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013078 return -EINVAL;
13079 }
13080
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013081 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013082 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13083 pAdapter->sessionId,
13084 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13085 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013086 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013087 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013088
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013089 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013090 hdd_device_mode_to_string(pAdapter->device_mode),
13091 pAdapter->device_mode);
13092 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013093 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013094 return -EIO;
13095 }
13096
13097 pRoamProfile = &pWextState->roamProfile;
13098
13099 /* Issue disconnect only if interface type is set to IBSS */
13100 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013101 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013102 return -EINVAL;
13103 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013104 /* Clearing add IE of beacon */
13105 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13106 sizeof(tSirMacAddr));
13107 updateIE.smeSessionId = pAdapter->sessionId;
13108 updateIE.ieBufferlength = 0;
13109 updateIE.pAdditionIEBuffer = NULL;
13110 updateIE.append = true;
13111 updateIE.notify = true;
13112 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13113 &updateIE,
13114 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013115 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013116 }
13117
13118 /* Reset WNI_CFG_PROBE_RSP Flags */
13119 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013120
13121 /* Issue Disconnect request */
13122 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13123 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13124 pAdapter->sessionId,
13125 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013126 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013127 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013128 hal_status);
13129 return -EAGAIN;
13130 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013131
13132 /* wait for mc thread to cleanup and then return to upper stack
13133 * so by the time upper layer calls the change interface, we are
13134 * all set to proceed further
13135 */
13136 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13137 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13138 if (!rc) {
13139 hdd_err("Failed to disconnect, timed out");
13140 return -ETIMEDOUT;
13141 }
13142
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013143 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013144 return 0;
13145}
13146
13147/**
13148 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13149 * @wiphy: Pointer to wiphy
13150 * @dev: Pointer to network device
13151 *
13152 * This function is used to leave an IBSS network
13153 *
13154 * Return: 0 for success, non-zero for failure
13155 */
13156static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13157 struct net_device *dev)
13158{
13159 int ret = 0;
13160
13161 cds_ssr_protect(__func__);
13162 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13163 cds_ssr_unprotect(__func__);
13164
13165 return ret;
13166}
13167
13168/**
13169 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13170 * @wiphy: Pointer to wiphy
13171 * @changed: Parameters changed
13172 *
13173 * This function is used to set the phy parameters. RTS Threshold/FRAG
13174 * Threshold/Retry Count etc.
13175 *
13176 * Return: 0 for success, non-zero for failure
13177 */
13178static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13179 u32 changed)
13180{
13181 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13182 tHalHandle hHal = pHddCtx->hHal;
13183 int status;
13184
13185 ENTER();
13186
Anurag Chouhan6d760662016-02-20 16:05:43 +053013187 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013188 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013189 return -EINVAL;
13190 }
13191
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013192 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013193 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13194 NO_SESSION, wiphy->rts_threshold));
13195 status = wlan_hdd_validate_context(pHddCtx);
13196
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013197 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013198 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013199
13200 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13201 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13202 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13203
13204 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13205 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013206 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013207 rts_threshold);
13208 return -EINVAL;
13209 }
13210
13211 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13212 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013213 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013214 rts_threshold);
13215 return -EIO;
13216 }
13217
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013218 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013219 }
13220
13221 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13222 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13223 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13224 wiphy->frag_threshold;
13225
13226 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13227 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013228 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013229 frag_threshold);
13230 return -EINVAL;
13231 }
13232
13233 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13234 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013235 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013236 frag_threshold);
13237 return -EIO;
13238 }
13239
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013240 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013241 }
13242
13243 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13244 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13245 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13246 wiphy->retry_short : wiphy->retry_long;
13247
13248 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13249 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013250 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013251 return -EINVAL;
13252 }
13253
13254 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13255 if (0 != sme_cfg_set_int(hHal,
13256 WNI_CFG_LONG_RETRY_LIMIT,
13257 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013258 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013259 retry_value);
13260 return -EIO;
13261 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013262 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013263 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13264 if (0 != sme_cfg_set_int(hHal,
13265 WNI_CFG_SHORT_RETRY_LIMIT,
13266 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013267 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013268 retry_value);
13269 return -EIO;
13270 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013271 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013272 }
13273 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013274 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013275 return 0;
13276}
13277
13278/**
13279 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13280 * @wiphy: Pointer to wiphy
13281 * @changed: Parameters changed
13282 *
13283 * Return: 0 for success, non-zero for failure
13284 */
13285static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13286{
13287 int ret;
13288
13289 cds_ssr_protect(__func__);
13290 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13291 cds_ssr_unprotect(__func__);
13292
13293 return ret;
13294}
13295
13296/**
13297 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13298 * key
13299 * @wiphy: Pointer to wiphy
13300 * @dev: Pointer to network device
13301 * @key_index: Key index
13302 *
13303 * Return: 0
13304 */
13305static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13306 struct net_device *netdev,
13307 u8 key_index)
13308{
13309 ENTER();
13310 return 0;
13311}
13312
13313/**
13314 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13315 * wlan_hdd_set_default_mgmt_key
13316 * @wiphy: pointer to wiphy
13317 * @netdev: pointer to net_device structure
13318 * @key_index: key index
13319 *
13320 * Return: 0 on success, error number on failure
13321 */
13322static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13323 struct net_device *netdev,
13324 u8 key_index)
13325{
13326 int ret;
13327
13328 cds_ssr_protect(__func__);
13329 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13330 cds_ssr_unprotect(__func__);
13331
13332 return ret;
13333}
13334
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013335/**
13336 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13337 * @wiphy: Pointer to wiphy
13338 * @dev: Pointer to network device
13339 * @params: Pointer to tx queue parameters
13340 *
13341 * Return: 0
13342 */
13343static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13344 struct net_device *dev,
13345 struct ieee80211_txq_params *params)
13346{
13347 ENTER();
13348 return 0;
13349}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013350
13351/**
13352 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13353 * @wiphy: pointer to wiphy
13354 * @netdev: pointer to net_device structure
13355 * @params: pointer to ieee80211_txq_params
13356 *
13357 * Return: 0 on success, error number on failure
13358 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013359static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13360 struct net_device *dev,
13361 struct ieee80211_txq_params *params)
13362{
13363 int ret;
13364
13365 cds_ssr_protect(__func__);
13366 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13367 cds_ssr_unprotect(__func__);
13368
13369 return ret;
13370}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013371
13372/**
13373 * __wlan_hdd_cfg80211_del_station() - delete station v2
13374 * @wiphy: Pointer to wiphy
13375 * @param: Pointer to delete station parameter
13376 *
13377 * Return: 0 for success, non-zero for failure
13378 */
13379static
13380int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13381 struct net_device *dev,
13382 struct tagCsrDelStaParams *pDelStaParams)
13383{
13384 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13385 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013386 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013387 hdd_hostapd_state_t *hapd_state;
13388 int status;
13389 uint8_t staId;
13390 uint8_t *mac;
13391
13392 ENTER();
13393
Anurag Chouhan6d760662016-02-20 16:05:43 +053013394 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013395 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013396 return -EINVAL;
13397 }
13398
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013399 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013400 TRACE_CODE_HDD_CFG80211_DEL_STA,
13401 pAdapter->sessionId, pAdapter->device_mode));
13402
13403 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13404 status = wlan_hdd_validate_context(pHddCtx);
13405
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013406 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013407 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013408
13409 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13410
Krunal Sonib4326f22016-03-10 13:05:51 -080013411 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13412 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013413
13414 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13415 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013416 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013417 return 0;
13418 }
13419
Anurag Chouhanc5548422016-02-24 18:33:27 +053013420 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013421 uint16_t i;
13422 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13423 if ((pAdapter->aStaInfo[i].isUsed) &&
13424 (!pAdapter->aStaInfo[i].
13425 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013426 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013427 mac,
13428 pAdapter->aStaInfo[i].
13429 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013430 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013431 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13432 hdd_ipa_wlan_evt(pAdapter,
13433 pAdapter->
13434 aStaInfo[i].
13435 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013436 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013437 mac);
13438 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013439 hdd_notice("Delete STA with MAC::"
13440 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013441 MAC_ADDR_ARRAY(mac));
13442
13443 if (pHddCtx->dev_dfs_cac_status ==
13444 DFS_CAC_IN_PROGRESS)
13445 goto fn_end;
13446
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013447 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013448 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013449 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013450 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013451 hdd_softap_sta_deauth(pAdapter,
13452 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013453 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013454 pAdapter->aStaInfo[i].
13455 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013456 qdf_status =
13457 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013458 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013459 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013460 if (!QDF_IS_STATUS_SUCCESS(
13461 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013462 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013463 }
13464 }
13465 }
13466 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013467 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013468 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013469 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013470 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013471 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013472 hdd_notice("Skip DEL STA as this is not used::"
13473 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013474 MAC_ADDR_ARRAY(mac));
13475 return -ENOENT;
13476 }
13477
13478 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13479 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013480 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013481 }
13482
13483 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13484 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013485 hdd_notice("Skip DEL STA as deauth is in progress::"
13486 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013487 MAC_ADDR_ARRAY(mac));
13488 return -ENOENT;
13489 }
13490
13491 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13492
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013493 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013494 MAC_ADDR_ARRAY(mac));
13495
13496 /* Case: SAP in ACS selected DFS ch and client connected
13497 * Now Radar detected. Then if random channel is another
13498 * DFS ch then new CAC is initiated and no TX allowed.
13499 * So do not send any mgmt frames as it will timeout
13500 * during CAC.
13501 */
13502
13503 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13504 goto fn_end;
13505
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013506 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013507 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13508 (pAdapter), pAdapter->sessionId,
13509 (uint8_t *)&pDelStaParams->peerMacAddr,
13510 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013511 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013512 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013513 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013514 pAdapter->aStaInfo[staId].isDeauthInProgress =
13515 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013516 hdd_notice("STA removal failed for ::"
13517 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013518 MAC_ADDR_ARRAY(mac));
13519 return -ENOENT;
13520 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013521 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013522 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013523 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013524 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013525 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013526 }
13527 }
13528 }
13529
13530fn_end:
13531 EXIT();
13532 return 0;
13533}
13534
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013535#if defined(USE_CFG80211_DEL_STA_V2)
13536/**
13537 * wlan_hdd_del_station() - delete station wrapper
13538 * @adapter: pointer to the hdd adapter
13539 *
13540 * Return: None
13541 */
13542void wlan_hdd_del_station(hdd_adapter_t *adapter)
13543{
13544 struct station_del_parameters del_sta;
13545 del_sta.mac = NULL;
13546 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13547 del_sta.reason_code = eCsrForcedDeauthSta;
13548
13549 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13550 &del_sta);
13551}
13552#else
13553void wlan_hdd_del_station(hdd_adapter_t *adapter)
13554{
13555 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13556}
13557#endif
13558
13559#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013560/**
13561 * wlan_hdd_cfg80211_del_station() - delete station v2
13562 * @wiphy: Pointer to wiphy
13563 * @param: Pointer to delete station parameter
13564 *
13565 * Return: 0 for success, non-zero for failure
13566 */
13567int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13568 struct net_device *dev,
13569 struct station_del_parameters *param)
13570#else
13571/**
13572 * wlan_hdd_cfg80211_del_station() - delete station
13573 * @wiphy: Pointer to wiphy
13574 * @mac: Pointer to station mac address
13575 *
13576 * Return: 0 for success, non-zero for failure
13577 */
13578#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13579int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13580 struct net_device *dev,
13581 const uint8_t *mac)
13582#else
13583int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13584 struct net_device *dev,
13585 uint8_t *mac)
13586#endif
13587#endif
13588{
13589 int ret;
13590 struct tagCsrDelStaParams delStaParams;
13591
13592 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013593#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013594 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013595 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013596 return -EINVAL;
13597 }
13598 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13599 param->subtype, &delStaParams);
13600#else
13601 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13602 (SIR_MAC_MGMT_DEAUTH >> 4),
13603 &delStaParams);
13604#endif
13605 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13606 cds_ssr_unprotect(__func__);
13607
13608 return ret;
13609}
13610
13611/**
13612 * __wlan_hdd_cfg80211_add_station() - add station
13613 * @wiphy: Pointer to wiphy
13614 * @mac: Pointer to station mac address
13615 * @pmksa: Pointer to add station parameter
13616 *
13617 * Return: 0 for success, non-zero for failure
13618 */
13619static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13620 struct net_device *dev,
13621 const uint8_t *mac,
13622 struct station_parameters *params)
13623{
13624 int status = -EPERM;
13625#ifdef FEATURE_WLAN_TDLS
13626 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13627 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13628 u32 mask, set;
13629
13630 ENTER();
13631
Anurag Chouhan6d760662016-02-20 16:05:43 +053013632 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013633 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013634 return -EINVAL;
13635 }
13636
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013637 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013638 TRACE_CODE_HDD_CFG80211_ADD_STA,
13639 pAdapter->sessionId, params->listen_interval));
13640
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013641 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013642 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013643
13644 mask = params->sta_flags_mask;
13645
13646 set = params->sta_flags_set;
13647
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013648 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013649 MAC_ADDR_ARRAY(mac));
13650
13651 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13652 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13653 status =
13654 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13655 }
13656 }
13657#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013658 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013659 return status;
13660}
13661
13662/**
13663 * wlan_hdd_cfg80211_add_station() - add station
13664 * @wiphy: Pointer to wiphy
13665 * @mac: Pointer to station mac address
13666 * @pmksa: Pointer to add station parameter
13667 *
13668 * Return: 0 for success, non-zero for failure
13669 */
13670#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13671static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13672 struct net_device *dev,
13673 const uint8_t *mac,
13674 struct station_parameters *params)
13675#else
13676static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13677 struct net_device *dev, uint8_t *mac,
13678 struct station_parameters *params)
13679#endif
13680{
13681 int ret;
13682
13683 cds_ssr_protect(__func__);
13684 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13685 cds_ssr_unprotect(__func__);
13686
13687 return ret;
13688}
13689
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013690/**
13691 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13692 * @wiphy: Pointer to wiphy
13693 * @dev: Pointer to network device
13694 * @pmksa: Pointer to set pmksa parameter
13695 *
13696 * Return: 0 for success, non-zero for failure
13697 */
13698static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13699 struct net_device *dev,
13700 struct cfg80211_pmksa *pmksa)
13701{
13702 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13703 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13704 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013705 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013706 int status;
13707 tPmkidCacheInfo pmk_id;
13708
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013709 ENTER();
13710
Anurag Chouhan6d760662016-02-20 16:05:43 +053013711 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013712 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013713 return -EINVAL;
13714 }
13715
13716 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013717 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013718 return -EINVAL;
13719 }
13720
13721 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013722 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013723 pmksa->bssid, pmksa->pmkid);
13724 return -EINVAL;
13725 }
13726
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013727 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013728 MAC_ADDR_ARRAY(pmksa->bssid));
13729
13730 status = wlan_hdd_validate_context(pHddCtx);
13731
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013732 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013733 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013734
13735 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13736
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013737 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13738 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013739
13740 /* Add to the PMKSA ID Cache in CSR */
13741 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13742 &pmk_id, 1, false);
13743
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013744 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013745 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
13746 pAdapter->sessionId, result));
13747
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013748 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013749 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013750}
13751
13752/**
13753 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13754 * @wiphy: Pointer to wiphy
13755 * @dev: Pointer to network device
13756 * @pmksa: Pointer to set pmksa parameter
13757 *
13758 * Return: 0 for success, non-zero for failure
13759 */
13760static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13761 struct net_device *dev,
13762 struct cfg80211_pmksa *pmksa)
13763{
13764 int ret;
13765
13766 cds_ssr_protect(__func__);
13767 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
13768 cds_ssr_unprotect(__func__);
13769
13770 return ret;
13771}
13772
13773/**
13774 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13775 * @wiphy: Pointer to wiphy
13776 * @dev: Pointer to network device
13777 * @pmksa: Pointer to pmksa parameter
13778 *
13779 * Return: 0 for success, non-zero for failure
13780 */
13781static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13782 struct net_device *dev,
13783 struct cfg80211_pmksa *pmksa)
13784{
13785 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13786 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13787 tHalHandle halHandle;
13788 int status = 0;
13789
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013790 ENTER();
13791
Anurag Chouhan6d760662016-02-20 16:05:43 +053013792 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013793 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013794 return -EINVAL;
13795 }
13796
13797 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013798 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013799 return -EINVAL;
13800 }
13801
13802 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013803 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013804 return -EINVAL;
13805 }
13806
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013807 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013808 MAC_ADDR_ARRAY(pmksa->bssid));
13809
13810 status = wlan_hdd_validate_context(pHddCtx);
13811
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013812 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013813 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013814
13815 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13816
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013817 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053013818 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
13819 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013820 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013821 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013822 sme_roam_del_pmkid_from_cache(halHandle,
13823 pAdapter->sessionId, pmksa->bssid,
13824 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013825 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013826 MAC_ADDR_ARRAY(pmksa->bssid));
13827 status = -EINVAL;
13828 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013829 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013830 return status;
13831}
13832
13833/**
13834 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13835 * @wiphy: Pointer to wiphy
13836 * @dev: Pointer to network device
13837 * @pmksa: Pointer to pmksa parameter
13838 *
13839 * Return: 0 for success, non-zero for failure
13840 */
13841static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13842 struct net_device *dev,
13843 struct cfg80211_pmksa *pmksa)
13844{
13845 int ret;
13846
13847 cds_ssr_protect(__func__);
13848 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
13849 cds_ssr_unprotect(__func__);
13850
13851 return ret;
13852
13853}
13854
13855/**
13856 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13857 * @wiphy: Pointer to wiphy
13858 * @dev: Pointer to network device
13859 *
13860 * Return: 0 for success, non-zero for failure
13861 */
13862static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13863 struct net_device *dev)
13864{
13865 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13866 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13867 tHalHandle halHandle;
13868 int status = 0;
13869
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013870 ENTER();
13871
Anurag Chouhan6d760662016-02-20 16:05:43 +053013872 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013873 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013874 return -EINVAL;
13875 }
13876
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013877 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013878
13879 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13880 status = wlan_hdd_validate_context(pHddCtx);
13881
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013882 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013883 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013884
13885 /* Retrieve halHandle */
13886 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13887
13888 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013889 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013890 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
13891 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013892 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013893 status = -EINVAL;
13894 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013895 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013896 return status;
13897}
13898
13899/**
13900 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13901 * @wiphy: Pointer to wiphy
13902 * @dev: Pointer to network device
13903 *
13904 * Return: 0 for success, non-zero for failure
13905 */
13906static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13907 struct net_device *dev)
13908{
13909 int ret;
13910
13911 cds_ssr_protect(__func__);
13912 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
13913 cds_ssr_unprotect(__func__);
13914
13915 return ret;
13916}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013917
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080013918#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013919/**
13920 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13921 * @wiphy: Pointer to wiphy
13922 * @dev: Pointer to network device
13923 * @ftie: Pointer to fast transition ie parameter
13924 *
13925 * Return: 0 for success, non-zero for failure
13926 */
13927static int
13928__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13929 struct net_device *dev,
13930 struct cfg80211_update_ft_ies_params *ftie)
13931{
13932 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
13933 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13934 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13935 int status;
13936
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013937 ENTER();
13938
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013939 status = wlan_hdd_validate_context(hdd_ctx);
13940 if (status)
13941 return status;
13942
Anurag Chouhan6d760662016-02-20 16:05:43 +053013943 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013944 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013945 return -EINVAL;
13946 }
13947
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013948 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013949 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
13950 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
13951 /* Added for debug on reception of Re-assoc Req. */
13952 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013953 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013954 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013955 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013956 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013957 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013958 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013959
13960 /* Pass the received FT IEs to SME */
13961 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
13962 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013963 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013964 return 0;
13965}
13966
13967/**
13968 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13969 * @wiphy: Pointer to wiphy
13970 * @dev: Pointer to network device
13971 * @ftie: Pointer to fast transition ie parameter
13972 *
13973 * Return: 0 for success, non-zero for failure
13974 */
13975static int
13976wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13977 struct net_device *dev,
13978 struct cfg80211_update_ft_ies_params *ftie)
13979{
13980 int ret;
13981
13982 cds_ssr_protect(__func__);
13983 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
13984 cds_ssr_unprotect(__func__);
13985
13986 return ret;
13987}
13988#endif
13989
13990#ifdef WLAN_FEATURE_GTK_OFFLOAD
13991/**
13992 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
13993 * @callbackContext: Callback context
13994 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
13995 *
13996 * Callback rountine called upon receiving response for get offload info
13997 *
13998 * Return: none
13999 */
14000void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14001 tpSirGtkOffloadGetInfoRspParams
14002 pGtkOffloadGetInfoRsp)
14003{
14004 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14005 uint8_t tempReplayCounter[8];
14006 hdd_station_ctx_t *pHddStaCtx;
14007
14008 ENTER();
14009
14010 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014011 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014012 return;
14013 }
14014
14015 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014016 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014017 return;
14018 }
14019
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014020 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014021 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014022 return;
14023 }
14024
14025 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14026 /* Update replay counter */
14027 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14028 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14029
14030 {
14031 /* changing from little to big endian since supplicant
14032 * works on big endian format
14033 */
14034 int i;
14035 uint8_t *p =
14036 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14037
14038 for (i = 0; i < 8; i++) {
14039 tempReplayCounter[7 - i] = (uint8_t) p[i];
14040 }
14041 }
14042
14043 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014044 cfg80211_gtk_rekey_notify(pAdapter->dev,
14045 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014046 tempReplayCounter, GFP_KERNEL);
14047}
14048
14049/**
14050 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14051 * @wiphy: Pointer to wiphy
14052 * @dev: Pointer to network device
14053 * @data: Pointer to rekey data
14054 *
14055 * This function is used to offload GTK rekeying job to the firmware.
14056 *
14057 * Return: 0 for success, non-zero for failure
14058 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014059static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014060int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14061 struct net_device *dev,
14062 struct cfg80211_gtk_rekey_data *data)
14063{
14064 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14065 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14066 hdd_station_ctx_t *pHddStaCtx;
14067 tHalHandle hHal;
14068 int result;
14069 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014070 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014071
14072 ENTER();
14073
Anurag Chouhan6d760662016-02-20 16:05:43 +053014074 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014075 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014076 return -EINVAL;
14077 }
14078
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014079 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014080 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14081 pAdapter->sessionId, pAdapter->device_mode));
14082
14083 result = wlan_hdd_validate_context(pHddCtx);
14084
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014085 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014086 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014087
14088 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14089 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14090 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014091 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014092 return -EAGAIN;
14093 }
14094
14095 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14096 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14097 NL80211_KCK_LEN);
14098 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14099 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014100 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014101 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014102 {
14103 /* changing from big to little endian since driver
14104 * works on little endian format
14105 */
14106 uint8_t *p =
14107 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14108 ullKeyReplayCounter;
14109 int i;
14110
14111 for (i = 0; i < 8; i++) {
14112 p[7 - i] = data->replay_ctr[i];
14113 }
14114 }
14115
14116 if (true == pHddCtx->hdd_wlan_suspended) {
14117 /* if wlan is suspended, enable GTK offload directly from here */
14118 memcpy(&hddGtkOffloadReqParams,
14119 &pHddStaCtx->gtkOffloadReqParams,
14120 sizeof(tSirGtkOffloadParams));
14121 status =
14122 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14123 pAdapter->sessionId);
14124
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014125 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014126 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014127 status);
14128 return -EINVAL;
14129 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014130 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014131 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014132 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014133 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014134 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014135 return result;
14136}
14137
14138/**
14139 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14140 * @wiphy: Pointer to wiphy
14141 * @dev: Pointer to network device
14142 * @data: Pointer to rekey data
14143 *
14144 * This function is used to offload GTK rekeying job to the firmware.
14145 *
14146 * Return: 0 for success, non-zero for failure
14147 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014148static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014149int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14150 struct net_device *dev,
14151 struct cfg80211_gtk_rekey_data *data)
14152{
14153 int ret;
14154
14155 cds_ssr_protect(__func__);
14156 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14157 cds_ssr_unprotect(__func__);
14158
14159 return ret;
14160}
14161#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14162
14163/**
14164 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14165 * @wiphy: Pointer to wiphy
14166 * @dev: Pointer to network device
14167 * @param: Pointer to access control parameter
14168 *
14169 * Return: 0 for success, non-zero for failure
14170 */
14171static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14172 struct net_device *dev,
14173 const struct cfg80211_acl_data *params)
14174{
14175 int i;
14176 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14177 hdd_hostapd_state_t *pHostapdState;
14178 tsap_Config_t *pConfig;
14179 v_CONTEXT_t p_cds_context = NULL;
14180 hdd_context_t *pHddCtx;
14181 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014182 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014183
14184 ENTER();
14185
Anurag Chouhan6d760662016-02-20 16:05:43 +053014186 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014187 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014188 return -EINVAL;
14189 }
14190
14191 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014192 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014193 return -EINVAL;
14194 }
14195
14196 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14197 status = wlan_hdd_validate_context(pHddCtx);
14198
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014199 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014201
14202 p_cds_context = pHddCtx->pcds_context;
14203 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14204
14205 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014206 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014207 return -EINVAL;
14208 }
14209
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014210 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014211 params->n_acl_entries);
14212
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014213 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014214 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14215 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014216 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014217 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14218
14219 /* default value */
14220 pConfig->num_accept_mac = 0;
14221 pConfig->num_deny_mac = 0;
14222
14223 /**
14224 * access control policy
14225 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14226 * listed in hostapd.deny file.
14227 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14228 * listed in hostapd.accept file.
14229 */
14230 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14231 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14232 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14233 params->acl_policy) {
14234 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14235 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014236 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014237 params->acl_policy);
14238 return -ENOTSUPP;
14239 }
14240
14241 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14242 pConfig->num_accept_mac = params->n_acl_entries;
14243 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014244 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14245 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014246 MAC_ADDR_ARRAY(
14247 params->mac_addrs[i].addr));
14248
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014249 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014250 params->mac_addrs[i].addr,
14251 sizeof(qcmacaddr));
14252 }
14253 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14254 pConfig->num_deny_mac = params->n_acl_entries;
14255 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014256 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14257 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014258 MAC_ADDR_ARRAY(
14259 params->mac_addrs[i].addr));
14260
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014261 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014262 params->mac_addrs[i].addr,
14263 sizeof(qcmacaddr));
14264 }
14265 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014266 qdf_status = wlansap_set_mac_acl(
14267 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014268 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014269 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014270 return -EINVAL;
14271 }
14272 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014273 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014274 hdd_device_mode_to_string(pAdapter->device_mode),
14275 pAdapter->device_mode);
14276 return -EINVAL;
14277 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014278 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014279 return 0;
14280}
14281
14282/**
14283 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14284 * __wlan_hdd_cfg80211_set_mac_acl
14285 * @wiphy: pointer to wiphy structure
14286 * @dev: pointer to net_device
14287 * @params: pointer to cfg80211_acl_data
14288 *
14289 * Return; 0 on success, error number otherwise
14290 */
14291static int
14292wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14293 struct net_device *dev,
14294 const struct cfg80211_acl_data *params)
14295{
14296 int ret;
14297
14298 cds_ssr_protect(__func__);
14299 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14300 cds_ssr_unprotect(__func__);
14301
14302 return ret;
14303}
14304
14305#ifdef WLAN_NL80211_TESTMODE
14306#ifdef FEATURE_WLAN_LPHB
14307/**
14308 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14309 * @pHddCtx: Pointer to hdd context
14310 * @lphbInd: Pointer to low power heart beat indication parameter
14311 *
14312 * Return: none
14313 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014314static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14315 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014316{
14317 struct sk_buff *skb;
14318
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014319 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014320
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014321 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014322 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014323
14324 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014325 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014326 return;
14327 }
14328
14329 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14330 wiphy, sizeof(tSirLPHBInd),
14331 GFP_ATOMIC);
14332 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014333 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014334 return;
14335 }
14336
14337 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014338 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014339 goto nla_put_failure;
14340 }
14341 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014342 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014343 goto nla_put_failure;
14344 }
14345 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014346 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347 goto nla_put_failure;
14348 }
14349 cfg80211_testmode_event(skb, GFP_ATOMIC);
14350 return;
14351
14352nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014353 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014354 kfree_skb(skb);
14355
14356 return;
14357}
14358#endif /* FEATURE_WLAN_LPHB */
14359
14360/**
14361 * __wlan_hdd_cfg80211_testmode() - test mode
14362 * @wiphy: Pointer to wiphy
14363 * @data: Data pointer
14364 * @len: Data length
14365 *
14366 * Return: 0 for success, non-zero for failure
14367 */
14368static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14369 void *data, int len)
14370{
14371 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14372 int err;
14373 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14374
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014375 ENTER();
14376
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014377 err = wlan_hdd_validate_context(pHddCtx);
14378 if (err)
14379 return err;
14380
14381 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14382 len, wlan_hdd_tm_policy);
14383 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014384 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014385 return err;
14386 }
14387
14388 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014389 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014390 return -EINVAL;
14391 }
14392
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014393 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014394 TRACE_CODE_HDD_CFG80211_TESTMODE,
14395 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014396 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14397#ifdef FEATURE_WLAN_LPHB
14398 /* Low Power Heartbeat configuration request */
14399 case WLAN_HDD_TM_CMD_WLAN_HB:
14400 {
14401 int buf_len;
14402 void *buf;
14403 tSirLPHBReq *hb_params = NULL;
14404 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014405 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014406
14407 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014408 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014409 return -EINVAL;
14410 }
14411
14412 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14413 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14414
14415 hb_params_temp = (tSirLPHBReq *) buf;
14416 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14417 && (hb_params_temp->params.lphbTcpParamReq.
14418 timePeriodSec == 0))
14419 return -EINVAL;
14420
14421 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014422 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014423 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014424 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014425 return -ENOMEM;
14426 }
14427
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014428 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014429 smeStatus =
14430 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14431 hb_params,
14432 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014433 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014434 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014435 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014436 }
14437 return 0;
14438 }
14439#endif /* FEATURE_WLAN_LPHB */
14440
14441#if defined(QCA_WIFI_FTM)
14442 case WLAN_HDD_TM_CMD_WLAN_FTM:
14443 {
14444 int buf_len;
14445 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014446 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014447 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014448 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014449 return -EINVAL;
14450 }
14451
14452 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14453 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14454
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014455 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014456
14457 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14458
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014459 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014460 err = -EBUSY;
14461 break;
14462 }
14463#endif
14464
14465 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014466 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014467 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14468 return -EOPNOTSUPP;
14469 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014470 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014471 return err;
14472}
14473
14474/**
14475 * wlan_hdd_cfg80211_testmode() - test mode
14476 * @wiphy: Pointer to wiphy
14477 * @dev: Pointer to network device
14478 * @data: Data pointer
14479 * @len: Data length
14480 *
14481 * Return: 0 for success, non-zero for failure
14482 */
14483static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14484#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14485 struct wireless_dev *wdev,
14486#endif
14487 void *data, int len)
14488{
14489 int ret;
14490
14491 cds_ssr_protect(__func__);
14492 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14493 cds_ssr_unprotect(__func__);
14494
14495 return ret;
14496}
14497
14498#if defined(QCA_WIFI_FTM)
14499/**
14500 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14501 * @buf: Pointer to buffer
14502 * @buf_len: Buffer length
14503 *
14504 * Return: none
14505 */
14506void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14507{
14508 struct sk_buff *skb;
14509 hdd_context_t *hdd_ctx;
14510
14511 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014512 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014513 return;
14514 }
14515
Anurag Chouhan6d760662016-02-20 16:05:43 +053014516 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014517 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014518 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014519 return;
14520 }
14521
14522 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14523 buf_len, GFP_KERNEL);
14524 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014525 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014526 return;
14527 }
14528
14529 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14530 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14531 goto nla_put_failure;
14532
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014533 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014534
14535 cfg80211_testmode_event(skb, GFP_KERNEL);
14536 return;
14537
14538nla_put_failure:
14539 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014540 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014541}
14542#endif
14543#endif /* CONFIG_NL80211_TESTMODE */
14544
14545#ifdef QCA_HT_2040_COEX
14546/**
14547 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14548 * @wiphy: Pointer to wiphy
14549 * @dev: Pointer to network device
14550 * @chandef: Pointer to channel definition parameter
14551 *
14552 * Return: 0 for success, non-zero for failure
14553 */
14554static int
14555__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14556 struct net_device *dev,
14557 struct cfg80211_chan_def *chandef)
14558{
14559 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14560 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014561 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014562 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053014563 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014564
Anurag Chouhan6d760662016-02-20 16:05:43 +053014565 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014566 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014567 return -EINVAL;
14568 }
14569
14570 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14571 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014572 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014573 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014574
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014575 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014576 sme_get_config_param(pHddCtx->hHal, &sme_config);
14577 switch (chandef->width) {
14578 case NL80211_CHAN_WIDTH_20:
14579 if (sme_config.csrConfig.channelBondingMode24GHz !=
14580 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14581 sme_config.csrConfig.channelBondingMode24GHz =
14582 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14583 sme_update_config(pHddCtx->hHal, &sme_config);
14584 cbModeChange = true;
14585 }
14586 break;
14587
14588 case NL80211_CHAN_WIDTH_40:
14589 if (sme_config.csrConfig.channelBondingMode24GHz ==
14590 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14591 if (NL80211_CHAN_HT40MINUS ==
14592 cfg80211_get_chandef_type(chandef))
14593 sme_config.csrConfig.channelBondingMode24GHz =
14594 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14595 else
14596 sme_config.csrConfig.channelBondingMode24GHz =
14597 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14598 sme_update_config(pHddCtx->hHal, &sme_config);
14599 cbModeChange = true;
14600 }
14601 break;
14602
14603 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014604 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014605 return -EINVAL;
14606 }
14607
14608 if (!cbModeChange)
14609 return 0;
14610
Krunal Sonib4326f22016-03-10 13:05:51 -080014611 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014612 return 0;
14613
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014614 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014615 sme_config.csrConfig.channelBondingMode24GHz);
14616
14617 /* Change SAP ht2040 mode */
14618 status = hdd_set_sap_ht2040_mode(pAdapter,
14619 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014620 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014621 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014622 return -EINVAL;
14623 }
14624
14625 return 0;
14626}
14627
14628/**
14629 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14630 * @wiphy: Pointer to wiphy
14631 * @dev: Pointer to network device
14632 * @chandef: Pointer to channel definition parameter
14633 *
14634 * Return: 0 for success, non-zero for failure
14635 */
14636static int
14637wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14638 struct net_device *dev,
14639 struct cfg80211_chan_def *chandef)
14640{
14641 int ret;
14642
14643 cds_ssr_protect(__func__);
14644 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14645 cds_ssr_unprotect(__func__);
14646
14647 return ret;
14648}
14649#endif
14650
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014651#ifdef CHANNEL_SWITCH_SUPPORTED
14652/**
14653 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14654 * channel in SAP/GO
14655 * @wiphy: wiphy pointer
14656 * @dev: dev pointer.
14657 * @csa_params: Change channel params
14658 *
14659 * This function is called to switch channel in SAP/GO
14660 *
14661 * Return: 0 if success else return non zero
14662 */
14663static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14664 struct net_device *dev,
14665 struct cfg80211_csa_settings *csa_params)
14666{
14667 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14668 hdd_context_t *hdd_ctx;
14669 uint8_t channel;
14670 uint16_t freq;
14671 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014672 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014673
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014674 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014675 csa_params->chandef.chan->center_freq);
14676
14677 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14678 ret = wlan_hdd_validate_context(hdd_ctx);
14679
14680 if (0 != ret)
14681 return ret;
14682
Krunal Sonib4326f22016-03-10 13:05:51 -080014683 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14684 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014685 return -ENOTSUPP;
14686
14687 freq = csa_params->chandef.chan->center_freq;
14688 channel = cds_freq_to_chan(freq);
14689
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014690 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14691
14692 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014693 return ret;
14694}
14695
14696/**
14697 * wlan_hdd_cfg80211_channel_switch()- function to switch
14698 * channel in SAP/GO
14699 * @wiphy: wiphy pointer
14700 * @dev: dev pointer.
14701 * @csa_params: Change channel params
14702 *
14703 * This function is called to switch channel in SAP/GO
14704 *
14705 * Return: 0 if success else return non zero
14706 */
14707static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14708 struct net_device *dev,
14709 struct cfg80211_csa_settings *csa_params)
14710{
14711 int ret;
14712
14713 cds_ssr_protect(__func__);
14714 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14715 cds_ssr_unprotect(__func__);
14716 return ret;
14717}
14718#endif
14719
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014720/**
14721 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14722 * translation from NL to policy manager type
14723 * @type: Generic connection mode type defined in NL
14724 *
14725 *
14726 * This function provides the type translation
14727 *
14728 * Return: cds_con_mode enum
14729 */
14730enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
14731 enum nl80211_iftype type)
14732{
14733 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
14734 switch (type) {
14735 case NL80211_IFTYPE_STATION:
14736 mode = CDS_STA_MODE;
14737 break;
14738 case NL80211_IFTYPE_P2P_CLIENT:
14739 mode = CDS_P2P_CLIENT_MODE;
14740 break;
14741 case NL80211_IFTYPE_P2P_GO:
14742 mode = CDS_P2P_GO_MODE;
14743 break;
14744 case NL80211_IFTYPE_AP:
14745 mode = CDS_SAP_MODE;
14746 break;
14747 case NL80211_IFTYPE_ADHOC:
14748 mode = CDS_IBSS_MODE;
14749 break;
14750 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014751 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014752 type);
14753 }
14754 return mode;
14755}
14756
14757/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014758 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14759 * @wiphy: Handle to struct wiphy to get handle to module context.
14760 * @chandef: Contains information about the capture channel to be set.
14761 *
14762 * This interface is called if and only if monitor mode interface alone is
14763 * active.
14764 *
14765 * Return: 0 success or error code on failure.
14766 */
14767static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14768 struct cfg80211_chan_def *chandef)
14769{
14770 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14771 hdd_adapter_t *adapter;
14772 hdd_station_ctx_t *sta_ctx;
14773 struct hdd_mon_set_ch_info *ch_info;
14774 QDF_STATUS status;
14775 tHalHandle hal_hdl;
14776 struct qdf_mac_addr bssid;
14777 tCsrRoamProfile roam_profile;
14778 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014779 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014780 int ret;
14781 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
14782
14783 ENTER();
14784
14785 ret = wlan_hdd_validate_context(hdd_ctx);
14786 if (ret)
14787 return ret;
14788
14789 hal_hdl = hdd_ctx->hHal;
14790
14791 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
14792 if (!adapter)
14793 return -EIO;
14794
14795 hdd_info("%s: set monitor mode Channel %d and freq %d",
14796 adapter->dev->name, chan_num, chandef->chan->center_freq);
14797
14798 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14799 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014800 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
14801 roam_profile.ChannelInfo.numOfChannels = 1;
14802 roam_profile.phyMode = ch_info->phy_mode;
14803 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014804 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014805
14806 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
14807 QDF_MAC_ADDR_SIZE);
14808
14809 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014810 /*
14811 * CDS api expects secondary channel for calculating
14812 * the channel params
14813 */
14814 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
14815 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
14816 if (chan_num >= 1 && chan_num <= 5)
14817 sec_ch = chan_num + 4;
14818 else if (chan_num >= 6 && chan_num <= 13)
14819 sec_ch = chan_num - 4;
14820 }
14821 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014822 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
14823 &roam_profile);
14824 if (status) {
14825 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
14826 status);
14827 ret = qdf_status_to_os_return(status);
14828 return ret;
14829 }
14830 EXIT();
14831 return 0;
14832}
14833
14834/**
14835 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14836 * @wiphy: Handle to struct wiphy to get handle to module context.
14837 * @chandef: Contains information about the capture channel to be set.
14838 *
14839 * This interface is called if and only if monitor mode interface alone is
14840 * active.
14841 *
14842 * Return: 0 success or error code on failure.
14843 */
14844static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14845 struct cfg80211_chan_def *chandef)
14846{
14847 int ret;
14848
14849 cds_ssr_protect(__func__);
14850 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
14851 cds_ssr_unprotect(__func__);
14852 return ret;
14853}
14854
14855/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014856 * struct cfg80211_ops - cfg80211_ops
14857 *
14858 * @add_virtual_intf: Add virtual interface
14859 * @del_virtual_intf: Delete virtual interface
14860 * @change_virtual_intf: Change virtual interface
14861 * @change_station: Change station
14862 * @add_beacon: Add beacon in sap mode
14863 * @del_beacon: Delete beacon in sap mode
14864 * @set_beacon: Set beacon in sap mode
14865 * @start_ap: Start ap
14866 * @change_beacon: Change beacon
14867 * @stop_ap: Stop ap
14868 * @change_bss: Change bss
14869 * @add_key: Add key
14870 * @get_key: Get key
14871 * @del_key: Delete key
14872 * @set_default_key: Set default key
14873 * @set_channel: Set channel
14874 * @scan: Scan
14875 * @connect: Connect
14876 * @disconnect: Disconnect
14877 * @join_ibss = Join ibss
14878 * @leave_ibss = Leave ibss
14879 * @set_wiphy_params = Set wiphy params
14880 * @set_tx_power = Set tx power
14881 * @get_tx_power = get tx power
14882 * @remain_on_channel = Remain on channel
14883 * @cancel_remain_on_channel = Cancel remain on channel
14884 * @mgmt_tx = Tx management frame
14885 * @mgmt_tx_cancel_wait = Cancel management tx wait
14886 * @set_default_mgmt_key = Set default management key
14887 * @set_txq_params = Set tx queue parameters
14888 * @get_station = Get station
14889 * @set_power_mgmt = Set power management
14890 * @del_station = Delete station
14891 * @add_station = Add station
14892 * @set_pmksa = Set pmksa
14893 * @del_pmksa = Delete pmksa
14894 * @flush_pmksa = Flush pmksa
14895 * @update_ft_ies = Update FT IEs
14896 * @tdls_mgmt = Tdls management
14897 * @tdls_oper = Tdls operation
14898 * @set_rekey_data = Set rekey data
14899 * @sched_scan_start = Scheduled scan start
14900 * @sched_scan_stop = Scheduled scan stop
14901 * @resume = Resume wlan
14902 * @suspend = Suspend wlan
14903 * @set_mac_acl = Set mac acl
14904 * @testmode_cmd = Test mode command
14905 * @set_ap_chanwidth = Set AP channel bandwidth
14906 * @dump_survey = Dump survey
14907 * @key_mgmt_set_pmk = Set pmk key management
14908 */
14909static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
14910 .add_virtual_intf = wlan_hdd_add_virtual_intf,
14911 .del_virtual_intf = wlan_hdd_del_virtual_intf,
14912 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
14913 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014914 .start_ap = wlan_hdd_cfg80211_start_ap,
14915 .change_beacon = wlan_hdd_cfg80211_change_beacon,
14916 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014917 .change_bss = wlan_hdd_cfg80211_change_bss,
14918 .add_key = wlan_hdd_cfg80211_add_key,
14919 .get_key = wlan_hdd_cfg80211_get_key,
14920 .del_key = wlan_hdd_cfg80211_del_key,
14921 .set_default_key = wlan_hdd_cfg80211_set_default_key,
14922 .scan = wlan_hdd_cfg80211_scan,
14923 .connect = wlan_hdd_cfg80211_connect,
14924 .disconnect = wlan_hdd_cfg80211_disconnect,
14925 .join_ibss = wlan_hdd_cfg80211_join_ibss,
14926 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
14927 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
14928 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
14929 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
14930 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
14931 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
14932 .mgmt_tx = wlan_hdd_mgmt_tx,
14933 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
14934 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
14935 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053014936 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014937 .get_station = wlan_hdd_cfg80211_get_station,
14938 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
14939 .del_station = wlan_hdd_cfg80211_del_station,
14940 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014941 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
14942 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
14943 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014944#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014945 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
14946#endif
14947#ifdef FEATURE_WLAN_TDLS
14948 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
14949 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
14950#endif
14951#ifdef WLAN_FEATURE_GTK_OFFLOAD
14952 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
14953#endif /* WLAN_FEATURE_GTK_OFFLOAD */
14954#ifdef FEATURE_WLAN_SCAN_PNO
14955 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
14956 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
14957#endif /*FEATURE_WLAN_SCAN_PNO */
14958 .resume = wlan_hdd_cfg80211_resume_wlan,
14959 .suspend = wlan_hdd_cfg80211_suspend_wlan,
14960 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
14961#ifdef WLAN_NL80211_TESTMODE
14962 .testmode_cmd = wlan_hdd_cfg80211_testmode,
14963#endif
14964#ifdef QCA_HT_2040_COEX
14965 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
14966#endif
14967 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014968#ifdef CHANNEL_SWITCH_SUPPORTED
14969 .channel_switch = wlan_hdd_cfg80211_channel_switch,
14970#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014971 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053014972#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
14973 defined(CFG80211_ABORT_SCAN)
14974 .abort_scan = wlan_hdd_cfg80211_abort_scan,
14975#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014976};