blob: ce3e7907bb883ee320d252506f9bb3599df2d77b [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
1489 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1490 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1491 } else {
1492 if (ht_enabled && ht40_enabled)
1493 ch_width = 40;
1494 else
1495 ch_width = 20;
1496 }
1497 if (ch_width == 80)
1498 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1499 else if (ch_width == 40)
1500 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1501 else
1502 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1503
1504 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1505 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1506 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1507 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1508 * since it contains the frequency values of the channels in
1509 * the channel list.
1510 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1511 * is present
1512 */
1513 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1514 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1515 sap_config->acs_cfg.ch_list_count = nla_len(
1516 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1517 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301518 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519 sizeof(uint8_t) *
1520 sap_config->acs_cfg.ch_list_count);
1521 if (sap_config->acs_cfg.ch_list == NULL)
1522 goto out;
1523
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301524 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001525 sap_config->acs_cfg.ch_list_count);
1526 }
1527 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1528 uint32_t *freq =
1529 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1530 sap_config->acs_cfg.ch_list_count = nla_len(
1531 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1532 sizeof(uint32_t);
1533 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301534 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001535 sap_config->acs_cfg.ch_list_count);
1536 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001537 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001538 status = -ENOMEM;
1539 goto out;
1540 }
1541
1542 /* convert frequency to channel */
1543 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1544 sap_config->acs_cfg.ch_list[i] =
1545 ieee80211_frequency_to_channel(freq[i]);
1546 }
1547 }
1548
1549 hdd_debug("get pcl for DO_ACS vendor command");
1550
1551 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001552 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301553 sap_config->acs_cfg.pcl_channels,
1554 &sap_config->acs_cfg.pcl_ch_count,
1555 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301556 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001557 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001559 /* ACS override for android */
1560 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled) {
Jeff Johnson020db452016-06-29 14:37:26 -07001561 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001562 vht_enabled = 1;
1563 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1564 sap_config->acs_cfg.ch_width =
1565 hdd_ctx->config->vhtChannelWidth;
1566 /* No VHT80 in 2.4G so perform ACS accordingly */
1567 if (sap_config->acs_cfg.end_ch <= 14 &&
1568 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1569 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1570 }
1571
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301572 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1573
Jeff Johnson020db452016-06-29 14:37:26 -07001574 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 -08001575 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1576 ch_width, ht_enabled, vht_enabled,
1577 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1578
1579 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001580 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001581 sap_config->acs_cfg.ch_list_count);
1582 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001583 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001584 }
1585 sap_config->acs_cfg.acs_mode = true;
1586 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001587 /* ***Note*** Completion variable usage is not allowed
1588 * here since ACS scan operation may take max 2.2 sec
1589 * for 5G band:
1590 * 9 Active channel X 40 ms active scan time +
1591 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001592 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1593 * for this long. So we split up the scanning part.
1594 */
1595 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001596 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001597 status = 0;
1598 } else {
1599 status = wlan_hdd_cfg80211_start_acs(adapter);
1600 }
1601
1602out:
1603 if (0 == status) {
1604 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1605 NLMSG_HDRLEN);
1606 if (temp_skbuff != NULL)
1607 return cfg80211_vendor_cmd_reply(temp_skbuff);
1608 }
1609
1610 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1611
1612 return status;
1613}
1614
1615 /**
1616 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1617 * @wiphy: Linux wiphy struct pointer
1618 * @wdev: Linux wireless device struct pointer
1619 * @data: ACS information from hostapd
1620 * @data_len: ACS information len
1621 *
1622 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1623 * and starts ACS procedure.
1624 *
1625 * Return: ACS procedure start status
1626 */
1627
1628static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1629 struct wireless_dev *wdev,
1630 const void *data, int data_len)
1631{
1632 int ret;
1633
1634 cds_ssr_protect(__func__);
1635 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1636 cds_ssr_unprotect(__func__);
1637
1638 return ret;
1639}
1640
1641/**
1642 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1643 * @work: Linux workqueue struct pointer for ACS work
1644 *
1645 * This function starts the ACS procedure which was marked pending when an ACS
1646 * procedure was in progress for a concurrent SAP interface.
1647 *
1648 * Return: None
1649 */
1650
1651static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1652{
1653 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1654 acs_pending_work.work);
1655 wlan_hdd_cfg80211_start_acs(adapter);
1656}
1657
1658/**
1659 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1660 * @adapter: Pointer to SAP adapter struct
1661 * @pri_channel: SAP ACS procedure selected Primary channel
1662 * @sec_channel: SAP ACS procedure selected secondary channel
1663 *
1664 * This is a callback function from SAP module on ACS procedure is completed.
1665 * This function send the ACS selected channel information to hostapd
1666 *
1667 * Return: None
1668 */
1669
1670void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1671{
1672 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1673 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1674 struct sk_buff *vendor_event;
1675 int ret_val;
1676 hdd_adapter_t *con_sap_adapter;
1677 uint16_t ch_width;
1678
1679 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001680 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001681 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1682 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1683 GFP_KERNEL);
1684
1685 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001686 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001687 return;
1688 }
1689
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001690 ret_val = nla_put_u8(vendor_event,
1691 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1692 sap_cfg->acs_cfg.pri_ch);
1693 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001694 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001695 kfree_skb(vendor_event);
1696 return;
1697 }
1698
1699 ret_val = nla_put_u8(vendor_event,
1700 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1701 sap_cfg->acs_cfg.ht_sec_ch);
1702 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001703 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001704 kfree_skb(vendor_event);
1705 return;
1706 }
1707
1708 ret_val = nla_put_u8(vendor_event,
1709 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1710 sap_cfg->acs_cfg.vht_seg0_center_ch);
1711 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001712 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001713 kfree_skb(vendor_event);
1714 return;
1715 }
1716
1717 ret_val = nla_put_u8(vendor_event,
1718 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1719 sap_cfg->acs_cfg.vht_seg1_center_ch);
1720 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001721 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001722 kfree_skb(vendor_event);
1723 return;
1724 }
1725
1726 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1727 ch_width = 80;
1728 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1729 ch_width = 40;
1730 else
1731 ch_width = 20;
1732
1733 ret_val = nla_put_u16(vendor_event,
1734 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1735 ch_width);
1736 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001737 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001738 kfree_skb(vendor_event);
1739 return;
1740 }
1741 if (sap_cfg->acs_cfg.pri_ch > 14)
1742 ret_val = nla_put_u8(vendor_event,
1743 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1744 QCA_ACS_MODE_IEEE80211A);
1745 else
1746 ret_val = nla_put_u8(vendor_event,
1747 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1748 QCA_ACS_MODE_IEEE80211G);
1749
1750 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001751 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001752 kfree_skb(vendor_event);
1753 return;
1754 }
1755
Jeff Johnson46b40792016-06-29 14:03:14 -07001756 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 -08001757 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1758 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1759 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1760
1761 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1762 /* ***Note*** As already mentioned Completion variable usage is not
1763 * allowed here since ACS scan operation may take max 2.2 sec.
1764 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1765 * operation.
1766 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1767 * when Primary AP ACS is complete and secondary AP ACS is started here
1768 * immediately, Primary AP start_bss may come inbetween ACS operation
1769 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1770 * delay. This path and below constraint will be removed on sessionizing
1771 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1772 * As per design constraint user space control application must take
1773 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1774 * this code path. Sec AP hostapd should be started after Primary AP
1775 * start beaconing which can be confirmed by getchannel iwpriv command
1776 */
1777
1778 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1779 if (con_sap_adapter &&
1780 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001781 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1782 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001783 /* Lets give 500ms for OBSS + START_BSS to complete */
1784 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1785 msecs_to_jiffies(500));
1786 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1787 }
1788
1789 return;
1790}
1791
1792static int
1793__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1794 struct wireless_dev *wdev,
1795 const void *data,
1796 int data_len)
1797{
1798 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1799 struct sk_buff *skb = NULL;
1800 uint32_t fset = 0;
1801 int ret;
1802
Jeff Johnson1f61b612016-02-12 16:28:33 -08001803 ENTER_DEV(wdev->netdev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301804
Anurag Chouhan6d760662016-02-20 16:05:43 +05301805 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001806 hdd_err("Command not allowed in FTM mode");
1807 return -EPERM;
1808 }
1809
1810 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301811 if (ret)
1812 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001813
1814 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001815 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001816 fset |= WIFI_FEATURE_INFRA;
1817 }
1818 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001819 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001820 fset |= WIFI_FEATURE_INFRA_5G;
1821 }
1822#ifdef WLAN_FEATURE_P2P
1823 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1824 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001825 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826 fset |= WIFI_FEATURE_P2P;
1827 }
1828#endif
1829 fset |= WIFI_FEATURE_SOFT_AP;
1830
1831 /* HOTSPOT is a supplicant feature, enable it by default */
1832 fset |= WIFI_FEATURE_HOTSPOT;
1833
1834#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301835 if (pHddCtx->config->extscan_enabled &&
1836 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001837 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001838 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1839 }
1840#endif
1841 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001842 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843 fset |= WIFI_FEATURE_NAN;
1844 }
1845 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001846 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 fset |= WIFI_FEATURE_D2D_RTT;
1848 fset |= WIFI_FEATURE_D2AP_RTT;
1849 }
1850#ifdef FEATURE_WLAN_SCAN_PNO
1851 if (pHddCtx->config->configPNOScanSupport &&
1852 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001853 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001854 fset |= WIFI_FEATURE_PNO;
1855 }
1856#endif
1857 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1858#ifdef FEATURE_WLAN_TDLS
1859 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1860 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001861 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001862 fset |= WIFI_FEATURE_TDLS;
1863 }
1864 if (sme_is_feature_supported_by_fw(TDLS) &&
1865 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1866 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001867 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001868 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1869 }
1870#endif
1871#ifdef WLAN_AP_STA_CONCURRENCY
1872 fset |= WIFI_FEATURE_AP_STA;
1873#endif
1874 fset |= WIFI_FEATURE_RSSI_MONITOR;
1875
1876 if (hdd_link_layer_stats_supported())
1877 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1878
1879 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1880 NLMSG_HDRLEN);
1881 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001882 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001883 return -EINVAL;
1884 }
Jeff Johnson020db452016-06-29 14:37:26 -07001885 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001887 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888 goto nla_put_failure;
1889 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301890 ret = cfg80211_vendor_cmd_reply(skb);
1891 EXIT();
1892 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001893nla_put_failure:
1894 kfree_skb(skb);
1895 return -EINVAL;
1896}
1897
1898/**
1899 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1900 * @wiphy: pointer to wireless wiphy structure.
1901 * @wdev: pointer to wireless_dev structure.
1902 * @data: Pointer to the data to be passed via vendor interface
1903 * @data_len:Length of the data to be passed
1904 *
1905 * Return: Return the Success or Failure code.
1906 */
1907static int
1908wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1909 struct wireless_dev *wdev,
1910 const void *data, int data_len)
1911{
1912 int ret = 0;
1913
1914 cds_ssr_protect(__func__);
1915 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1916 data, data_len);
1917 cds_ssr_unprotect(__func__);
1918
1919 return ret;
1920}
1921
1922/**
1923 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1924 * @wiphy: pointer to wireless wiphy structure.
1925 * @wdev: pointer to wireless_dev structure.
1926 * @data: Pointer to the data to be passed via vendor interface
1927 * @data_len:Length of the data to be passed
1928 *
1929 * Set the MAC address that is to be used for scanning.
1930 *
1931 * Return: Return the Success or Failure code.
1932 */
1933static int
1934__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1935 struct wireless_dev *wdev,
1936 const void *data,
1937 int data_len)
1938{
1939 tpSirScanMacOui pReqMsg = NULL;
1940 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1941 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301942 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943 int ret;
1944
Jeff Johnson1f61b612016-02-12 16:28:33 -08001945 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946
Anurag Chouhan6d760662016-02-20 16:05:43 +05301947 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001948 hdd_err("Command not allowed in FTM mode");
1949 return -EPERM;
1950 }
1951
1952 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301953 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001955
1956 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001957 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001958 return -ENOTSUPP;
1959 }
1960
1961 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1962 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001963 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001964 return -EINVAL;
1965 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301966 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001967 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07001968 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001969 return -ENOMEM;
1970 }
1971 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001972 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973 goto fail;
1974 }
1975 nla_memcpy(&pReqMsg->oui[0],
1976 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
1977 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07001978 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 pReqMsg->oui[1], pReqMsg->oui[2]);
1980 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301981 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001982 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983 goto fail;
1984 }
1985 return 0;
1986fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301987 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988 return -EINVAL;
1989}
1990
1991/**
1992 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1993 * @wiphy: pointer to wireless wiphy structure.
1994 * @wdev: pointer to wireless_dev structure.
1995 * @data: Pointer to the data to be passed via vendor interface
1996 * @data_len:Length of the data to be passed
1997 *
1998 * Set the MAC address that is to be used for scanning. This is an
1999 * SSR-protecting wrapper function.
2000 *
2001 * Return: Return the Success or Failure code.
2002 */
2003static int
2004wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2005 struct wireless_dev *wdev,
2006 const void *data,
2007 int data_len)
2008{
2009 int ret;
2010
2011 cds_ssr_protect(__func__);
2012 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2013 data, data_len);
2014 cds_ssr_unprotect(__func__);
2015
2016 return ret;
2017}
2018
2019/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302020 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2021 * @wiphy: pointer phy adapter
2022 * @wdev: pointer to wireless device structure
2023 * @data: pointer to data buffer
2024 * @data_len: length of data
2025 *
2026 * This routine will give concurrency matrix
2027 *
2028 * Return: int status code
2029 */
2030static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2031 struct wireless_dev *wdev,
2032 const void *data,
2033 int data_len)
2034{
2035 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2036 uint8_t i, feature_sets, max_feature_sets;
2037 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2038 struct sk_buff *reply_skb;
2039 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2040 int ret;
2041
2042 ENTER_DEV(wdev->netdev);
2043
2044 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2045 hdd_err("Command not allowed in FTM mode");
2046 return -EPERM;
2047 }
2048
2049 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302050 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302051 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302052
2053 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2054 data, data_len, NULL)) {
2055 hdd_err("Invalid ATTR");
2056 return -EINVAL;
2057 }
2058
2059 /* Parse and fetch max feature set */
2060 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2061 hdd_err("Attr max feature set size failed");
2062 return -EINVAL;
2063 }
2064 max_feature_sets = nla_get_u32(tb[
2065 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2066 hdd_info("Max feature set size: %d", max_feature_sets);
2067
2068 /* Fill feature combination matrix */
2069 feature_sets = 0;
2070 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2071 WIFI_FEATURE_P2P;
2072 /* Add more feature combinations here */
2073
2074 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
2075 hdd_info("Number of feature sets:%d", feature_sets);
2076 hdd_info("Feature set matrix");
2077 for (i = 0; i < feature_sets; i++)
2078 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2079
2080 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2081 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2082 if (!reply_skb) {
2083 hdd_err("Feature set matrix: buffer alloc fail");
2084 return -ENOMEM;
2085 }
2086
2087 if (nla_put_u32(reply_skb,
2088 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2089 feature_sets) ||
2090 nla_put(reply_skb,
2091 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2092 sizeof(u32) * feature_sets,
2093 feature_set_matrix)) {
2094 hdd_err("nla put fail");
2095 kfree_skb(reply_skb);
2096 return -EINVAL;
2097 }
2098 return cfg80211_vendor_cmd_reply(reply_skb);
2099}
2100
2101/**
2102 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2103 * @wiphy: pointer to wireless wiphy structure.
2104 * @wdev: pointer to wireless_dev structure.
2105 * @data: Pointer to the data to be passed via vendor interface
2106 * @data_len:Length of the data to be passed
2107 *
2108 * Retrieves the concurrency feature set matrix
2109 *
2110 * Return: 0 on success, negative errno on failure
2111 */
2112static int
2113wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2114 struct wireless_dev *wdev,
2115 const void *data,
2116 int data_len)
2117{
2118 int ret;
2119
2120 cds_ssr_protect(__func__);
2121 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2122 data, data_len);
2123 cds_ssr_unprotect(__func__);
2124
2125 return ret;
2126}
2127
2128/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002129 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2130 * @feature_flags: pointer to the byte array of features.
2131 * @feature: Feature to be turned ON in the byte array.
2132 *
2133 * Return: None
2134 *
2135 * This is called to turn ON or SET the feature flag for the requested feature.
2136 **/
2137#define NUM_BITS_IN_BYTE 8
2138void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags, uint8_t feature)
2139{
2140 uint32_t index;
2141 uint8_t bit_mask;
2142
2143 index = feature / NUM_BITS_IN_BYTE;
2144 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2145 feature_flags[index] |= bit_mask;
2146}
2147
2148/**
2149 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2150 * @wiphy: pointer to wireless wiphy structure.
2151 * @wdev: pointer to wireless_dev structure.
2152 * @data: Pointer to the data to be passed via vendor interface
2153 * @data_len:Length of the data to be passed
2154 *
2155 * This is called when wlan driver needs to send supported feature set to
2156 * supplicant upon a request/query from the supplicant.
2157 *
2158 * Return: Return the Success or Failure code.
2159 **/
2160#define MAX_CONCURRENT_CHAN_ON_24G 2
2161#define MAX_CONCURRENT_CHAN_ON_5G 2
2162static int
2163__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2164 struct wireless_dev *wdev,
2165 const void *data, int data_len)
2166{
2167 struct sk_buff *skb = NULL;
2168 uint32_t dbs_capability = 0;
2169 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302170 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171 int ret_val;
2172
2173 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2174 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2175
Jeff Johnson1f61b612016-02-12 16:28:33 -08002176 ENTER_DEV(wdev->netdev);
2177
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002178 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2179 if (ret_val)
2180 return ret_val;
2181
Anurag Chouhan6d760662016-02-20 16:05:43 +05302182 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183 hdd_err("Command not allowed in FTM mode");
2184 return -EPERM;
2185 }
2186
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002187 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002188 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002189 wlan_hdd_cfg80211_set_feature(feature_flags,
2190 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2191 }
2192
2193 wlan_hdd_cfg80211_set_feature(feature_flags,
2194 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2195 if (wma_is_scan_simultaneous_capable())
2196 wlan_hdd_cfg80211_set_feature(feature_flags,
2197 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002198
2199 if (wma_is_p2p_lo_capable())
2200 wlan_hdd_cfg80211_set_feature(feature_flags,
2201 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2202
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002203 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2204 NLMSG_HDRLEN);
2205
2206 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002207 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208 return -ENOMEM;
2209 }
2210
2211 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2212 sizeof(feature_flags), feature_flags))
2213 goto nla_put_failure;
2214
2215 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302216 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002217 if (one_by_one_dbs)
2218 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2219
2220 if (two_by_two_dbs)
2221 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2222
2223 if (!one_by_one_dbs && !two_by_two_dbs)
2224 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2225 } else {
2226 hdd_err("wma_get_dbs_hw_mode failed");
2227 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2228 }
2229
2230 hdd_info("dbs_capability is %d", dbs_capability);
2231
2232 if (nla_put_u32(skb,
2233 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2234 MAX_CONCURRENT_CHAN_ON_24G))
2235 goto nla_put_failure;
2236
2237 if (nla_put_u32(skb,
2238 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2239 MAX_CONCURRENT_CHAN_ON_5G))
2240 goto nla_put_failure;
2241
2242 return cfg80211_vendor_cmd_reply(skb);
2243
2244nla_put_failure:
2245 kfree_skb(skb);
2246 return -EINVAL;
2247}
2248
2249/**
2250 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2251 * @wiphy: pointer to wireless wiphy structure.
2252 * @wdev: pointer to wireless_dev structure.
2253 * @data: Pointer to the data to be passed via vendor interface
2254 * @data_len:Length of the data to be passed
2255 *
2256 * This is called when wlan driver needs to send supported feature set to
2257 * supplicant upon a request/query from the supplicant.
2258 *
2259 * Return: Return the Success or Failure code.
2260 */
2261static int
2262wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2263 struct wireless_dev *wdev,
2264 const void *data, int data_len)
2265{
2266 int ret;
2267
2268 cds_ssr_protect(__func__);
2269 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2270 data, data_len);
2271 cds_ssr_unprotect(__func__);
2272
2273 return ret;
2274}
2275
2276
2277/**
2278 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2279 * @wiphy: The wiphy structure
2280 * @wdev: The wireless device
2281 * @data: Data passed by framework
2282 * @data_len: Parameters to be configured passed as data
2283 *
2284 * The roaming related parameters are configured by the framework
2285 * using this interface.
2286 *
2287 * Return: Return either success or failure code.
2288 */
2289static int
2290__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2291 struct wireless_dev *wdev, const void *data, int data_len)
2292{
2293 struct net_device *dev = wdev->netdev;
2294 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2295 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2296 uint8_t session_id;
2297 struct roam_ext_params roam_params;
2298 uint32_t cmd_type, req_id;
2299 struct nlattr *curr_attr;
2300 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2301 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2302 int rem, i;
2303 uint32_t buf_len = 0;
2304 int ret;
2305
Jeff Johnson1f61b612016-02-12 16:28:33 -08002306 ENTER_DEV(dev);
2307
Anurag Chouhan6d760662016-02-20 16:05:43 +05302308 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002309 hdd_err("Command not allowed in FTM mode");
2310 return -EPERM;
2311 }
2312
2313 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302314 if (ret)
2315 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002316
2317 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2318 data, data_len,
2319 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002320 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002321 return -EINVAL;
2322 }
2323 /* Parse and fetch Command Type*/
2324 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002325 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002326 goto fail;
2327 }
2328 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302329 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002330 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2331 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002332 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002333 goto fail;
2334 }
2335 req_id = nla_get_u32(
2336 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002337 hdd_debug("Req Id (%d)", req_id);
2338 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002339 switch (cmd_type) {
2340 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2341 i = 0;
2342 nla_for_each_nested(curr_attr,
2343 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2344 rem) {
2345 if (nla_parse(tb2,
2346 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2347 nla_data(curr_attr), nla_len(curr_attr),
2348 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002349 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002350 goto fail;
2351 }
2352 /* Parse and Fetch allowed SSID list*/
2353 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002354 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002355 goto fail;
2356 }
2357 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2358 /*
2359 * Upper Layers include a null termination character.
2360 * Check for the actual permissible length of SSID and
2361 * also ensure not to copy the NULL termination
2362 * character to the driver buffer.
2363 */
2364 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2365 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2366 nla_memcpy(
2367 roam_params.ssid_allowed_list[i].ssId,
2368 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2369 buf_len - 1);
2370 roam_params.ssid_allowed_list[i].length =
2371 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002372 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002373 roam_params.ssid_allowed_list[i].length,
2374 roam_params.ssid_allowed_list[i].ssId,
2375 roam_params.ssid_allowed_list[i].length);
2376 i++;
2377 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002378 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379 }
2380 }
2381 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002382 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383 roam_params.num_ssid_allowed_list);
2384 sme_update_roam_params(pHddCtx->hHal, session_id,
2385 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2386 break;
2387 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2388 /* Parse and fetch 5G Boost Threshold */
2389 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002390 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002391 goto fail;
2392 }
2393 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2394 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002395 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002396 roam_params.raise_rssi_thresh_5g);
2397 /* Parse and fetch 5G Penalty Threshold */
2398 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002399 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002400 goto fail;
2401 }
2402 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2403 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002404 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002405 roam_params.drop_rssi_thresh_5g);
2406 /* Parse and fetch 5G Boost Factor */
2407 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002408 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002409 goto fail;
2410 }
2411 roam_params.raise_factor_5g = nla_get_u32(
2412 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002413 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002414 roam_params.raise_factor_5g);
2415 /* Parse and fetch 5G Penalty factor */
2416 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002417 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002418 goto fail;
2419 }
2420 roam_params.drop_factor_5g = nla_get_u32(
2421 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002422 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002423 roam_params.drop_factor_5g);
2424 /* Parse and fetch 5G Max Boost */
2425 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002426 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002427 goto fail;
2428 }
2429 roam_params.max_raise_rssi_5g = nla_get_u32(
2430 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002431 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002432 roam_params.max_raise_rssi_5g);
2433 /* Parse and fetch Rssi Diff */
2434 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002435 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002436 goto fail;
2437 }
2438 roam_params.rssi_diff = nla_get_s32(
2439 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002440 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002441 roam_params.rssi_diff);
2442 /* Parse and fetch Alert Rssi Threshold */
2443 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002444 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 goto fail;
2446 }
2447 roam_params.alert_rssi_threshold = nla_get_u32(
2448 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002449 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450 roam_params.alert_rssi_threshold);
2451 sme_update_roam_params(pHddCtx->hHal, session_id,
2452 roam_params,
2453 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2454 break;
2455 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2456 /* Parse and fetch Activate Good Rssi Roam */
2457 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002458 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002459 goto fail;
2460 }
2461 roam_params.good_rssi_roam = nla_get_s32(
2462 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002463 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464 roam_params.good_rssi_roam);
2465 sme_update_roam_params(pHddCtx->hHal, session_id,
2466 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2467 break;
2468 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2469 /* Parse and fetch number of preferred BSSID */
2470 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002471 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 goto fail;
2473 }
2474 roam_params.num_bssid_favored = nla_get_u32(
2475 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002476 hdd_debug("Num of Preferred BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002477 roam_params.num_bssid_favored);
2478 i = 0;
2479 nla_for_each_nested(curr_attr,
2480 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2481 rem) {
2482 if (nla_parse(tb2,
2483 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2484 nla_data(curr_attr), nla_len(curr_attr),
2485 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002486 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002487 goto fail;
2488 }
2489 /* Parse and fetch MAC address */
2490 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002491 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002492 goto fail;
2493 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002494 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002495 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302496 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002497 hdd_debug(MAC_ADDRESS_STR,
2498 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002499 /* Parse and fetch preference factor*/
2500 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002501 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002502 goto fail;
2503 }
2504 roam_params.bssid_favored_factor[i] = nla_get_u32(
2505 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002506 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002507 roam_params.bssid_favored_factor[i]);
2508 i++;
2509 }
2510 sme_update_roam_params(pHddCtx->hHal, session_id,
2511 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2512 break;
2513 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2514 /* Parse and fetch number of blacklist BSSID */
2515 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002516 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002517 goto fail;
2518 }
2519 roam_params.num_bssid_avoid_list = nla_get_u32(
2520 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002521 hdd_debug("Num of blacklist BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522 roam_params.num_bssid_avoid_list);
2523 i = 0;
2524 nla_for_each_nested(curr_attr,
2525 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2526 rem) {
2527 if (nla_parse(tb2,
2528 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2529 nla_data(curr_attr), nla_len(curr_attr),
2530 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002531 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002532 goto fail;
2533 }
2534 /* Parse and fetch MAC address */
2535 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002536 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002537 goto fail;
2538 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002539 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002540 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302541 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002542 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002543 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002544 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545 i++;
2546 }
2547 sme_update_roam_params(pHddCtx->hHal, session_id,
2548 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2549 break;
2550 }
2551 return 0;
2552fail:
2553 return -EINVAL;
2554}
2555
2556/**
2557 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2558 * @wiphy: pointer to wireless wiphy structure.
2559 * @wdev: pointer to wireless_dev structure.
2560 * @data: Pointer to the data to be passed via vendor interface
2561 * @data_len:Length of the data to be passed
2562 *
2563 * Return: Return the Success or Failure code.
2564 */
2565static int
2566wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2567 struct wireless_dev *wdev,
2568 const void *data,
2569 int data_len)
2570{
2571 int ret;
2572
2573 cds_ssr_protect(__func__);
2574 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2575 data, data_len);
2576 cds_ssr_unprotect(__func__);
2577
2578 return ret;
2579}
2580
2581static const struct nla_policy
2582wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2583 +1] = {
2584 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2585};
2586
2587/**
2588 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2589 * @hdd_ctx: HDD context
2590 * @device_mode: device mode
2591 * Return: bool
2592 */
2593static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002594 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595{
2596 hdd_adapter_t *adapter;
2597 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2598 hdd_ap_ctx_t *ap_ctx;
2599 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302600 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002601
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302602 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603 &adapter_node);
2604
2605 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302606 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002607 adapter = adapter_node->pAdapter;
2608
2609 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002610 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002611 ap_ctx =
2612 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2613
2614 /*
2615 * if there is SAP already running on DFS channel,
2616 * do not disable scan on dfs channels. Note that
2617 * with SAP on DFS, there cannot be conurrency on
2618 * single radio. But then we can have multiple
2619 * radios !!
2620 */
2621 if (CHANNEL_STATE_DFS ==
2622 cds_get_channel_state(
2623 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002624 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625 return true;
2626 }
2627 }
2628
2629 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002630 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002631 sta_ctx =
2632 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2633
2634 /*
2635 * if STA is already connected on DFS channel,
2636 * do not disable scan on dfs channels
2637 */
2638 if (hdd_conn_is_connected(sta_ctx) &&
2639 (CHANNEL_STATE_DFS ==
2640 cds_get_channel_state(
2641 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002642 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002643 return true;
2644 }
2645 }
2646
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302647 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002648 adapter_node,
2649 &next);
2650 adapter_node = next;
2651 }
2652
2653 return false;
2654}
2655
2656/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002657 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2658 * @hdd_ctx: HDD context within host driver
2659 * @adapter: Adapter pointer
2660 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2661 *
2662 * Loops through devices to see who is operating on DFS channels
2663 * and then disables/enables DFS channels by calling SME API.
2664 * Fails the disable request if any device is active on a DFS channel.
2665 *
2666 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002667 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002668
2669int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2670 hdd_adapter_t *adapter,
2671 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002672{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002673 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302674 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676
2677 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2678 if (no_dfs_flag) {
2679 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002680 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681
2682 if (true == status)
2683 return -EOPNOTSUPP;
2684
2685 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002686 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002687
2688 if (true == status)
2689 return -EOPNOTSUPP;
2690 }
2691
2692 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2693
2694 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2695
2696 /*
2697 * call the SME API to tunnel down the new channel list
2698 * to the firmware
2699 */
2700 status = sme_handle_dfs_chan_scan(
2701 h_hal, hdd_ctx->config->enableDFSChnlScan);
2702
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302703 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002704 ret_val = 0;
2705
2706 /*
2707 * Clear the SME scan cache also. Note that the
2708 * clearing of scan results is independent of session;
2709 * so no need to iterate over
2710 * all sessions
2711 */
2712 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302713 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714 ret_val = -EPERM;
2715 }
2716
2717 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002718 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002719 ret_val = 0;
2720 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002721 return ret_val;
2722}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002723
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002724/**
2725 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2726 * @wiphy: corestack handler
2727 * @wdev: wireless device
2728 * @data: data
2729 * @data_len: data length
2730 * Return: success(0) or reason code for failure
2731 */
2732static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2733 struct wireless_dev *wdev,
2734 const void *data,
2735 int data_len)
2736{
2737 struct net_device *dev = wdev->netdev;
2738 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2739 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2740 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2741 int ret_val;
2742 uint32_t no_dfs_flag = 0;
2743
Jeff Johnson1f61b612016-02-12 16:28:33 -08002744 ENTER_DEV(dev);
2745
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002746 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302747 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002748 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002749
2750 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2751 data, data_len,
2752 wlan_hdd_set_no_dfs_flag_config_policy)) {
2753 hdd_err("invalid attr");
2754 return -EINVAL;
2755 }
2756
2757 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2758 hdd_err("attr dfs flag failed");
2759 return -EINVAL;
2760 }
2761
2762 no_dfs_flag = nla_get_u32(
2763 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2764
Jeff Johnson020db452016-06-29 14:37:26 -07002765 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002766
2767 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002768 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002769 return -EINVAL;
2770 }
2771
2772 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2773 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002774 return ret_val;
2775}
2776
2777/**
2778 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2779 *
2780 * @wiphy: wiphy device pointer
2781 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002782 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002783 * @data_len: Buffer length
2784 *
2785 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2786 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2787 *
2788 * Return: EOK or other error codes.
2789 */
2790
2791static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2792 struct wireless_dev *wdev,
2793 const void *data,
2794 int data_len)
2795{
2796 int ret;
2797
2798 cds_ssr_protect(__func__);
2799 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2800 data, data_len);
2801 cds_ssr_unprotect(__func__);
2802
2803 return ret;
2804}
2805
Manikandan Mohan80dea792016-04-28 16:36:48 -07002806static const struct nla_policy
2807wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2808 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2809};
2810
2811/**
2812 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2813 * @wiphy: wiphy device pointer
2814 * @wdev: wireless device pointer
2815 * @data: Vendor command data buffer
2816 * @data_len: Buffer length
2817 *
2818 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2819 * setup WISA Mode features.
2820 *
2821 * Return: Success(0) or reason code for failure
2822 */
2823static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2824 struct wireless_dev *wdev, const void *data, int data_len)
2825{
2826 struct net_device *dev = wdev->netdev;
2827 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2828 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2829 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2830 struct sir_wisa_params wisa;
2831 int ret_val;
2832 QDF_STATUS status;
2833 bool wisa_mode;
2834
2835 ENTER_DEV(dev);
2836 ret_val = wlan_hdd_validate_context(hdd_ctx);
2837 if (ret_val)
2838 goto err;
2839
2840 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2841 hdd_err("Command not allowed in FTM mode");
2842 return -EPERM;
2843 }
2844
2845 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2846 wlan_hdd_wisa_cmd_policy)) {
2847 hdd_err("Invalid WISA cmd attributes");
2848 ret_val = -EINVAL;
2849 goto err;
2850 }
2851 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2852 hdd_err("Invalid WISA mode");
2853 ret_val = -EINVAL;
2854 goto err;
2855 }
2856
2857 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2858 hdd_info("WISA Mode: %d", wisa_mode);
2859 wisa.mode = wisa_mode;
2860 wisa.vdev_id = adapter->sessionId;
2861 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002862 if (!QDF_IS_STATUS_SUCCESS(status)) {
2863 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002864 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002865 }
2866 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
2867 ol_txrx_set_wisa_mode(ol_txrx_get_vdev_from_vdev_id(
2868 adapter->sessionId), wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002869err:
2870 EXIT();
2871 return ret_val;
2872}
2873
2874/**
2875 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2876 * @wiphy: corestack handler
2877 * @wdev: wireless device
2878 * @data: data
2879 * @data_len: data length
2880 *
2881 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2882 * setup WISA mode features.
2883 *
2884 * Return: Success(0) or reason code for failure
2885 */
2886static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2887 struct wireless_dev *wdev,
2888 const void *data,
2889 int data_len)
2890{
2891 int ret;
2892
2893 cds_ssr_protect(__func__);
2894 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2895 cds_ssr_unprotect(__func__);
2896
2897 return ret;
2898}
2899
Anurag Chouhan96919482016-07-13 16:36:57 +05302900/*
2901 * define short names for the global vendor params
2902 * used by __wlan_hdd_cfg80211_get_station_cmd()
2903 */
2904#define STATION_INVALID \
2905 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2906#define STATION_INFO \
2907 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2908#define STATION_ASSOC_FAIL_REASON \
2909 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2910#define STATION_MAX \
2911 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2912
2913static const struct nla_policy
2914hdd_get_station_policy[STATION_MAX + 1] = {
2915 [STATION_INFO] = {.type = NLA_FLAG},
2916 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2917};
2918
2919/**
2920 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2921 * @hdd_ctx: HDD context within host driver
2922 * @wdev: wireless device
2923 *
2924 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
2925 * Validate cmd attributes and send the station info to upper layers.
2926 *
2927 * Return: Success(0) or reason code for failure
2928 */
2929static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
2930 hdd_adapter_t *adapter)
2931{
2932 struct sk_buff *skb = NULL;
2933 uint32_t nl_buf_len;
2934 hdd_station_ctx_t *hdd_sta_ctx;
2935
2936 nl_buf_len = NLMSG_HDRLEN;
2937 nl_buf_len += sizeof(uint32_t);
2938 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
2939
2940 if (!skb) {
2941 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
2942 return -ENOMEM;
2943 }
2944
2945 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2946
2947 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
2948 hdd_sta_ctx->conn_info.assoc_status_code)) {
2949 hdd_err("put fail");
2950 goto fail;
2951 }
2952 return cfg80211_vendor_cmd_reply(skb);
2953fail:
2954 if (skb)
2955 kfree_skb(skb);
2956 return -EINVAL;
2957}
2958
2959/**
2960 * hdd_map_auth_type() - transform auth type specific to
2961 * vendor command
2962 * @auth_type: csr auth type
2963 *
2964 * Return: Success(0) or reason code for failure
2965 */
2966static int hdd_convert_auth_type(uint32_t auth_type)
2967{
2968 uint32_t ret_val;
2969
2970 switch (auth_type) {
2971 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
2972 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
2973 break;
2974 case eCSR_AUTH_TYPE_SHARED_KEY:
2975 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
2976 break;
2977 case eCSR_AUTH_TYPE_WPA:
2978 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
2979 break;
2980 case eCSR_AUTH_TYPE_WPA_PSK:
2981 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
2982 break;
2983 case eCSR_AUTH_TYPE_AUTOSWITCH:
2984 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
2985 break;
2986 case eCSR_AUTH_TYPE_WPA_NONE:
2987 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
2988 break;
2989 case eCSR_AUTH_TYPE_RSN:
2990 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
2991 break;
2992 case eCSR_AUTH_TYPE_RSN_PSK:
2993 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
2994 break;
2995 case eCSR_AUTH_TYPE_FT_RSN:
2996 ret_val = QCA_WLAN_AUTH_TYPE_FT;
2997 break;
2998 case eCSR_AUTH_TYPE_FT_RSN_PSK:
2999 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3000 break;
3001 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3002 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3003 break;
3004 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3005 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3006 break;
3007 case eCSR_AUTH_TYPE_CCKM_WPA:
3008 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3009 break;
3010 case eCSR_AUTH_TYPE_CCKM_RSN:
3011 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3012 break;
3013 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3014 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3015 break;
3016 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3017 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3018 break;
3019 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3020 case eCSR_AUTH_TYPE_FAILED:
3021 case eCSR_AUTH_TYPE_NONE:
3022 default:
3023 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3024 break;
3025 }
3026 return ret_val;
3027}
3028
3029/**
3030 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3031 * vendor command
3032 * @dot11mode: dot11mode
3033 *
3034 * Return: Success(0) or reason code for failure
3035 */
3036static int hdd_convert_dot11mode(uint32_t dot11mode)
3037{
3038 uint32_t ret_val;
3039
3040 switch (dot11mode) {
3041 case eCSR_CFG_DOT11_MODE_11A:
3042 ret_val = QCA_WLAN_802_11_MODE_11A;
3043 break;
3044 case eCSR_CFG_DOT11_MODE_11B:
3045 ret_val = QCA_WLAN_802_11_MODE_11B;
3046 break;
3047 case eCSR_CFG_DOT11_MODE_11G:
3048 ret_val = QCA_WLAN_802_11_MODE_11G;
3049 break;
3050 case eCSR_CFG_DOT11_MODE_11N:
3051 ret_val = QCA_WLAN_802_11_MODE_11N;
3052 break;
3053 case eCSR_CFG_DOT11_MODE_11AC:
3054 ret_val = QCA_WLAN_802_11_MODE_11AC;
3055 break;
3056 case eCSR_CFG_DOT11_MODE_AUTO:
3057 case eCSR_CFG_DOT11_MODE_ABG:
3058 default:
3059 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3060 }
3061 return ret_val;
3062}
3063
3064/**
3065 * hdd_add_tx_bitrate() - add tx bitrate attribute
3066 * @skb: pointer to sk buff
3067 * @hdd_sta_ctx: pointer to hdd station context
3068 * @idx: attribute index
3069 *
3070 * Return: Success(0) or reason code for failure
3071 */
3072static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3073 hdd_station_ctx_t *hdd_sta_ctx,
3074 int idx)
3075{
3076 struct nlattr *nla_attr;
3077 uint32_t bitrate, bitrate_compat;
3078
3079 nla_attr = nla_nest_start(skb, idx);
3080 if (!nla_attr)
3081 goto fail;
3082 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3083 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3084
3085 /* report 16-bit bitrate only if we can */
3086 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3087 if (bitrate > 0 &&
3088 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3089 hdd_err("put fail");
3090 goto fail;
3091 }
3092 if (bitrate_compat > 0 &&
3093 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3094 hdd_err("put fail");
3095 goto fail;
3096 }
3097 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3098 hdd_sta_ctx->conn_info.txrate.nss)) {
3099 hdd_err("put fail");
3100 goto fail;
3101 }
3102 nla_nest_end(skb, nla_attr);
3103 return 0;
3104fail:
3105 return -EINVAL;
3106}
3107
3108/**
3109 * hdd_add_sta_info() - add station info attribute
3110 * @skb: pointer to sk buff
3111 * @hdd_sta_ctx: pointer to hdd station context
3112 * @idx: attribute index
3113 *
3114 * Return: Success(0) or reason code for failure
3115 */
3116static int32_t hdd_add_sta_info(struct sk_buff *skb,
3117 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3118{
3119 struct nlattr *nla_attr;
3120
3121 nla_attr = nla_nest_start(skb, idx);
3122 if (!nla_attr)
3123 goto fail;
3124 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3125 (hdd_sta_ctx->conn_info.signal + 100))) {
3126 hdd_err("put fail");
3127 goto fail;
3128 }
3129 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3130 goto fail;
3131 nla_nest_end(skb, nla_attr);
3132 return 0;
3133fail:
3134 return -EINVAL;
3135}
3136
3137/**
3138 * hdd_add_survey_info() - add survey info attribute
3139 * @skb: pointer to sk buff
3140 * @hdd_sta_ctx: pointer to hdd station context
3141 * @idx: attribute index
3142 *
3143 * Return: Success(0) or reason code for failure
3144 */
3145static int32_t hdd_add_survey_info(struct sk_buff *skb,
3146 hdd_station_ctx_t *hdd_sta_ctx,
3147 int idx)
3148{
3149 struct nlattr *nla_attr;
3150
3151 nla_attr = nla_nest_start(skb, idx);
3152 if (!nla_attr)
3153 goto fail;
3154 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3155 hdd_sta_ctx->conn_info.freq) ||
3156 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3157 (hdd_sta_ctx->conn_info.noise + 100))) {
3158 hdd_err("put fail");
3159 goto fail;
3160 }
3161 nla_nest_end(skb, nla_attr);
3162 return 0;
3163fail:
3164 return -EINVAL;
3165}
3166
3167/**
3168 * hdd_add_link_standard_info() - add link info attribute
3169 * @skb: pointer to sk buff
3170 * @hdd_sta_ctx: pointer to hdd station context
3171 * @idx: attribute index
3172 *
3173 * Return: Success(0) or reason code for failure
3174 */
3175static int32_t
3176hdd_add_link_standard_info(struct sk_buff *skb,
3177 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3178{
3179 struct nlattr *nla_attr;
3180
3181 nla_attr = nla_nest_start(skb, idx);
3182 if (!nla_attr)
3183 goto fail;
3184 if (nla_put(skb,
3185 NL80211_ATTR_SSID,
3186 hdd_sta_ctx->conn_info.SSID.SSID.length,
3187 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3188 hdd_err("put fail");
3189 goto fail;
3190 }
3191 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3192 goto fail;
3193 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3194 goto fail;
3195 nla_nest_end(skb, nla_attr);
3196 return 0;
3197fail:
3198 return -EINVAL;
3199}
3200
3201/**
3202 * hdd_add_ap_standard_info() - add ap info attribute
3203 * @skb: pointer to sk buff
3204 * @hdd_sta_ctx: pointer to hdd station context
3205 * @idx: attribute index
3206 *
3207 * Return: Success(0) or reason code for failure
3208 */
3209static int32_t
3210hdd_add_ap_standard_info(struct sk_buff *skb,
3211 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3212{
3213 struct nlattr *nla_attr;
3214
3215 nla_attr = nla_nest_start(skb, idx);
3216 if (!nla_attr)
3217 goto fail;
3218 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3219 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3220 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3221 &hdd_sta_ctx->conn_info.vht_caps)) {
3222 hdd_err("put fail");
3223 goto fail;
3224 }
3225 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3226 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3227 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3228 &hdd_sta_ctx->conn_info.ht_caps)) {
3229 hdd_err("put fail");
3230 goto fail;
3231 }
3232 nla_nest_end(skb, nla_attr);
3233 return 0;
3234fail:
3235 return -EINVAL;
3236}
3237
3238/**
3239 * hdd_get_station_info() - send BSS information to supplicant
3240 * @hdd_ctx: pointer to hdd context
3241 * @adapter: pointer to adapter
3242 *
3243 * Return: 0 if success else error status
3244 */
3245static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3246 hdd_adapter_t *adapter)
3247{
3248 struct sk_buff *skb = NULL;
3249 uint8_t *tmp_hs20 = NULL;
3250 uint32_t nl_buf_len;
3251 hdd_station_ctx_t *hdd_sta_ctx;
3252
3253 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3254
3255 nl_buf_len = NLMSG_HDRLEN;
3256 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3257 sizeof(hdd_sta_ctx->conn_info.freq) +
3258 sizeof(hdd_sta_ctx->conn_info.noise) +
3259 sizeof(hdd_sta_ctx->conn_info.signal) +
3260 (sizeof(uint32_t) * 2) +
3261 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3262 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3263 sizeof(hdd_sta_ctx->conn_info.authType) +
3264 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3265 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3266 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3267 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3268 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3269 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3270 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3271 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3272 1);
3273 }
3274 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3275 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3276 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3277 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3278
3279
3280 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3281 if (!skb) {
3282 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3283 return -ENOMEM;
3284 }
3285
3286 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3287 LINK_INFO_STANDARD_NL80211_ATTR)) {
3288 hdd_err("put fail");
3289 goto fail;
3290 }
3291 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3292 AP_INFO_STANDARD_NL80211_ATTR)) {
3293 hdd_err("put fail");
3294 goto fail;
3295 }
3296 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3297 hdd_sta_ctx->conn_info.roam_count) ||
3298 nla_put_u32(skb, INFO_AKM,
3299 hdd_convert_auth_type(
3300 hdd_sta_ctx->conn_info.authType)) ||
3301 nla_put_u32(skb, WLAN802_11_MODE,
3302 hdd_convert_dot11mode(
3303 hdd_sta_ctx->conn_info.dot11Mode))) {
3304 hdd_err("put fail");
3305 goto fail;
3306 }
3307 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3308 if (nla_put(skb, HT_OPERATION,
3309 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3310 &hdd_sta_ctx->conn_info.ht_operation)) {
3311 hdd_err("put fail");
3312 goto fail;
3313 }
3314 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3315 if (nla_put(skb, VHT_OPERATION,
3316 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3317 &hdd_sta_ctx->conn_info.vht_operation)) {
3318 hdd_err("put fail");
3319 goto fail;
3320 }
3321 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3322 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3323 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3324 tmp_hs20 + 1)) {
3325 hdd_err("put fail");
3326 goto fail;
3327 }
3328
3329 return cfg80211_vendor_cmd_reply(skb);
3330fail:
3331 if (skb)
3332 kfree_skb(skb);
3333 return -EINVAL;
3334}
3335
3336/**
3337 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3338 * @wiphy: corestack handler
3339 * @wdev: wireless device
3340 * @data: data
3341 * @data_len: data length
3342 *
3343 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3344 * Validate cmd attributes and send the station info to upper layers.
3345 *
3346 * Return: Success(0) or reason code for failure
3347 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303348static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303349__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3350 struct wireless_dev *wdev,
3351 const void *data,
3352 int data_len)
3353{
3354 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3355 struct net_device *dev = wdev->netdev;
3356 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3357 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3358 int32_t status;
3359
3360 ENTER_DEV(dev);
3361 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3362 hdd_err("Command not allowed in FTM mode");
3363 status = -EPERM;
3364 goto out;
3365 }
3366
3367 status = wlan_hdd_validate_context(hdd_ctx);
3368 if (0 != status)
3369 goto out;
3370
3371
3372 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3373 data, data_len, NULL);
3374 if (status) {
3375 hdd_err("Invalid ATTR");
3376 goto out;
3377 }
3378
3379 /* Parse and fetch Command Type*/
3380 if (tb[STATION_INFO]) {
3381 status = hdd_get_station_info(hdd_ctx, adapter);
3382 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3383 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3384 } else {
3385 hdd_err("get station info cmd type failed");
3386 status = -EINVAL;
3387 goto out;
3388 }
3389 EXIT();
3390out:
3391 return status;
3392}
3393
3394/**
3395 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3396 * @wiphy: corestack handler
3397 * @wdev: wireless device
3398 * @data: data
3399 * @data_len: data length
3400 *
3401 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3402 * Validate cmd attributes and send the station info to upper layers.
3403 *
3404 * Return: Success(0) or reason code for failure
3405 */
3406static int32_t
3407hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3408 struct wireless_dev *wdev,
3409 const void *data,
3410 int data_len)
3411{
3412 int ret;
3413
3414 cds_ssr_protect(__func__);
3415 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3416 cds_ssr_unprotect(__func__);
3417
3418 return ret;
3419}
3420
3421/*
3422 * undef short names defined for get station command
3423 * used by __wlan_hdd_cfg80211_get_station_cmd()
3424 */
3425#undef STATION_INVALID
3426#undef STATION_INFO
3427#undef STATION_ASSOC_FAIL_REASON
3428#undef STATION_MAX
3429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003430#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3431/**
3432 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3433 * @wiphy: pointer to wireless wiphy structure.
3434 * @wdev: pointer to wireless_dev structure.
3435 * @data: Pointer to the Key data
3436 * @data_len:Length of the data passed
3437 *
3438 * This is called when wlan driver needs to save the keys received via
3439 * vendor specific command.
3440 *
3441 * Return: Return the Success or Failure code.
3442 */
3443static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3444 struct wireless_dev *wdev,
3445 const void *data, int data_len)
3446{
3447 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3448 struct net_device *dev = wdev->netdev;
3449 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3450 hdd_context_t *hdd_ctx_ptr;
3451 int status;
3452
Jeff Johnson1f61b612016-02-12 16:28:33 -08003453 ENTER_DEV(dev);
3454
Anurag Chouhan6d760662016-02-20 16:05:43 +05303455 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003456 hdd_err("Command not allowed in FTM mode");
3457 return -EPERM;
3458 }
3459
3460 if ((data == NULL) || (data_len == 0) ||
3461 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003462 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003463 return -EINVAL;
3464 }
3465
3466 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3467 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003468 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003469 return -EINVAL;
3470 }
3471
3472 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303473 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003474 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003475 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3476 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003477 true,
3478 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303479 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3480 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3482 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3483 return 0;
3484}
3485
3486/**
3487 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3488 * @wiphy: pointer to wireless wiphy structure.
3489 * @wdev: pointer to wireless_dev structure.
3490 * @data: Pointer to the Key data
3491 * @data_len:Length of the data passed
3492 *
3493 * This is called when wlan driver needs to save the keys received via
3494 * vendor specific command.
3495 *
3496 * Return: Return the Success or Failure code.
3497 */
3498static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3499 struct wireless_dev *wdev,
3500 const void *data, int data_len)
3501{
3502 int ret;
3503
3504 cds_ssr_protect(__func__);
3505 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3506 cds_ssr_unprotect(__func__);
3507
3508 return ret;
3509}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003510#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003511
3512static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3513 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3514 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3515 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003516 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003517};
3518
3519/**
3520 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3521 * @wiphy: pointer to wireless wiphy structure.
3522 * @wdev: pointer to wireless_dev structure.
3523 * @data: Pointer to the data to be passed via vendor interface
3524 * @data_len:Length of the data to be passed
3525 *
3526 * This is called when wlan driver needs to send wifi driver related info
3527 * (driver/fw version) to the user space application upon request.
3528 *
3529 * Return: Return the Success or Failure code.
3530 */
3531static int
3532__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3533 struct wireless_dev *wdev,
3534 const void *data, int data_len)
3535{
3536 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3537 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003538 tSirVersionString driver_version;
3539 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003540 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003541 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003542 struct sk_buff *reply_skb;
3543 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003544
Jeff Johnson1f61b612016-02-12 16:28:33 -08003545 ENTER_DEV(wdev->netdev);
3546
Anurag Chouhan6d760662016-02-20 16:05:43 +05303547 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003548 hdd_err("Command not allowed in FTM mode");
3549 return -EPERM;
3550 }
3551
3552 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303553 if (status)
3554 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003555
3556 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3557 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003558 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003559 return -EINVAL;
3560 }
3561
3562 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003563 hdd_err("Rcvd req for Driver version");
3564 strlcpy(driver_version, QWLAN_VERSIONSTR,
3565 sizeof(driver_version));
3566 skb_len += strlen(driver_version) + 1;
3567 count++;
3568 }
3569
3570 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3571 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003572 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3573 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003574 snprintf(firmware_version, sizeof(firmware_version),
3575 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3576 skb_len += strlen(firmware_version) + 1;
3577 count++;
3578 }
3579
3580 if (count == 0) {
3581 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003582 return -EINVAL;
3583 }
3584
Ryan Hsu7ac88852016-04-28 10:20:34 -07003585 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3586 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3587
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003588 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003589 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003590 return -ENOMEM;
3591 }
3592
Ryan Hsu7ac88852016-04-28 10:20:34 -07003593 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3594 if (nla_put_string(reply_skb,
3595 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3596 driver_version))
3597 goto error_nla_fail;
3598 }
3599
3600 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3601 if (nla_put_string(reply_skb,
3602 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3603 firmware_version))
3604 goto error_nla_fail;
3605 }
3606
3607 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3608 if (nla_put_u32(reply_skb,
3609 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3610 hdd_ctx->radio_index))
3611 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003612 }
3613
3614 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003615
3616error_nla_fail:
3617 hdd_err("nla put fail");
3618 kfree_skb(reply_skb);
3619 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003620}
3621
3622/**
3623 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3624 * @wiphy: pointer to wireless wiphy structure.
3625 * @wdev: pointer to wireless_dev structure.
3626 * @data: Pointer to the data to be passed via vendor interface
3627 * @data_len:Length of the data to be passed
3628 *
3629 * This is called when wlan driver needs to send wifi driver related info
3630 * (driver/fw version) to the user space application upon request.
3631 *
3632 * Return: Return the Success or Failure code.
3633 */
3634static int
3635wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3636 struct wireless_dev *wdev,
3637 const void *data, int data_len)
3638{
3639 int ret;
3640
3641 cds_ssr_protect(__func__);
3642 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3643 cds_ssr_unprotect(__func__);
3644
3645 return ret;
3646}
3647
3648/**
3649 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3650 * @wiphy: pointer to wireless wiphy structure.
3651 * @wdev: pointer to wireless_dev structure.
3652 * @data: Pointer to the data to be passed via vendor interface
3653 * @data_len:Length of the data to be passed
3654 *
3655 * This is called by userspace to know the supported logger features
3656 *
3657 * Return: Return the Success or Failure code.
3658 */
3659static int
3660__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3661 struct wireless_dev *wdev,
3662 const void *data, int data_len)
3663{
3664 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3665 int status;
3666 uint32_t features;
3667 struct sk_buff *reply_skb = NULL;
3668
Jeff Johnson1f61b612016-02-12 16:28:33 -08003669 ENTER_DEV(wdev->netdev);
3670
Anurag Chouhan6d760662016-02-20 16:05:43 +05303671 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003672 hdd_err("Command not allowed in FTM mode");
3673 return -EPERM;
3674 }
3675
3676 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303677 if (status)
3678 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003679
3680 features = 0;
3681
3682 if (hdd_is_memdump_supported())
3683 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3684 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3685 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3686 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3687
3688 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3689 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3690 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003691 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003692 return -ENOMEM;
3693 }
3694
Jeff Johnson020db452016-06-29 14:37:26 -07003695 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003696 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3697 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003698 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003699 kfree_skb(reply_skb);
3700 return -EINVAL;
3701 }
3702
3703 return cfg80211_vendor_cmd_reply(reply_skb);
3704}
3705
3706/**
3707 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3708 * @wiphy: pointer to wireless wiphy structure.
3709 * @wdev: pointer to wireless_dev structure.
3710 * @data: Pointer to the data to be passed via vendor interface
3711 * @data_len:Length of the data to be passed
3712 *
3713 * This is called by userspace to know the supported logger features
3714 *
3715 * Return: Return the Success or Failure code.
3716 */
3717static int
3718wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3719 struct wireless_dev *wdev,
3720 const void *data, int data_len)
3721{
3722 int ret;
3723
3724 cds_ssr_protect(__func__);
3725 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3726 data, data_len);
3727 cds_ssr_unprotect(__func__);
3728
3729 return ret;
3730}
3731
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003732#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003733/**
3734 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3735 * @hdd_ctx_ptr: pointer to HDD Context.
3736 * @bssid: pointer to bssid of roamed AP.
3737 * @req_rsn_ie: Pointer to request RSN IE
3738 * @req_rsn_len: Length of the request RSN IE
3739 * @rsp_rsn_ie: Pointer to response RSN IE
3740 * @rsp_rsn_len: Length of the response RSN IE
3741 * @roam_info_ptr: Pointer to the roaming related information
3742 *
3743 * This is called when wlan driver needs to send the roaming and
3744 * authorization information after roaming.
3745 *
3746 * The information that would be sent is the request RSN IE, response
3747 * RSN IE and BSSID of the newly roamed AP.
3748 *
3749 * If the Authorized status is authenticated, then additional parameters
3750 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3751 * supplicant.
3752 *
3753 * The supplicant upon receiving this event would ignore the legacy
3754 * cfg80211_roamed call and use the entire information from this event.
3755 * The cfg80211_roamed should still co-exist since the kernel will
3756 * make use of the parameters even if the supplicant ignores it.
3757 *
3758 * Return: Return the Success or Failure code.
3759 */
3760int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3761 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3762 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3763{
3764 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003765 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003766 ENTER();
3767
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303768 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003769 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003770
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003771 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003772 !roam_info_ptr->roamSynchInProgress)
3773 return 0;
3774
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003775 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3776 NULL,
3777 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3778 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3779 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003780 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003781 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3782 GFP_KERNEL);
3783
3784 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003785 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003786 return -EINVAL;
3787 }
3788
3789 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3790 ETH_ALEN, bssid) ||
3791 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3792 req_rsn_len, req_rsn_ie) ||
3793 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3794 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003795 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003796 goto nla_put_failure;
3797 }
Jeff Johnson020db452016-06-29 14:37:26 -07003798 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003799 if (roam_info_ptr->synchAuthStatus ==
3800 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003801 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003802 if (nla_put_u8(skb,
3803 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3804 hdd_err("nla put fail");
3805 goto nla_put_failure;
3806 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003807 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3808 /* if FT or CCKM connection: dont send replay counter */
3809 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3810 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3811 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3812 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3813 nla_put(skb,
3814 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3815 SIR_REPLAY_CTR_LEN,
3816 roam_info_ptr->replay_ctr)) {
3817 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003818 hdd_err("failed to send replay counter.");
3819 goto nla_put_failure;
3820 }
3821 if (nla_put(skb,
3822 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3823 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3824 nla_put(skb,
3825 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3826 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3827 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003828 goto nla_put_failure;
3829 }
3830 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003831 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003832 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3833 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003834 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003835 goto nla_put_failure;
3836 }
3837 }
3838
Jeff Johnson020db452016-06-29 14:37:26 -07003839 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003840 roam_info_ptr->subnet_change_status);
3841
3842 /*
3843 * Add subnet change status if subnet has changed
3844 * 0 = unchanged
3845 * 1 = changed
3846 * 2 = unknown
3847 */
3848 if (roam_info_ptr->subnet_change_status) {
3849 if (nla_put_u8(skb,
3850 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3851 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003852 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003853 goto nla_put_failure;
3854 }
3855 }
3856
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003857 cfg80211_vendor_event(skb, GFP_KERNEL);
3858 return 0;
3859
3860nla_put_failure:
3861 kfree_skb(skb);
3862 return -EINVAL;
3863}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003864#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003865
3866static const struct nla_policy
3867wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3868
3869 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3870 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3871 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303872 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003873};
3874
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003875/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303876 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3877 *
3878 * @adapter: Pointer to HDD adapter
3879 * @ie_data: Pointer to Scan IEs buffer
3880 * @ie_len: Length of Scan IEs
3881 *
3882 * Return: 0 on success; error number otherwise
3883 */
3884static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3885 uint8_t *ie_data, uint8_t ie_len)
3886{
3887 hdd_scaninfo_t *scan_info = NULL;
3888 scan_info = &adapter->scan_info;
3889
3890 if (scan_info->default_scan_ies) {
3891 qdf_mem_free(scan_info->default_scan_ies);
3892 scan_info->default_scan_ies = NULL;
3893 }
3894
3895 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3896 if (!scan_info->default_scan_ies)
3897 return -ENOMEM;
3898
3899 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3900 scan_info->default_scan_ies_len = ie_len;
3901 return 0;
3902}
3903
3904/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003905 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3906 * vendor command
3907 *
3908 * @wiphy: wiphy device pointer
3909 * @wdev: wireless device pointer
3910 * @data: Vendor command data buffer
3911 * @data_len: Buffer length
3912 *
3913 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3914 *
3915 * Return: Error code.
3916 */
3917static int
3918__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3919 struct wireless_dev *wdev,
3920 const void *data,
3921 int data_len)
3922{
3923 struct net_device *dev = wdev->netdev;
3924 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3925 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3926 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3927 int ret_val = 0;
3928 u32 modulated_dtim;
3929 u16 stats_avg_factor;
3930 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303931 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003932 u32 ftm_capab;
Kapil Gupta6213c012016-09-02 19:39:09 +05303933 uint8_t qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303934 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303935 int attr_len;
3936 int access_policy = 0;
3937 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3938 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303939 uint16_t scan_ie_len = 0;
3940 uint8_t *scan_ie;
3941
Jeff Johnson1f61b612016-02-12 16:28:33 -08003942 ENTER_DEV(dev);
3943
Anurag Chouhan6d760662016-02-20 16:05:43 +05303944 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003945 hdd_err("Command not allowed in FTM mode");
3946 return -EPERM;
3947 }
3948
3949 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303950 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003951 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003952
3953 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3954 data, data_len,
3955 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07003956 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003957 return -EINVAL;
3958 }
3959
Krunal Sonie3531942016-04-12 17:43:53 -07003960 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
3961 ftm_capab = nla_get_u32(tb[
3962 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
3963 hdd_ctx->config->fine_time_meas_cap =
3964 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
3965 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05303966 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07003967 hdd_ctx->config->fine_time_meas_cap);
3968 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
3969 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
3970 hdd_ctx->config->fine_time_meas_cap);
3971 }
3972
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003973 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
3974 modulated_dtim = nla_get_u32(
3975 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
3976
3977 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
3978 adapter->sessionId,
3979 modulated_dtim);
3980
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303981 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003982 ret_val = -EPERM;
3983 }
3984
Kapil Gupta6213c012016-09-02 19:39:09 +05303985 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
3986 qpower = nla_get_u8(
3987 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
3988 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
3989 ret_val = -EINVAL;
3990 }
3991
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003992 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
3993 stats_avg_factor = nla_get_u16(
3994 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
3995 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
3996 adapter->sessionId,
3997 stats_avg_factor);
3998
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303999 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004000 ret_val = -EPERM;
4001 }
4002
4003
4004 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4005 guard_time = nla_get_u32(
4006 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4007 status = sme_configure_guard_time(hdd_ctx->hHal,
4008 adapter->sessionId,
4009 guard_time);
4010
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304011 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004012 ret_val = -EPERM;
4013 }
4014
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304015 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4016 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4017 attr_len = nla_len(
4018 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4019 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4020 hdd_info("Invalid value. attr_len %d",
4021 attr_len);
4022 return -EINVAL;
4023 }
4024
4025 nla_memcpy(&vendor_ie,
4026 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4027 attr_len);
4028 vendor_ie_present = true;
4029 hdd_info("Access policy vendor ie present.attr_len %d",
4030 attr_len);
4031 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4032 &vendor_ie[0], attr_len);
4033 }
4034
4035 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4036 access_policy = (int) nla_get_u32(
4037 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4038 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4039 (access_policy >
4040 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4041 hdd_info("Invalid value. access_policy %d",
4042 access_policy);
4043 return -EINVAL;
4044 }
4045 access_policy_present = true;
4046 hdd_info("Access policy present. access_policy %d",
4047 access_policy);
4048 }
4049
4050 if (vendor_ie_present && access_policy_present) {
4051 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4052 access_policy =
4053 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
4054 } else {
4055 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
4056 }
4057
4058 hdd_info("calling sme_update_access_policy_vendor_ie");
4059 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4060 adapter->sessionId, &vendor_ie[0],
4061 access_policy);
4062 if (QDF_STATUS_SUCCESS != status) {
4063 hdd_info("Failed to set vendor ie and access policy.");
4064 return -EINVAL;
4065 }
4066 }
4067
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304068 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4069 set_value = nla_get_u8(
4070 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4071 hdd_info("set_value: %d", set_value);
4072 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4073 }
4074
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304075 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4076 scan_ie_len = nla_len(
4077 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4078 hdd_info("Received default scan IE of len %d session %d device mode %d",
4079 scan_ie_len, adapter->sessionId,
4080 adapter->device_mode);
4081 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4082 scan_ie = (uint8_t *) nla_data(tb
4083 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304084
4085 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4086 scan_ie_len))
4087 hdd_err("Failed to save default scan IEs");
4088
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304089 if (adapter->device_mode == QDF_STA_MODE) {
4090 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4091 adapter->sessionId, scan_ie,
4092 scan_ie_len);
4093 if (QDF_STATUS_SUCCESS != status)
4094 ret_val = -EPERM;
4095 }
4096 } else
4097 ret_val = -EPERM;
4098 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004099 return ret_val;
4100}
4101
4102/**
4103 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4104 * vendor command
4105 *
4106 * @wiphy: wiphy device pointer
4107 * @wdev: wireless device pointer
4108 * @data: Vendor command data buffer
4109 * @data_len: Buffer length
4110 *
4111 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4112 *
4113 * Return: EOK or other error codes.
4114 */
4115static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4116 struct wireless_dev *wdev,
4117 const void *data,
4118 int data_len)
4119{
4120 int ret;
4121
4122 cds_ssr_protect(__func__);
4123 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4124 data, data_len);
4125 cds_ssr_unprotect(__func__);
4126
4127 return ret;
4128}
4129
4130static const struct
4131nla_policy
4132qca_wlan_vendor_wifi_logger_start_policy
4133[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4134 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4135 = {.type = NLA_U32 },
4136 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4137 = {.type = NLA_U32 },
4138 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4139 = {.type = NLA_U32 },
4140};
4141
4142/**
4143 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4144 * or disable the collection of packet statistics from the firmware
4145 * @wiphy: WIPHY structure pointer
4146 * @wdev: Wireless device structure pointer
4147 * @data: Pointer to the data received
4148 * @data_len: Length of the data received
4149 *
4150 * This function enables or disables the collection of packet statistics from
4151 * the firmware
4152 *
4153 * Return: 0 on success and errno on failure
4154 */
4155static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4156 struct wireless_dev *wdev,
4157 const void *data,
4158 int data_len)
4159{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304160 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004161 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4162 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4163 struct sir_wifi_start_log start_log;
4164
Jeff Johnson1f61b612016-02-12 16:28:33 -08004165 ENTER_DEV(wdev->netdev);
4166
Anurag Chouhan6d760662016-02-20 16:05:43 +05304167 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004168 hdd_err("Command not allowed in FTM mode");
4169 return -EPERM;
4170 }
4171
4172 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304173 if (status)
4174 return status;
4175
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004176
4177 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4178 data, data_len,
4179 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004180 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004181 return -EINVAL;
4182 }
4183
4184 /* Parse and fetch ring id */
4185 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004186 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004187 return -EINVAL;
4188 }
4189 start_log.ring_id = nla_get_u32(
4190 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004191 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004192
4193 /* Parse and fetch verbose level */
4194 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004195 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004196 return -EINVAL;
4197 }
4198 start_log.verbose_level = nla_get_u32(
4199 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004200 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004201
4202 /* Parse and fetch flag */
4203 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004204 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004205 return -EINVAL;
4206 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304207 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004208 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304209 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004210
4211 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4212
4213 if (start_log.ring_id == RING_ID_WAKELOCK) {
4214 /* Start/stop wakelock events */
4215 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4216 cds_set_wakelock_logging(true);
4217 else
4218 cds_set_wakelock_logging(false);
4219 return 0;
4220 }
4221
4222 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304223 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004224 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004225 status);
4226 return -EINVAL;
4227 }
4228 return 0;
4229}
4230
4231/**
4232 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4233 * or disable the collection of packet statistics from the firmware
4234 * @wiphy: WIPHY structure pointer
4235 * @wdev: Wireless device structure pointer
4236 * @data: Pointer to the data received
4237 * @data_len: Length of the data received
4238 *
4239 * This function is used to enable or disable the collection of packet
4240 * statistics from the firmware
4241 *
4242 * Return: 0 on success and errno on failure
4243 */
4244static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4245 struct wireless_dev *wdev,
4246 const void *data,
4247 int data_len)
4248{
4249 int ret = 0;
4250
4251 cds_ssr_protect(__func__);
4252 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4253 wdev, data, data_len);
4254 cds_ssr_unprotect(__func__);
4255
4256 return ret;
4257}
4258
4259static const struct
4260nla_policy
4261qca_wlan_vendor_wifi_logger_get_ring_data_policy
4262[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4263 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4264 = {.type = NLA_U32 },
4265};
4266
4267/**
4268 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4269 * @wiphy: WIPHY structure pointer
4270 * @wdev: Wireless device structure pointer
4271 * @data: Pointer to the data received
4272 * @data_len: Length of the data received
4273 *
4274 * This function is used to flush or retrieve the per packet statistics from
4275 * the driver
4276 *
4277 * Return: 0 on success and errno on failure
4278 */
4279static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4280 struct wireless_dev *wdev,
4281 const void *data,
4282 int data_len)
4283{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304284 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004285 uint32_t ring_id;
4286 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4287 struct nlattr *tb
4288 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4289
Jeff Johnson1f61b612016-02-12 16:28:33 -08004290 ENTER_DEV(wdev->netdev);
4291
Anurag Chouhan6d760662016-02-20 16:05:43 +05304292 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004293 hdd_err("Command not allowed in FTM mode");
4294 return -EPERM;
4295 }
4296
4297 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304298 if (status)
4299 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004300
4301 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4302 data, data_len,
4303 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004304 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004305 return -EINVAL;
4306 }
4307
4308 /* Parse and fetch ring id */
4309 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004310 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004311 return -EINVAL;
4312 }
4313
4314 ring_id = nla_get_u32(
4315 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4316
4317 if (ring_id == RING_ID_PER_PACKET_STATS) {
4318 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004319 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304320 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4321 /*
4322 * As part of DRIVER ring ID, flush both driver and fw logs.
4323 * For other Ring ID's driver doesn't have any rings to flush
4324 */
4325 hdd_notice("Bug report triggered by framework");
4326
4327 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4328 WLAN_LOG_INDICATOR_FRAMEWORK,
4329 WLAN_LOG_REASON_CODE_UNUSED,
4330 true, false);
4331 if (QDF_STATUS_SUCCESS != status) {
4332 hdd_err("Failed to trigger bug report");
4333 return -EINVAL;
4334 }
4335 } else {
4336 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4337 WLAN_LOG_INDICATOR_FRAMEWORK,
4338 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004339 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004340 return 0;
4341}
4342
4343/**
4344 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4345 * @wiphy: WIPHY structure pointer
4346 * @wdev: Wireless device structure pointer
4347 * @data: Pointer to the data received
4348 * @data_len: Length of the data received
4349 *
4350 * This function is used to flush or retrieve the per packet statistics from
4351 * the driver
4352 *
4353 * Return: 0 on success and errno on failure
4354 */
4355static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4356 struct wireless_dev *wdev,
4357 const void *data,
4358 int data_len)
4359{
4360 int ret = 0;
4361
4362 cds_ssr_protect(__func__);
4363 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4364 wdev, data, data_len);
4365 cds_ssr_unprotect(__func__);
4366
4367 return ret;
4368}
4369
4370#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4371/**
4372 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4373 * @hdd_ctx: HDD context
4374 * @request_id: [input] request id
4375 * @pattern_id: [output] pattern id
4376 *
4377 * This function loops through request id to pattern id array
4378 * if the slot is available, store the request id and return pattern id
4379 * if entry exists, return the pattern id
4380 *
4381 * Return: 0 on success and errno on failure
4382 */
4383static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4384 uint32_t request_id,
4385 uint8_t *pattern_id)
4386{
4387 uint32_t i;
4388
4389 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4390 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4391 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4392 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4393 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4394 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4395 return 0;
4396 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4397 request_id) {
4398 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4399 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4400 return 0;
4401 }
4402 }
4403 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4404 return -EINVAL;
4405}
4406
4407/**
4408 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4409 * @hdd_ctx: HDD context
4410 * @request_id: [input] request id
4411 * @pattern_id: [output] pattern id
4412 *
4413 * This function loops through request id to pattern id array
4414 * reset request id to 0 (slot available again) and
4415 * return pattern id
4416 *
4417 * Return: 0 on success and errno on failure
4418 */
4419static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4420 uint32_t request_id,
4421 uint8_t *pattern_id)
4422{
4423 uint32_t i;
4424
4425 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4426 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4427 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4428 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4429 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4430 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4431 return 0;
4432 }
4433 }
4434 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4435 return -EINVAL;
4436}
4437
4438
4439/*
4440 * define short names for the global vendor params
4441 * used by __wlan_hdd_cfg80211_offloaded_packets()
4442 */
4443#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4444#define PARAM_REQUEST_ID \
4445 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4446#define PARAM_CONTROL \
4447 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4448#define PARAM_IP_PACKET \
4449 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4450#define PARAM_SRC_MAC_ADDR \
4451 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4452#define PARAM_DST_MAC_ADDR \
4453 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4454#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4455
4456/**
4457 * wlan_hdd_add_tx_ptrn() - add tx pattern
4458 * @adapter: adapter pointer
4459 * @hdd_ctx: hdd context
4460 * @tb: nl attributes
4461 *
4462 * This function reads the NL attributes and forms a AddTxPtrn message
4463 * posts it to SME.
4464 *
4465 */
4466static int
4467wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4468 struct nlattr **tb)
4469{
4470 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304471 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004472 uint32_t request_id, ret, len;
4473 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304474 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004475 uint16_t eth_type = htons(ETH_P_IP);
4476
4477 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004478 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004479 return -ENOTSUPP;
4480 }
4481
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304482 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004483 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004484 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004485 return -ENOMEM;
4486 }
4487
4488 /* Parse and fetch request Id */
4489 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004490 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491 goto fail;
4492 }
4493
4494 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4495 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004496 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004497 return -EINVAL;
4498 }
Jeff Johnson77848112016-06-29 14:52:06 -07004499 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004500
4501 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004502 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004503 goto fail;
4504 }
4505 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004506 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004507 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004508 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004509 goto fail;
4510 }
4511
4512 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004513 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004514 goto fail;
4515 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004516 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304517 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004518 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004519 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004520
Anurag Chouhanc5548422016-02-24 18:33:27 +05304521 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004522 &adapter->macAddressCurrent)) {
4523 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004524 goto fail;
4525 }
4526
4527 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004528 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004529 goto fail;
4530 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304531 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004532 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004533 MAC_ADDR_ARRAY(dst_addr.bytes));
4534
4535 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004536 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004537 goto fail;
4538 }
4539 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004540 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004541
4542 if (add_req->ucPtrnSize < 0 ||
4543 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4544 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004545 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004546 add_req->ucPtrnSize);
4547 goto fail;
4548 }
4549
4550 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304551 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304552 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304553 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304554 QDF_MAC_ADDR_SIZE);
4555 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304556 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004557 len += 2;
4558
4559 /*
4560 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4561 * ------------------------------------------------------------
4562 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4563 * ------------------------------------------------------------
4564 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304565 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004566 nla_data(tb[PARAM_IP_PACKET]),
4567 add_req->ucPtrnSize);
4568 add_req->ucPtrnSize += len;
4569
4570 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4571 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004572 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004573 goto fail;
4574 }
4575 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004576 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004577
4578 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304579 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004580 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581 goto fail;
4582 }
4583
4584 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304585 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004586 return 0;
4587
4588fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304589 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004590 return -EINVAL;
4591}
4592
4593/**
4594 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4595 * @adapter: adapter pointer
4596 * @hdd_ctx: hdd context
4597 * @tb: nl attributes
4598 *
4599 * This function reads the NL attributes and forms a DelTxPtrn message
4600 * posts it to SME.
4601 *
4602 */
4603static int
4604wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4605 struct nlattr **tb)
4606{
4607 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304608 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609 uint32_t request_id, ret;
4610 uint8_t pattern_id = 0;
4611
4612 /* Parse and fetch request Id */
4613 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004614 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004615 return -EINVAL;
4616 }
4617 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4618 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004619 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004620 return -EINVAL;
4621 }
4622
4623 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4624 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004625 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004626 return -EINVAL;
4627 }
4628
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304629 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004630 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004631 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004632 return -ENOMEM;
4633 }
4634
Anurag Chouhanc5548422016-02-24 18:33:27 +05304635 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004636 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004637 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004638 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004639 request_id, del_req->ucPtrnId);
4640
4641 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304642 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004643 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004644 goto fail;
4645 }
4646
4647 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304648 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004649 return 0;
4650
4651fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304652 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004653 return -EINVAL;
4654}
4655
4656
4657/**
4658 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4659 * @wiphy: Pointer to wireless phy
4660 * @wdev: Pointer to wireless device
4661 * @data: Pointer to data
4662 * @data_len: Data length
4663 *
4664 * Return: 0 on success, negative errno on failure
4665 */
4666static int
4667__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4668 struct wireless_dev *wdev,
4669 const void *data,
4670 int data_len)
4671{
4672 struct net_device *dev = wdev->netdev;
4673 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4674 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4675 struct nlattr *tb[PARAM_MAX + 1];
4676 uint8_t control;
4677 int ret;
4678 static const struct nla_policy policy[PARAM_MAX + 1] = {
4679 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4680 [PARAM_CONTROL] = { .type = NLA_U32 },
4681 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304682 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304684 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004685 [PARAM_PERIOD] = { .type = NLA_U32 },
4686 };
4687
Jeff Johnson1f61b612016-02-12 16:28:33 -08004688 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689
Anurag Chouhan6d760662016-02-20 16:05:43 +05304690 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004691 hdd_err("Command not allowed in FTM mode");
4692 return -EPERM;
4693 }
4694
4695 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304696 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004698
4699 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004700 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701 return -ENOTSUPP;
4702 }
4703
4704 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004705 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004706 return -EINVAL;
4707 }
4708
4709 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004710 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004711 return -EINVAL;
4712 }
4713 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004714 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004715
4716 if (control == WLAN_START_OFFLOADED_PACKETS)
4717 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4718 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4719 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4720 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004721 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004722 return -EINVAL;
4723 }
4724}
4725
4726/*
4727 * done with short names for the global vendor params
4728 * used by __wlan_hdd_cfg80211_offloaded_packets()
4729 */
4730#undef PARAM_MAX
4731#undef PARAM_REQUEST_ID
4732#undef PARAM_CONTROL
4733#undef PARAM_IP_PACKET
4734#undef PARAM_SRC_MAC_ADDR
4735#undef PARAM_DST_MAC_ADDR
4736#undef PARAM_PERIOD
4737
4738/**
4739 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4740 * @wiphy: wiphy structure pointer
4741 * @wdev: Wireless device structure pointer
4742 * @data: Pointer to the data received
4743 * @data_len: Length of @data
4744 *
4745 * Return: 0 on success; errno on failure
4746 */
4747static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4748 struct wireless_dev *wdev,
4749 const void *data,
4750 int data_len)
4751{
4752 int ret = 0;
4753
4754 cds_ssr_protect(__func__);
4755 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4756 wdev, data, data_len);
4757 cds_ssr_unprotect(__func__);
4758
4759 return ret;
4760}
4761#endif
4762
4763/*
4764 * define short names for the global vendor params
4765 * used by __wlan_hdd_cfg80211_monitor_rssi()
4766 */
4767#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4768#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4769#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4770#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4771#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4772
4773/**
4774 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4775 * @wiphy: Pointer to wireless phy
4776 * @wdev: Pointer to wireless device
4777 * @data: Pointer to data
4778 * @data_len: Data length
4779 *
4780 * Return: 0 on success, negative errno on failure
4781 */
4782static int
4783__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4784 struct wireless_dev *wdev,
4785 const void *data,
4786 int data_len)
4787{
4788 struct net_device *dev = wdev->netdev;
4789 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4790 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4791 struct nlattr *tb[PARAM_MAX + 1];
4792 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304793 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004794 int ret;
4795 uint32_t control;
4796 static const struct nla_policy policy[PARAM_MAX + 1] = {
4797 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4798 [PARAM_CONTROL] = { .type = NLA_U32 },
4799 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4800 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4801 };
4802
Jeff Johnson1f61b612016-02-12 16:28:33 -08004803 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004804
4805 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304806 if (ret)
4807 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004808
4809 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004810 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004811 return -ENOTSUPP;
4812 }
4813
4814 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004815 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004816 return -EINVAL;
4817 }
4818
4819 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004820 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004821 return -EINVAL;
4822 }
4823
4824 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004825 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004826 return -EINVAL;
4827 }
4828
4829 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4830 req.session_id = adapter->sessionId;
4831 control = nla_get_u32(tb[PARAM_CONTROL]);
4832
4833 if (control == QCA_WLAN_RSSI_MONITORING_START) {
4834 req.control = true;
4835 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004836 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004837 return -EINVAL;
4838 }
4839
4840 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004841 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004842 return -EINVAL;
4843 }
4844
4845 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
4846 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
4847
4848 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004849 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004850 req.min_rssi, req.max_rssi);
4851 return -EINVAL;
4852 }
Jeff Johnson77848112016-06-29 14:52:06 -07004853 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854 req.min_rssi, req.max_rssi);
4855
4856 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
4857 req.control = false;
4858 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004859 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860 return -EINVAL;
4861 }
Jeff Johnson77848112016-06-29 14:52:06 -07004862 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004863 req.request_id, req.session_id, req.control);
4864
4865 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304866 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004867 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004868 return -EINVAL;
4869 }
4870
4871 return 0;
4872}
4873
4874/*
4875 * done with short names for the global vendor params
4876 * used by __wlan_hdd_cfg80211_monitor_rssi()
4877 */
4878#undef PARAM_MAX
4879#undef PARAM_CONTROL
4880#undef PARAM_REQUEST_ID
4881#undef PARAM_MAX_RSSI
4882#undef PARAM_MIN_RSSI
4883
4884/**
4885 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
4886 * @wiphy: wiphy structure pointer
4887 * @wdev: Wireless device structure pointer
4888 * @data: Pointer to the data received
4889 * @data_len: Length of @data
4890 *
4891 * Return: 0 on success; errno on failure
4892 */
4893static int
4894wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
4895 const void *data, int data_len)
4896{
4897 int ret;
4898
4899 cds_ssr_protect(__func__);
4900 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
4901 cds_ssr_unprotect(__func__);
4902
4903 return ret;
4904}
4905
4906/**
4907 * hdd_rssi_threshold_breached() - rssi breached NL event
4908 * @hddctx: HDD context
4909 * @data: rssi breached event data
4910 *
4911 * This function reads the rssi breached event %data and fill in the skb with
4912 * NL attributes and send up the NL event.
4913 *
4914 * Return: none
4915 */
4916void hdd_rssi_threshold_breached(void *hddctx,
4917 struct rssi_breach_event *data)
4918{
4919 hdd_context_t *hdd_ctx = hddctx;
4920 struct sk_buff *skb;
4921
4922 ENTER();
4923
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304924 if (wlan_hdd_validate_context(hdd_ctx))
4925 return;
4926 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07004927 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004928 return;
4929 }
4930
4931 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4932 NULL,
4933 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
4934 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
4935 GFP_KERNEL);
4936
4937 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07004938 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004939 return;
4940 }
4941
Jeff Johnson77848112016-06-29 14:52:06 -07004942 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004943 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07004944 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004945 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
4946
4947 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
4948 data->request_id) ||
4949 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
4950 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
4951 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
4952 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004953 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004954 goto fail;
4955 }
4956
4957 cfg80211_vendor_event(skb, GFP_KERNEL);
4958 return;
4959
4960fail:
4961 kfree_skb(skb);
4962 return;
4963}
4964
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05304965static const struct nla_policy
4966ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
4967 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
4968};
4969
4970/**
4971 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
4972 * @wiphy: Pointer to wireless phy
4973 * @wdev: Pointer to wireless device
4974 * @data: Pointer to data
4975 * @data_len: Length of @data
4976 *
4977 * Return: 0 on success, negative errno on failure
4978 */
4979static int
4980__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
4981 struct wireless_dev *wdev,
4982 const void *data, int data_len)
4983{
4984 int status;
4985 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
4986 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07004987 struct net_device *dev = wdev->netdev;
4988 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05304989
4990 ENTER_DEV(wdev->netdev);
4991
4992 status = wlan_hdd_validate_context(pHddCtx);
4993 if (0 != status)
4994 return status;
4995 if (!pHddCtx->config->fhostNSOffload) {
4996 hdd_err("ND Offload not supported");
4997 return -EINVAL;
4998 }
4999
5000 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5001 (struct nlattr *)data,
5002 data_len, ns_offload_set_policy)) {
5003 hdd_err("nla_parse failed");
5004 return -EINVAL;
5005 }
5006
5007 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5008 hdd_err("ND Offload flag attribute not present");
5009 return -EINVAL;
5010 }
5011
5012 pHddCtx->ns_offload_enable =
5013 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5014
Dustin Brownd8279d22016-09-07 14:52:57 -07005015 /* update ns offload in case it is already enabled/disabled */
5016 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5017
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305018 return 0;
5019}
5020
5021/**
5022 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5023 * @wiphy: pointer to wireless wiphy structure.
5024 * @wdev: pointer to wireless_dev structure.
5025 * @data: Pointer to the data to be passed via vendor interface
5026 * @data_len:Length of the data to be passed
5027 *
5028 * Return: Return the Success or Failure code.
5029 */
5030static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5031 struct wireless_dev *wdev,
5032 const void *data, int data_len)
5033{
5034 int ret;
5035
5036 cds_ssr_protect(__func__);
5037 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5038 cds_ssr_unprotect(__func__);
5039
5040 return ret;
5041}
5042
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005043/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5044 * @wiphy: Pointer to wireless phy
5045 * @wdev: Pointer to wireless device
5046 * @data: Pointer to data
5047 * @data_len: Data length
5048 *
5049 * This function return the preferred frequency list generated by the policy
5050 * manager.
5051 *
5052 * Return: success or failure code
5053 */
5054static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5055 struct wireless_dev
5056 *wdev, const void *data,
5057 int data_len)
5058{
5059 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5060 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305061 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305062 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005063 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305064 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005065 enum cds_con_mode intf_mode;
5066 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5067 struct sk_buff *reply_skb;
5068
Jeff Johnson1f61b612016-02-12 16:28:33 -08005069 ENTER_DEV(wdev->netdev);
5070
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005071 ret = wlan_hdd_validate_context(hdd_ctx);
5072 if (ret)
5073 return -EINVAL;
5074
5075 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5076 data, data_len, NULL)) {
5077 hdd_err("Invalid ATTR");
5078 return -EINVAL;
5079 }
5080
5081 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5082 hdd_err("attr interface type failed");
5083 return -EINVAL;
5084 }
5085
5086 intf_mode = nla_get_u32(tb
5087 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5088
5089 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5090 hdd_err("Invalid interface type");
5091 return -EINVAL;
5092 }
5093
5094 hdd_debug("Userspace requested pref freq list");
5095
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305096 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5097 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305098 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005099 hdd_err("Get pcl failed");
5100 return -EINVAL;
5101 }
5102
5103 /* convert channel number to frequency */
5104 for (i = 0; i < pcl_len; i++) {
5105 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5106 freq_list[i] =
5107 ieee80211_channel_to_frequency(pcl[i],
5108 IEEE80211_BAND_2GHZ);
5109 else
5110 freq_list[i] =
5111 ieee80211_channel_to_frequency(pcl[i],
5112 IEEE80211_BAND_5GHZ);
5113 }
5114
5115 /* send the freq_list back to supplicant */
5116 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5117 sizeof(u32) *
5118 pcl_len +
5119 NLMSG_HDRLEN);
5120
5121 if (!reply_skb) {
5122 hdd_err("Allocate reply_skb failed");
5123 return -EINVAL;
5124 }
5125
5126 if (nla_put_u32(reply_skb,
5127 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5128 intf_mode) ||
5129 nla_put(reply_skb,
5130 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5131 sizeof(uint32_t) * pcl_len,
5132 freq_list)) {
5133 hdd_err("nla put fail");
5134 kfree_skb(reply_skb);
5135 return -EINVAL;
5136 }
5137
5138 return cfg80211_vendor_cmd_reply(reply_skb);
5139}
5140
5141/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5142 * @wiphy: Pointer to wireless phy
5143 * @wdev: Pointer to wireless device
5144 * @data: Pointer to data
5145 * @data_len: Data length
5146 *
5147 * This function return the preferred frequency list generated by the policy
5148 * manager.
5149 *
5150 * Return: success or failure code
5151 */
5152static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5153 struct wireless_dev
5154 *wdev, const void *data,
5155 int data_len)
5156{
5157 int ret = 0;
5158
5159 cds_ssr_protect(__func__);
5160 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5161 data, data_len);
5162 cds_ssr_unprotect(__func__);
5163
5164 return ret;
5165}
5166
5167/**
5168 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5169 * @wiphy: Pointer to wireless phy
5170 * @wdev: Pointer to wireless device
5171 * @data: Pointer to data
5172 * @data_len: Data length
5173 *
5174 * Return: 0 on success, negative errno on failure
5175 */
5176static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5177 struct wireless_dev *wdev,
5178 const void *data,
5179 int data_len)
5180{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305181 struct net_device *ndev = wdev->netdev;
5182 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005183 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5184 int ret = 0;
5185 enum cds_con_mode intf_mode;
5186 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5187 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005188
Jeff Johnson1f61b612016-02-12 16:28:33 -08005189 ENTER_DEV(ndev);
5190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005191 ret = wlan_hdd_validate_context(hdd_ctx);
5192 if (ret)
5193 return ret;
5194
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005195 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5196 data, data_len, NULL)) {
5197 hdd_err("Invalid ATTR");
5198 return -EINVAL;
5199 }
5200
5201 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5202 hdd_err("attr interface type failed");
5203 return -EINVAL;
5204 }
5205
5206 intf_mode = nla_get_u32(tb
5207 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5208
5209 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5210 hdd_err("Invalid interface type");
5211 return -EINVAL;
5212 }
5213
5214 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5215 hdd_err("attr probable freq failed");
5216 return -EINVAL;
5217 }
5218
5219 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5220 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5221
5222 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005223 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005224 channel_hint, HW_MODE_20_MHZ)) {
5225 hdd_err("Set channel hint failed due to concurrency check");
5226 return -EINVAL;
5227 }
5228
Krunal Soni09e55032016-06-07 10:06:55 -07005229 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5230 hdd_warn("Remain On Channel Pending");
5231
Krunal Soni3091bcc2016-06-23 12:28:21 -07005232 ret = qdf_reset_connection_update();
5233 if (!QDF_IS_STATUS_SUCCESS(ret))
5234 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005235
Krunal Soni3091bcc2016-06-23 12:28:21 -07005236 ret = cds_current_connections_update(adapter->sessionId,
5237 channel_hint,
5238 SIR_UPDATE_REASON_SET_OPER_CHAN);
5239 if (QDF_STATUS_E_FAILURE == ret) {
5240 /* return in the failure case */
5241 hdd_err("ERROR: connections update failed!!");
5242 return -EINVAL;
5243 }
5244
5245 if (QDF_STATUS_SUCCESS == ret) {
5246 /*
5247 * Success is the only case for which we expect hw mode
5248 * change to take place, hence we need to wait.
5249 * For any other return value it should be a pass
5250 * through
5251 */
5252 ret = qdf_wait_for_connection_update();
5253 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5254 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005255 return -EINVAL;
5256 }
5257
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005258 }
5259
5260 return 0;
5261}
5262
5263/**
5264 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5265 * @wiphy: Pointer to wireless phy
5266 * @wdev: Pointer to wireless device
5267 * @data: Pointer to data
5268 * @data_len: Data length
5269 *
5270 * Return: 0 on success, negative errno on failure
5271 */
5272static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5273 struct wireless_dev *wdev,
5274 const void *data,
5275 int data_len)
5276{
5277 int ret = 0;
5278
5279 cds_ssr_protect(__func__);
5280 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5281 data, data_len);
5282 cds_ssr_unprotect(__func__);
5283
5284 return ret;
5285}
5286
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305287static const struct
5288nla_policy
5289qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5290 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5291};
5292
5293/**
5294 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5295 * @wiphy: WIPHY structure pointer
5296 * @wdev: Wireless device structure pointer
5297 * @data: Pointer to the data received
5298 * @data_len: Length of the data received
5299 *
5300 * This function is used to get link properties like nss, rate flags and
5301 * operating frequency for the active connection with the given peer.
5302 *
5303 * Return: 0 on success and errno on failure
5304 */
5305static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5306 struct wireless_dev *wdev,
5307 const void *data,
5308 int data_len)
5309{
5310 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5311 struct net_device *dev = wdev->netdev;
5312 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5313 hdd_station_ctx_t *hdd_sta_ctx;
5314 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305315 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305316 uint32_t sta_id;
5317 struct sk_buff *reply_skb;
5318 uint32_t rate_flags = 0;
5319 uint8_t nss;
5320 uint8_t final_rate_flags = 0;
5321 uint32_t freq;
5322
Jeff Johnson1f61b612016-02-12 16:28:33 -08005323 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305324
Anurag Chouhan6d760662016-02-20 16:05:43 +05305325 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305326 hdd_err("Command not allowed in FTM mode");
5327 return -EPERM;
5328 }
5329
5330 if (0 != wlan_hdd_validate_context(hdd_ctx))
5331 return -EINVAL;
5332
5333 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5334 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005335 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305336 return -EINVAL;
5337 }
5338
5339 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005340 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305341 adapter->device_mode);
5342 return -EINVAL;
5343 }
5344
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305345 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305346 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005347 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305348 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5349
Krunal Sonib4326f22016-03-10 13:05:51 -08005350 if (adapter->device_mode == QDF_STA_MODE ||
5351 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305352 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5353 if ((hdd_sta_ctx->conn_info.connState !=
5354 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305355 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305356 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005357 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305358 MAC_ADDR_ARRAY(peer_mac));
5359 return -EINVAL;
5360 }
5361
5362 nss = hdd_sta_ctx->conn_info.nss;
5363 freq = cds_chan_to_freq(
5364 hdd_sta_ctx->conn_info.operationChannel);
5365 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005366 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5367 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305368
5369 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5370 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305371 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305372 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305373 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305374 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305375 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305376 break;
5377 }
5378
5379 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005380 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305381 MAC_ADDR_ARRAY(peer_mac));
5382 return -EINVAL;
5383 }
5384
5385 nss = adapter->aStaInfo[sta_id].nss;
5386 freq = cds_chan_to_freq(
5387 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5388 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5389 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005390 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305391 MAC_ADDR_ARRAY(peer_mac));
5392 return -EINVAL;
5393 }
5394
5395 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5396 if (rate_flags & eHAL_TX_RATE_VHT80) {
5397 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005398#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305399 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005400#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305401 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5402 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005403#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305404 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005405#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305406 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5407 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5408 } else if (rate_flags &
5409 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5410 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005411#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305412 if (rate_flags & eHAL_TX_RATE_HT40)
5413 final_rate_flags |=
5414 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005415#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305416 }
5417
5418 if (rate_flags & eHAL_TX_RATE_SGI) {
5419 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5420 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5421 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5422 }
5423 }
5424
5425 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5426 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5427
5428 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005429 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305430 return -EINVAL;
5431 }
5432
5433 if (nla_put_u8(reply_skb,
5434 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5435 nss) ||
5436 nla_put_u8(reply_skb,
5437 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5438 final_rate_flags) ||
5439 nla_put_u32(reply_skb,
5440 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5441 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005442 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305443 kfree_skb(reply_skb);
5444 return -EINVAL;
5445 }
5446
5447 return cfg80211_vendor_cmd_reply(reply_skb);
5448}
5449
5450/**
5451 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5452 * properties.
5453 * @wiphy: WIPHY structure pointer
5454 * @wdev: Wireless device structure pointer
5455 * @data: Pointer to the data received
5456 * @data_len: Length of the data received
5457 *
5458 * This function is used to get link properties like nss, rate flags and
5459 * operating frequency for the active connection with the given peer.
5460 *
5461 * Return: 0 on success and errno on failure
5462 */
5463static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5464 struct wireless_dev *wdev,
5465 const void *data,
5466 int data_len)
5467{
5468 int ret = 0;
5469
5470 cds_ssr_protect(__func__);
5471 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5472 wdev, data, data_len);
5473 cds_ssr_unprotect(__func__);
5474
5475 return ret;
5476}
5477
Peng Xu278d0122015-09-24 16:34:17 -07005478static const struct
5479nla_policy
5480qca_wlan_vendor_ota_test_policy
5481[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5482 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5483};
5484
5485/**
5486 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5487 * @wiphy: Pointer to wireless phy
5488 * @wdev: Pointer to wireless device
5489 * @data: Pointer to data
5490 * @data_len: Data length
5491 *
5492 * Return: 0 on success, negative errno on failure
5493 */
5494static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5495 struct wireless_dev *wdev,
5496 const void *data,
5497 int data_len)
5498{
5499 struct net_device *dev = wdev->netdev;
5500 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5501 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5502 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5503 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5504 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305505 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005506 uint32_t current_roam_state;
5507
Jeff Johnson1f61b612016-02-12 16:28:33 -08005508 ENTER_DEV(dev);
5509
Anurag Chouhan6d760662016-02-20 16:05:43 +05305510 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005511 hdd_err("Command not allowed in FTM mode");
5512 return -EPERM;
5513 }
5514
5515 if (0 != wlan_hdd_validate_context(hdd_ctx))
5516 return -EINVAL;
5517
5518 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5519 data, data_len,
5520 qca_wlan_vendor_ota_test_policy)) {
5521 hdd_err("invalid attr");
5522 return -EINVAL;
5523 }
5524
5525 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5526 hdd_err("attr ota test failed");
5527 return -EINVAL;
5528 }
5529
5530 ota_enable = nla_get_u8(
5531 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5532
5533 hdd_info(" OTA test enable = %d", ota_enable);
5534 if (ota_enable != 1) {
5535 hdd_err("Invalid value, only enable test mode is supported!");
5536 return -EINVAL;
5537 }
5538
5539 current_roam_state =
5540 sme_get_current_roam_state(hal, adapter->sessionId);
5541 status = sme_stop_roaming(hal, adapter->sessionId,
5542 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305543 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005544 hdd_err("Enable/Disable roaming failed");
5545 return -EINVAL;
5546 }
5547
5548 status = sme_ps_enable_disable(hal, adapter->sessionId,
5549 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305550 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005551 hdd_err("Enable/Disable power save failed");
5552 /* restore previous roaming setting */
5553 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5554 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5555 status = sme_start_roaming(hal, adapter->sessionId,
5556 eCsrHddIssued);
5557 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5558 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5559 status = sme_stop_roaming(hal, adapter->sessionId,
5560 eCsrHddIssued);
5561
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305562 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005563 hdd_err("Restoring roaming state failed");
5564
5565 return -EINVAL;
5566 }
5567
5568
5569 return 0;
5570}
5571
5572/**
5573 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5574 * @wiphy: Pointer to wireless phy
5575 * @wdev: Pointer to wireless device
5576 * @data: Pointer to data
5577 * @data_len: Data length
5578 *
5579 * Return: 0 on success, negative errno on failure
5580 */
5581static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5582 struct wireless_dev *wdev,
5583 const void *data,
5584 int data_len)
5585{
5586 int ret = 0;
5587
5588 cds_ssr_protect(__func__);
5589 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5590 cds_ssr_unprotect(__func__);
5591
5592 return ret;
5593}
5594
Peng Xu4d67c8f2015-10-16 16:02:26 -07005595/**
5596 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5597 * @wiphy: Pointer to wireless phy
5598 * @wdev: Pointer to wireless device
5599 * @data: Pointer to data
5600 * @data_len: Data length
5601 *
5602 * Return: 0 on success, negative errno on failure
5603 */
5604static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5605 struct wireless_dev *wdev,
5606 const void *data,
5607 int data_len)
5608{
5609 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5610 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005611 hdd_adapter_t *adapter;
5612 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005613 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5614 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005615 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005616
Jeff Johnson1f61b612016-02-12 16:28:33 -08005617 ENTER_DEV(dev);
5618
Peng Xu4d67c8f2015-10-16 16:02:26 -07005619 ret = wlan_hdd_validate_context(hdd_ctx);
5620 if (ret)
5621 return ret;
5622
5623 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5624
5625 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5626 data, data_len, NULL)) {
5627 hdd_err("Invalid ATTR");
5628 return -EINVAL;
5629 }
5630
5631 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5632 hdd_err("attr tx power scale failed");
5633 return -EINVAL;
5634 }
5635
5636 scale_value = nla_get_u8(tb
5637 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5638
5639 if (scale_value > MAX_TXPOWER_SCALE) {
5640 hdd_err("Invalid tx power scale level");
5641 return -EINVAL;
5642 }
5643
Peng Xu62c8c432016-05-09 15:23:02 -07005644 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005645
Peng Xu62c8c432016-05-09 15:23:02 -07005646 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005647 hdd_err("Set tx power scale failed");
5648 return -EINVAL;
5649 }
5650
5651 return 0;
5652}
5653
5654/**
5655 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5656 * @wiphy: Pointer to wireless phy
5657 * @wdev: Pointer to wireless device
5658 * @data: Pointer to data
5659 * @data_len: Data length
5660 *
5661 * Return: 0 on success, negative errno on failure
5662 */
5663static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5664 struct wireless_dev *wdev,
5665 const void *data,
5666 int data_len)
5667{
Peng Xu62c8c432016-05-09 15:23:02 -07005668 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005669
5670 cds_ssr_protect(__func__);
5671 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5672 data, data_len);
5673 cds_ssr_unprotect(__func__);
5674
5675 return ret;
5676}
5677
5678/**
5679 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5680 * @wiphy: Pointer to wireless phy
5681 * @wdev: Pointer to wireless device
5682 * @data: Pointer to data
5683 * @data_len: Data length
5684 *
5685 * Return: 0 on success, negative errno on failure
5686 */
5687static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5688 struct wireless_dev *wdev,
5689 const void *data,
5690 int data_len)
5691{
5692 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5693 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005694 hdd_adapter_t *adapter;
5695 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005696 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5697 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005698 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005699
Jeff Johnson1f61b612016-02-12 16:28:33 -08005700 ENTER_DEV(dev);
5701
Peng Xu4d67c8f2015-10-16 16:02:26 -07005702 ret = wlan_hdd_validate_context(hdd_ctx);
5703 if (ret)
5704 return ret;
5705
5706 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5707
5708 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5709 data, data_len, NULL)) {
5710 hdd_err("Invalid ATTR");
5711 return -EINVAL;
5712 }
5713
5714 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5715 hdd_err("attr tx power decrease db value failed");
5716 return -EINVAL;
5717 }
5718
5719 scale_value = nla_get_u8(tb
5720 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5721
Peng Xu62c8c432016-05-09 15:23:02 -07005722 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5723 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005724
Peng Xu62c8c432016-05-09 15:23:02 -07005725 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005726 hdd_err("Set tx power decrease db failed");
5727 return -EINVAL;
5728 }
5729
5730 return 0;
5731}
5732
5733/**
5734 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5735 * @wiphy: Pointer to wireless phy
5736 * @wdev: Pointer to wireless device
5737 * @data: Pointer to data
5738 * @data_len: Data length
5739 *
5740 * Return: 0 on success, negative errno on failure
5741 */
5742static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5743 struct wireless_dev *wdev,
5744 const void *data,
5745 int data_len)
5746{
Peng Xu62c8c432016-05-09 15:23:02 -07005747 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005748
5749 cds_ssr_protect(__func__);
5750 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5751 data, data_len);
5752 cds_ssr_unprotect(__func__);
5753
5754 return ret;
5755}
Peng Xu8fdaa492016-06-22 10:20:47 -07005756
5757/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305758 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5759 * @wiphy: Pointer to wireless phy
5760 * @wdev: Pointer to wireless device
5761 * @data: Pointer to data
5762 * @data_len: Data length
5763 *
5764 * Processes the conditional channel switch request and invokes the helper
5765 * APIs to process the channel switch request.
5766 *
5767 * Return: 0 on success, negative errno on failure
5768 */
5769static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5770 struct wireless_dev *wdev,
5771 const void *data,
5772 int data_len)
5773{
5774 int ret;
5775 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5776 struct net_device *dev = wdev->netdev;
5777 hdd_adapter_t *adapter;
5778 struct nlattr
5779 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5780 uint32_t freq_len, i;
5781 uint32_t *freq;
5782 uint8_t chans[QDF_MAX_NUM_CHAN];
5783
5784 ENTER_DEV(dev);
5785
5786 ret = wlan_hdd_validate_context(hdd_ctx);
5787 if (ret)
5788 return ret;
5789
5790 if (!hdd_ctx->config->enableDFSMasterCap) {
5791 hdd_err("DFS master capability is not present in the driver");
5792 return -EINVAL;
5793 }
5794
5795 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5796 hdd_err("Command not allowed in FTM mode");
5797 return -EPERM;
5798 }
5799
5800 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5801 if (adapter->device_mode != QDF_SAP_MODE) {
5802 hdd_err("Invalid device mode %d", adapter->device_mode);
5803 return -EINVAL;
5804 }
5805
5806 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
5807 data, data_len, NULL)) {
5808 hdd_err("Invalid ATTR");
5809 return -EINVAL;
5810 }
5811
5812 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
5813 hdd_err("Frequency list is missing");
5814 return -EINVAL;
5815 }
5816
5817 freq_len = nla_len(
5818 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
5819 sizeof(uint32_t);
5820
5821 if (freq_len > QDF_MAX_NUM_CHAN) {
5822 hdd_err("insufficient space to hold channels");
5823 return -ENOMEM;
5824 }
5825
5826 hdd_debug("freq_len=%d", freq_len);
5827
5828 freq = nla_data(
5829 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
5830
5831
5832 for (i = 0; i < freq_len; i++) {
5833 if (freq[i] == 0)
5834 chans[i] = 0;
5835 else
5836 chans[i] = ieee80211_frequency_to_channel(freq[i]);
5837
5838 hdd_debug("freq[%d]=%d", i, freq[i]);
5839 }
5840
5841 /*
5842 * The input frequency list from user space is designed to be a
5843 * priority based frequency list. This is only to accommodate any
5844 * future request. But, current requirement is only to perform CAC
5845 * on a single channel. So, the first entry from the list is picked.
5846 *
5847 * If channel is zero, any channel in the available outdoor regulatory
5848 * domain will be selected.
5849 */
5850 ret = wlan_hdd_request_pre_cac(chans[0]);
5851 if (ret) {
5852 hdd_err("pre cac request failed with reason:%d", ret);
5853 return ret;
5854 }
5855
5856 return 0;
5857}
5858
5859/**
Peng Xu8fdaa492016-06-22 10:20:47 -07005860 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
5861 * @wiphy: Pointer to wireless phy
5862 * @wdev: Pointer to wireless device
5863 * @data: Pointer to data
5864 * @data_len: Data length
5865 *
5866 * This function is to process the p2p listen offload start vendor
5867 * command. It parses the input parameters and invoke WMA API to
5868 * send the command to firmware.
5869 *
5870 * Return: 0 on success, negative errno on failure
5871 */
5872static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
5873 struct wireless_dev *wdev,
5874 const void *data,
5875 int data_len)
5876{
5877 int ret;
5878 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5879 struct net_device *dev = wdev->netdev;
5880 hdd_adapter_t *adapter;
5881 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
5882 struct sir_p2p_lo_start params;
5883 QDF_STATUS status;
5884
5885 ENTER_DEV(dev);
5886
5887 ret = wlan_hdd_validate_context(hdd_ctx);
5888 if (ret)
5889 return ret;
5890
5891 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5892 hdd_err("Command not allowed in FTM mode");
5893 return -EPERM;
5894 }
5895
5896 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5897 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
5898 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
5899 (adapter->device_mode != QDF_P2P_GO_MODE)) {
5900 hdd_err("Invalid device mode %d", adapter->device_mode);
5901 return -EINVAL;
5902 }
5903
5904 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
5905 data, data_len, NULL)) {
5906 hdd_err("Invalid ATTR");
5907 return -EINVAL;
5908 }
5909
5910 memset(&params, 0, sizeof(params));
5911
5912 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
5913 params.ctl_flags = 1; /* set to default value */
5914 else
5915 params.ctl_flags = nla_get_u32(tb
5916 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
5917
5918 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
5919 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
5920 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
5921 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
5922 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
5923 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
5924 hdd_err("Attribute parsing failed");
5925 return -EINVAL;
5926 }
5927
5928 params.vdev_id = adapter->sessionId;
5929 params.freq = nla_get_u32(tb
5930 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
5931 if ((params.freq != 2412) && (params.freq != 2437) &&
5932 (params.freq != 2462)) {
5933 hdd_err("Invalid listening channel: %d", params.freq);
5934 return -EINVAL;
5935 }
5936
5937 params.period = nla_get_u32(tb
5938 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
5939 if (!((params.period > 0) && (params.period < UINT_MAX))) {
5940 hdd_err("Invalid period: %d", params.period);
5941 return -EINVAL;
5942 }
5943
5944 params.interval = nla_get_u32(tb
5945 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
5946 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
5947 hdd_err("Invalid interval: %d", params.interval);
5948 return -EINVAL;
5949 }
5950
5951 params.count = nla_get_u32(tb
5952 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
5953 if (!((params.count > 0) && (params.count < UINT_MAX))) {
5954 hdd_err("Invalid count: %d", params.count);
5955 return -EINVAL;
5956 }
5957
5958 params.device_types = nla_data(tb
5959 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
5960 if (params.device_types == NULL) {
5961 hdd_err("Invalid device types");
5962 return -EINVAL;
5963 }
5964
5965 params.dev_types_len = nla_len(tb
5966 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
5967 if (params.dev_types_len < 8) {
5968 hdd_err("Invalid device type length: %d", params.dev_types_len);
5969 return -EINVAL;
5970 }
5971
5972 params.probe_resp_tmplt = nla_data(tb
5973 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
5974 if (params.probe_resp_tmplt == NULL) {
5975 hdd_err("Invalid probe response template");
5976 return -EINVAL;
5977 }
5978
5979 params.probe_resp_len = nla_len(tb
5980 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
5981 if (params.probe_resp_len == 0) {
5982 hdd_err("Invalid probe resp template length: %d",
5983 params.probe_resp_len);
5984 return -EINVAL;
5985 }
5986
5987 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
5988 params.freq, params.period, params.interval, params.count);
5989
5990 status = wma_p2p_lo_start(&params);
5991
5992 if (!QDF_IS_STATUS_SUCCESS(status)) {
5993 hdd_err("P2P LO start failed");
5994 return -EINVAL;
5995 }
5996
5997 return 0;
5998}
5999
6000
6001/**
6002 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6003 * @wiphy: Pointer to wireless phy
6004 * @wdev: Pointer to wireless device
6005 * @data: Pointer to data
6006 * @data_len: Data length
6007 *
6008 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6009 * to process p2p listen offload start vendor command.
6010 *
6011 * Return: 0 on success, negative errno on failure
6012 */
6013static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6014 struct wireless_dev *wdev,
6015 const void *data,
6016 int data_len)
6017{
6018 int ret = 0;
6019
6020 cds_ssr_protect(__func__);
6021 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6022 data, data_len);
6023 cds_ssr_unprotect(__func__);
6024
6025 return ret;
6026}
6027
6028/**
6029 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6030 * @wiphy: Pointer to wireless phy
6031 * @wdev: Pointer to wireless device
6032 * @data: Pointer to data
6033 * @data_len: Data length
6034 *
6035 * This function is to process the p2p listen offload stop vendor
6036 * command. It invokes WMA API to send command to firmware.
6037 *
6038 * Return: 0 on success, negative errno on failure
6039 */
6040static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6041 struct wireless_dev *wdev,
6042 const void *data,
6043 int data_len)
6044{
6045 QDF_STATUS status;
6046 hdd_adapter_t *adapter;
6047 struct net_device *dev = wdev->netdev;
6048
6049 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6050 hdd_err("Command not allowed in FTM mode");
6051 return -EPERM;
6052 }
6053
6054 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6055 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6056 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6057 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6058 hdd_err("Invalid device mode");
6059 return -EINVAL;
6060 }
6061
6062 status = wma_p2p_lo_stop(adapter->sessionId);
6063
6064 if (!QDF_IS_STATUS_SUCCESS(status)) {
6065 hdd_err("P2P LO stop failed");
6066 return -EINVAL;
6067 }
6068
6069 return 0;
6070}
6071
6072/**
6073 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6074 * @wiphy: Pointer to wireless phy
6075 * @wdev: Pointer to wireless device
6076 * @data: Pointer to data
6077 * @data_len: Data length
6078 *
6079 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6080 * to process p2p listen offload stop vendor command.
6081 *
6082 * Return: 0 on success, negative errno on failure
6083 */
6084static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6085 struct wireless_dev *wdev,
6086 const void *data,
6087 int data_len)
6088{
6089 int ret = 0;
6090
6091 cds_ssr_protect(__func__);
6092 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6093 data, data_len);
6094 cds_ssr_unprotect(__func__);
6095
6096 return ret;
6097}
6098
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306099/**
6100 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6101 * @wiphy: Pointer to wireless phy
6102 * @wdev: Pointer to wireless device
6103 * @data: Pointer to data
6104 * @data_len: Data length
6105 *
6106 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6107 * to process the conditional channel switch request.
6108 *
6109 * Return: 0 on success, negative errno on failure
6110 */
6111static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6112 struct wireless_dev *wdev,
6113 const void *data,
6114 int data_len)
6115{
6116 int ret;
6117
6118 cds_ssr_protect(__func__);
6119 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6120 data, data_len);
6121 cds_ssr_unprotect(__func__);
6122
6123 return ret;
6124}
6125
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306126/*
6127 * define short names for the global vendor params
6128 * used by __wlan_hdd_cfg80211_bpf_offload()
6129 */
6130#define BPF_INVALID \
6131 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6132#define BPF_SET_RESET \
6133 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6134#define BPF_VERSION \
6135 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6136#define BPF_FILTER_ID \
6137 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6138#define BPF_PACKET_SIZE \
6139 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6140#define BPF_CURRENT_OFFSET \
6141 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6142#define BPF_PROGRAM \
6143 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6144#define BPF_MAX \
6145 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006146
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306147static const struct nla_policy
6148wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6149 [BPF_SET_RESET] = {.type = NLA_U32},
6150 [BPF_VERSION] = {.type = NLA_U32},
6151 [BPF_FILTER_ID] = {.type = NLA_U32},
6152 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6153 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6154 [BPF_PROGRAM] = {.type = NLA_U8},
6155};
6156
6157/**
6158 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6159 * @hdd_context: hdd_context
6160 * @bpf_get_offload: struct for get offload
6161 *
6162 * This function receives the response/data from the lower layer and
6163 * checks to see if the thread is still waiting then post the results to
6164 * upper layer, if the request has timed out then ignore.
6165 *
6166 * Return: None
6167 */
6168void hdd_get_bpf_offload_cb(void *hdd_context,
6169 struct sir_bpf_get_offload *data)
6170{
6171 hdd_context_t *hdd_ctx = hdd_context;
6172 struct hdd_bpf_context *context;
6173
6174 ENTER();
6175
6176 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006177 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306178 data);
6179 return;
6180 }
6181
6182 spin_lock(&hdd_context_lock);
6183
6184 context = &bpf_context;
6185 /* The caller presumably timed out so there is nothing we can do */
6186 if (context->magic != BPF_CONTEXT_MAGIC) {
6187 spin_unlock(&hdd_context_lock);
6188 return;
6189 }
6190
6191 /* context is valid so caller is still waiting */
6192 /* paranoia: invalidate the magic */
6193 context->magic = 0;
6194
6195 context->capability_response = *data;
6196 complete(&context->completion);
6197
6198 spin_unlock(&hdd_context_lock);
6199
6200 return;
6201}
6202
6203/**
6204 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6205 * @hdd_context: hdd_context
6206 * @bpf_get_offload: struct for get offload
6207 *
6208 * Return: 0 on success, error number otherwise.
6209 */
6210static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6211 struct sir_bpf_get_offload *bpf_get_offload)
6212{
6213 struct sk_buff *skb;
6214 uint32_t nl_buf_len;
6215
6216 ENTER();
6217
6218 nl_buf_len = NLMSG_HDRLEN;
6219 nl_buf_len +=
6220 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6221 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6222
6223 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6224 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006225 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306226 return -ENOMEM;
6227 }
6228
Jeff Johnson77848112016-06-29 14:52:06 -07006229 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306230 bpf_get_offload->bpf_version,
6231 bpf_get_offload->max_bytes_for_bpf_inst);
6232
6233 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6234 bpf_get_offload->max_bytes_for_bpf_inst) ||
6235 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006236 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306237 goto nla_put_failure;
6238 }
6239
6240 cfg80211_vendor_cmd_reply(skb);
6241 EXIT();
6242 return 0;
6243
6244nla_put_failure:
6245 kfree_skb(skb);
6246 return -EINVAL;
6247}
6248
6249/**
6250 * hdd_get_bpf_offload - Get BPF offload Capabilities
6251 * @hdd_ctx: Hdd context
6252 *
6253 * Return: 0 on success, errno on failure
6254 */
6255static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6256{
6257 unsigned long rc;
6258 struct hdd_bpf_context *context;
6259 QDF_STATUS status;
6260 int ret;
6261
6262 ENTER();
6263
6264 spin_lock(&hdd_context_lock);
6265 context = &bpf_context;
6266 context->magic = BPF_CONTEXT_MAGIC;
6267 INIT_COMPLETION(context->completion);
6268 spin_unlock(&hdd_context_lock);
6269
6270 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6271 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006272 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306273 return -EINVAL;
6274 }
6275 /* request was sent -- wait for the response */
6276 rc = wait_for_completion_timeout(&context->completion,
6277 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6278 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006279 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306280 spin_lock(&hdd_context_lock);
6281 context->magic = 0;
6282 spin_unlock(&hdd_context_lock);
6283
6284 return -ETIMEDOUT;
6285 }
6286 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6287 &bpf_context.capability_response);
6288 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006289 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306290
6291 EXIT();
6292 return ret;
6293}
6294
6295/**
6296 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6297 * @hdd_ctx: Hdd context
6298 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306299 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306300 *
6301 * Return: 0 on success; errno on failure
6302 */
6303static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6304 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306305 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306306{
6307 struct sir_bpf_set_offload *bpf_set_offload;
6308 QDF_STATUS status;
6309 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306310 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306311
6312 ENTER();
6313
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306314 if (adapter->device_mode == QDF_STA_MODE ||
6315 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6316 if (!hdd_conn_is_connected(
6317 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6318 hdd_err("Not in Connected state!");
6319 return -ENOTSUPP;
6320 }
6321 }
6322
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306323 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6324 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006325 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306326 return -ENOMEM;
6327 }
6328 qdf_mem_zero(bpf_set_offload, sizeof(*bpf_set_offload));
6329
6330 /* Parse and fetch bpf packet size */
6331 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006332 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306333 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306334 goto fail;
6335 }
6336 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6337
6338 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006339 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306340 goto post_sme;
6341 }
6342
6343 /* Parse and fetch bpf program */
6344 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006345 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306346 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306347 goto fail;
6348 }
6349
6350 prog_len = nla_len(tb[BPF_PROGRAM]);
6351 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306352
6353 if (bpf_set_offload->program == NULL) {
6354 hdd_err("qdf_mem_malloc failed for bpf offload program");
6355 ret = -ENOMEM;
6356 goto fail;
6357 }
6358
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306359 bpf_set_offload->current_length = prog_len;
6360 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306361 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306362
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306363 hdd_info("BPF set instructions");
6364 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6365 bpf_set_offload->program, prog_len);
6366
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306367 /* Parse and fetch filter Id */
6368 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006369 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306370 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306371 goto fail;
6372 }
6373 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6374
6375 /* Parse and fetch current offset */
6376 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006377 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306378 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306379 goto fail;
6380 }
6381 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6382
6383post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006384 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 +05306385 bpf_set_offload->session_id,
6386 bpf_set_offload->version,
6387 bpf_set_offload->filter_id,
6388 bpf_set_offload->total_length,
6389 bpf_set_offload->current_length,
6390 bpf_set_offload->current_offset);
6391
6392 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6393 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006394 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306395 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306396 goto fail;
6397 }
6398 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306399
6400fail:
6401 if (bpf_set_offload->current_length)
6402 qdf_mem_free(bpf_set_offload->program);
6403 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306404 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306405}
6406
6407/**
6408 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6409 * @wiphy: wiphy structure pointer
6410 * @wdev: Wireless device structure pointer
6411 * @data: Pointer to the data received
6412 * @data_len: Length of @data
6413 *
6414 * Return: 0 on success; errno on failure
6415 */
6416static int
6417__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6418 struct wireless_dev *wdev,
6419 const void *data, int data_len)
6420{
6421 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6422 struct net_device *dev = wdev->netdev;
6423 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6424 struct nlattr *tb[BPF_MAX + 1];
6425 int ret_val, packet_filter_subcmd;
6426
6427 ENTER();
6428
6429 ret_val = wlan_hdd_validate_context(hdd_ctx);
6430 if (ret_val)
6431 return ret_val;
6432
6433 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006434 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306435 return -EINVAL;
6436 }
6437
6438 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006439 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306440 return -ENOTSUPP;
6441 }
6442
6443 if (nla_parse(tb, BPF_MAX, data, data_len,
6444 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006445 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306446 return -EINVAL;
6447 }
6448
6449 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006450 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306451 return -EINVAL;
6452 }
6453
6454 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6455
6456 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6457 return hdd_get_bpf_offload(hdd_ctx);
6458 else
6459 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306460 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306461}
6462
6463/**
6464 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6465 * @wiphy: wiphy structure pointer
6466 * @wdev: Wireless device structure pointer
6467 * @data: Pointer to the data received
6468 * @data_len: Length of @data
6469 *
6470 * Return: 0 on success; errno on failure
6471 */
6472
6473static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6474 struct wireless_dev *wdev,
6475 const void *data, int data_len)
6476{
6477 int ret;
6478
6479 cds_ssr_protect(__func__);
6480 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6481 cds_ssr_unprotect(__func__);
6482
6483 return ret;
6484}
6485
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306486/**
6487 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6488 * @pre_cac_adapter: AP adapter used for pre cac
6489 * @status: Status (true or false)
6490 * @handle: Global handle
6491 *
6492 * Sets the status of pre cac i.e., whether the pre cac is active or not
6493 *
6494 * Return: Zero on success, non-zero on failure
6495 */
6496static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6497 bool status, tHalHandle handle)
6498{
6499 QDF_STATUS ret;
6500
6501 ret = wlan_sap_set_pre_cac_status(
6502 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6503 if (QDF_IS_STATUS_ERROR(ret))
6504 return -EINVAL;
6505
6506 return 0;
6507}
6508
6509/**
6510 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6511 * @ap_adapter: AP adapter
6512 * @chan_before_pre_cac: Channel
6513 *
6514 * Saves the channel which the AP was beaconing on before moving to the pre
6515 * cac channel. If radar is detected on the pre cac channel, this saved
6516 * channel will be used for AP operations.
6517 *
6518 * Return: Zero on success, non-zero on failure
6519 */
6520static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6521 uint8_t chan_before_pre_cac)
6522{
6523 QDF_STATUS ret;
6524
6525 ret = wlan_sap_set_chan_before_pre_cac(
6526 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6527 if (QDF_IS_STATUS_ERROR(ret))
6528 return -EINVAL;
6529
6530 return 0;
6531}
6532
6533/**
6534 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6535 * @ap_adapter: AP adapter
6536 * @nol: Non-occupancy list
6537 * @nol_len: Length of NOL
6538 *
6539 * Get the NOL for SAP
6540 *
6541 * Return: Zero on success, non-zero on failure
6542 */
6543static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6544 uint32_t *nol_len)
6545{
6546 QDF_STATUS ret;
6547
6548 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6549 nol, nol_len);
6550 if (QDF_IS_STATUS_ERROR(ret))
6551 return -EINVAL;
6552
6553 return 0;
6554}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306555
6556/**
6557 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6558 * @hdd_ctx: HDD context
6559 * @ap_adapter: AP adapter
6560 * @channel: Channel requested by userspace
6561 * @pre_cac_chan: Pointer to the pre CAC channel
6562 *
6563 * Validates the channel provided by userspace. If user provided channel 0,
6564 * a valid outdoor channel must be selected from the regulatory channel.
6565 *
6566 * Return: Zero on success and non zero value on error
6567 */
6568int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6569 hdd_adapter_t *ap_adapter,
6570 uint8_t channel,
6571 uint8_t *pre_cac_chan)
6572{
6573 uint32_t i, j;
6574 QDF_STATUS status;
6575 int ret;
6576 uint8_t nol[QDF_MAX_NUM_CHAN];
6577 uint32_t nol_len = 0, weight_len = 0;
6578 bool found;
6579 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6580 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6581 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6582
6583 if (0 == channel) {
6584 /* Channel is not obtained from PCL because PCL may not have
6585 * the entire channel list. For example: if SAP is up on
6586 * channel 6 and PCL is queried for the next SAP interface,
6587 * if SCC is preferred, the PCL will contain only the channel
6588 * 6. But, we are in need of a DFS channel. So, going with the
6589 * first channel from the valid channel list.
6590 */
6591 status = cds_get_valid_chans(channel_list, &len);
6592 if (QDF_IS_STATUS_ERROR(status)) {
6593 hdd_err("Failed to get channel list");
6594 return -EINVAL;
6595 }
6596 cds_update_with_safe_channel_list(channel_list, &len,
6597 pcl_weights, weight_len);
6598 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6599 for (i = 0; i < len; i++) {
6600 found = false;
6601 for (j = 0; j < nol_len; j++) {
6602 if (channel_list[i] == nol[j]) {
6603 found = true;
6604 break;
6605 }
6606 }
6607 if (found)
6608 continue;
6609 if (CDS_IS_DFS_CH(channel_list[i])) {
6610 *pre_cac_chan = channel_list[i];
6611 break;
6612 }
6613 }
6614 if (*pre_cac_chan == 0) {
6615 hdd_err("unable to find outdoor channel");
6616 return -EINVAL;
6617 }
6618 } else {
6619 /* Only when driver selects a channel, check is done for
6620 * unnsafe and NOL channels. When user provides a fixed channel
6621 * the user is expected to take care of this.
6622 */
6623 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6624 !CDS_IS_DFS_CH(channel)) {
6625 hdd_err("Invalid channel for pre cac:%d", channel);
6626 return -EINVAL;
6627 } else {
6628 *pre_cac_chan = channel;
6629 }
6630 }
6631 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6632 return 0;
6633}
6634
6635/**
6636 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6637 * @channel: Channel option provided by userspace
6638 *
6639 * Sets the driver to the required hardware mode and start an adapater for
6640 * pre CAC which will mimic an AP.
6641 *
6642 * Return: Zero on success, non-zero value on error
6643 */
6644int wlan_hdd_request_pre_cac(uint8_t channel)
6645{
6646 uint8_t pre_cac_chan = 0;
6647 hdd_context_t *hdd_ctx;
6648 int ret;
6649 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6650 hdd_ap_ctx_t *hdd_ap_ctx;
6651 QDF_STATUS status;
6652 struct wiphy *wiphy;
6653 struct net_device *dev;
6654 struct cfg80211_chan_def chandef;
6655 enum nl80211_channel_type channel_type;
6656 uint32_t freq;
6657 struct ieee80211_channel *chan;
6658 tHalHandle handle;
6659 bool val;
6660
6661 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6662 if (0 != wlan_hdd_validate_context(hdd_ctx))
6663 return -EINVAL;
6664
6665 if (cds_get_connection_count() > 1) {
6666 hdd_err("pre cac not allowed in concurrency");
6667 return -EINVAL;
6668 }
6669
6670 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6671 if (!ap_adapter) {
6672 hdd_err("unable to get SAP adapter");
6673 return -EINVAL;
6674 }
6675
6676 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6677 if (!handle) {
6678 hdd_err("Invalid handle");
6679 return -EINVAL;
6680 }
6681
6682 val = wlan_sap_is_pre_cac_active(handle);
6683 if (val) {
6684 hdd_err("pre cac is already in progress");
6685 return -EINVAL;
6686 }
6687
6688 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6689 if (!hdd_ap_ctx) {
6690 hdd_err("SAP context is NULL");
6691 return -EINVAL;
6692 }
6693
6694 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6695 hdd_err("SAP is already on DFS channel:%d",
6696 hdd_ap_ctx->operatingChannel);
6697 return -EINVAL;
6698 }
6699
6700 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6701 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6702 hdd_ap_ctx->operatingChannel);
6703 return -EINVAL;
6704 }
6705
6706 hdd_info("channel:%d", channel);
6707
6708 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6709 &pre_cac_chan);
6710 if (ret != 0)
6711 return ret;
6712
6713 /* Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
6714 * connection update should result in DBS mode
6715 */
6716 status = cds_update_and_wait_for_connection_update(
6717 ap_adapter->sessionId,
6718 pre_cac_chan,
6719 SIR_UPDATE_REASON_PRE_CAC);
6720 if (QDF_IS_STATUS_ERROR(status)) {
6721 hdd_err("error in moving to DBS mode");
6722 return -EINVAL;
6723 }
6724
6725 hdd_debug("starting pre cac SAP adapter");
6726
6727 /* Starting a SAP adapter:
6728 * Instead of opening an adapter, we could just do a SME open session
6729 * for AP type. But, start BSS would still need an adapter.
6730 * So, this option is not taken.
6731 *
6732 * hdd open adapter is going to register this precac interface with
6733 * user space. This interface though exposed to user space will be in
6734 * DOWN state. Consideration was done to avoid this registration to the
6735 * user space. But, as part of SAP operations multiple events are sent
6736 * to user space. Some of these events received from unregistered
6737 * interface was causing crashes. So, retaining the registration.
6738 *
6739 * So, this interface would remain registered and will remain in DOWN
6740 * state for the CAC duration. We will add notes in the feature
6741 * announcement to not use this temporary interface for any activity
6742 * from user space.
6743 */
6744 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
6745 wlan_hdd_get_intf_addr(hdd_ctx),
6746 NET_NAME_UNKNOWN, true);
6747 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306748 hdd_err("error opening the pre cac adapter");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306749 return -EINVAL;
6750 }
6751
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306752 /*
6753 * This interface is internally created by the driver. So, no interface
6754 * up comes for this interface from user space and hence starting
6755 * the adapter internally.
6756 */
6757 if (hdd_start_adapter(pre_cac_adapter)) {
6758 hdd_err("error starting the pre cac adapter");
6759 goto close_pre_cac_adapter;
6760 }
6761
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306762 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6763
6764 wiphy = hdd_ctx->wiphy;
6765 dev = pre_cac_adapter->dev;
6766
6767 /* Since this is only a dummy interface lets us use the IEs from the
6768 * other active SAP interface. In regular scenarios, these IEs would
6769 * come from the user space entity
6770 */
6771 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6772 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6773 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6774 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306775 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306776 }
6777 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6778 ap_adapter->sessionCtx.ap.beacon,
6779 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6780 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6781 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6782 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6783 ap_adapter->sessionCtx.ap.sapConfig.authType;
6784
6785 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6786 * to operate on the same bandwidth as that of the 2.4GHz operations.
6787 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6788 */
6789 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6790 case CH_WIDTH_20MHZ:
6791 channel_type = NL80211_CHAN_HT20;
6792 break;
6793 case CH_WIDTH_40MHZ:
6794 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6795 ap_adapter->sessionCtx.ap.sapConfig.channel)
6796 channel_type = NL80211_CHAN_HT40PLUS;
6797 else
6798 channel_type = NL80211_CHAN_HT40MINUS;
6799 break;
6800 default:
6801 channel_type = NL80211_CHAN_NO_HT;
6802 break;
6803 }
6804
6805 freq = cds_chan_to_freq(pre_cac_chan);
6806 chan = __ieee80211_get_channel(wiphy, freq);
6807 if (!chan) {
6808 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306809 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306810 }
6811
6812 cfg80211_chandef_create(&chandef, chan, channel_type);
6813
6814 hdd_debug("orig width:%d channel_type:%d freq:%d",
6815 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
6816 channel_type, freq);
6817
6818 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
6819 if (0 != ret) {
6820 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306821 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306822 }
6823
6824 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
6825 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
6826 eHIDDEN_SSID_NOT_IN_USE, false);
6827 if (QDF_IS_STATUS_ERROR(status)) {
6828 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306829 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306830 }
6831
6832 /*
6833 * The pre cac status is set here. But, it would not be reset explicitly
6834 * anywhere, since after the pre cac success/failure, the pre cac
6835 * adapter itself would be removed.
6836 */
6837 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
6838 if (0 != ret) {
6839 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306840 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306841 }
6842
6843 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
6844 hdd_ap_ctx->operatingChannel);
6845 if (0 != ret) {
6846 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306847 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306848 }
6849
6850 ap_adapter->pre_cac_chan = pre_cac_chan;
6851
6852 return 0;
6853
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306854stop_close_pre_cac_adapter:
6855 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306856 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
6857 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306858close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306859 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
6860 return -EINVAL;
6861}
6862
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306863/**
6864 * hdd_init_bpf_completion() - Initialize the completion event for bpf
6865 *
6866 * Return: None
6867 */
6868void hdd_init_bpf_completion(void)
6869{
6870 init_completion(&bpf_context.completion);
6871}
6872
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306873static const struct nla_policy
6874wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
6875 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
6876};
6877
Agrawal Ashish65634612016-08-18 13:24:32 +05306878static const struct nla_policy
6879wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
6880 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
6881 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
6882};
6883
6884/**
6885 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
6886 * @wiphy: Pointer to wireless phy
6887 * @wdev: Pointer to wireless device
6888 * @data: Pointer to data
6889 * @data_len: Length of @data
6890 *
6891 * This function parses the incoming NL vendor command data attributes and
6892 * updates the SAP context about channel_hint and DFS mode.
6893 * If channel_hint is set, SAP will choose that channel
6894 * as operating channel.
6895 *
6896 * If DFS mode is enabled, driver will include DFS channels
6897 * in ACS else driver will skip DFS channels.
6898 *
6899 * Return: 0 on success, negative errno on failure
6900 */
6901static int
6902__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
6903 struct wireless_dev *wdev,
6904 const void *data, int data_len)
6905{
6906 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6907 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
6908 int ret;
6909 struct acs_dfs_policy *acs_policy;
6910 int mode = DFS_MODE_NONE;
6911 int channel_hint = 0;
6912
6913 ENTER_DEV(wdev->netdev);
6914
6915 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6916 hdd_err("Command not allowed in FTM mode");
6917 return -EINVAL;
6918 }
6919
6920 ret = wlan_hdd_validate_context(hdd_ctx);
6921 if (0 != ret)
6922 return ret;
6923
6924 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
6925 data, data_len,
6926 wlan_hdd_set_acs_dfs_config_policy)) {
6927 hdd_err("invalid attr");
6928 return -EINVAL;
6929 }
6930
6931 acs_policy = &hdd_ctx->acs_policy;
6932 /*
6933 * SCM sends this attribute to restrict SAP from choosing
6934 * DFS channels from ACS.
6935 */
6936 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
6937 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
6938
6939 if (!IS_DFS_MODE_VALID(mode)) {
6940 hdd_err("attr acs dfs mode is not valid");
6941 return -EINVAL;
6942 }
6943 acs_policy->acs_dfs_mode = mode;
6944
6945 /*
6946 * SCM sends this attribute to provide an active channel,
6947 * to skip redundant ACS between drivers, and save driver start up time
6948 */
6949 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
6950 channel_hint = nla_get_u8(
6951 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
6952
6953 if (!IS_CHANNEL_VALID(channel_hint)) {
6954 hdd_err("acs channel is not valid");
6955 return -EINVAL;
6956 }
6957 acs_policy->acs_channel = channel_hint;
6958
6959 return 0;
6960}
6961
6962/**
6963 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
6964 * @wiphy: wiphy structure pointer
6965 * @wdev: Wireless device structure pointer
6966 * @data: Pointer to the data received
6967 * @data_len: Length of @data
6968 *
6969 * This function parses the incoming NL vendor command data attributes and
6970 * updates the SAP context about channel_hint and DFS mode.
6971 *
6972 * Return: 0 on success; errno on failure
6973 */
6974static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
6975 struct wireless_dev *wdev,
6976 const void *data, int data_len)
6977{
6978 int ret;
6979
6980 cds_ssr_protect(__func__);
6981 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
6982 cds_ssr_unprotect(__func__);
6983
6984 return ret;
6985}
6986
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306987/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05306988 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
6989 * @mode : cfg80211 dfs mode
6990 *
6991 * Return: return csr sta roam dfs mode else return NONE
6992 */
6993static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
6994 enum dfs_mode mode)
6995{
6996 switch (mode) {
6997 case DFS_MODE_ENABLE:
6998 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
6999 break;
7000 case DFS_MODE_DISABLE:
7001 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7002 break;
7003 case DFS_MODE_DEPRIORITIZE:
7004 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7005 break;
7006 default:
7007 hdd_err("STA Roam policy dfs mode is NONE");
7008 return CSR_STA_ROAM_POLICY_NONE;
7009 }
7010}
7011
7012static const struct nla_policy
7013wlan_hdd_set_sta_roam_config_policy[
7014QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7015 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7016 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7017};
7018
7019/**
7020 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7021 * for station connection or roaming.
7022 * @wiphy: Pointer to wireless phy
7023 * @wdev: Pointer to wireless device
7024 * @data: Pointer to data
7025 * @data_len: Length of @data
7026 *
7027 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7028 * channels needs to be skipped in scanning or not.
7029 * If dfs_mode is disabled, driver will not scan DFS channels.
7030 * If skip_unsafe_channels is set, driver will skip unsafe channels
7031 * in Scanning.
7032 *
7033 * Return: 0 on success, negative errno on failure
7034 */
7035static int
7036__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7037 struct wireless_dev *wdev,
7038 const void *data, int data_len)
7039{
7040 struct net_device *dev = wdev->netdev;
7041 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7042 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7043 struct nlattr *tb[
7044 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7045 int ret;
7046 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7047 enum dfs_mode mode = DFS_MODE_NONE;
7048 bool skip_unsafe_channels = false;
7049 QDF_STATUS status;
7050
7051 ENTER_DEV(dev);
7052
7053 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7054 hdd_err("Command not allowed in FTM mode");
7055 return -EINVAL;
7056 }
7057
7058 ret = wlan_hdd_validate_context(hdd_ctx);
7059 if (0 != ret)
7060 return ret;
7061 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7062 data, data_len,
7063 wlan_hdd_set_sta_roam_config_policy)) {
7064 hdd_err("invalid attr");
7065 return -EINVAL;
7066 }
7067 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7068 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7069 if (!IS_DFS_MODE_VALID(mode)) {
7070 hdd_err("attr sta roam dfs mode policy is not valid");
7071 return -EINVAL;
7072 }
7073
7074 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7075
7076 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7077 skip_unsafe_channels = nla_get_u8(
7078 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7079
7080 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7081 skip_unsafe_channels, adapter->sessionId);
7082
7083 if (!QDF_IS_STATUS_SUCCESS(status)) {
7084 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7085 return -EINVAL;
7086 }
7087 return 0;
7088}
7089
7090/**
7091 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7092 * connection and roaming for station.
7093 * @wiphy: wiphy structure pointer
7094 * @wdev: Wireless device structure pointer
7095 * @data: Pointer to the data received
7096 * @data_len: Length of @data
7097 *
7098 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7099 * channels needs to be skipped in scanning or not.
7100 * If dfs_mode is disabled, driver will not scan DFS channels.
7101 * If skip_unsafe_channels is set, driver will skip unsafe channels
7102 * in Scanning.
7103 * Return: 0 on success; errno on failure
7104 */
7105static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7106 struct wireless_dev *wdev,
7107 const void *data, int data_len)
7108{
7109 int ret;
7110
7111 cds_ssr_protect(__func__);
7112 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7113 cds_ssr_unprotect(__func__);
7114
7115 return ret;
7116}
7117
Agrawal Ashish467dde42016-09-08 18:44:22 +05307118#ifdef FEATURE_WLAN_CH_AVOID
7119/**
7120 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7121 * is on unsafe channel.
7122 * @wiphy: wiphy structure pointer
7123 * @wdev: Wireless device structure pointer
7124 * @data: Pointer to the data received
7125 * @data_len: Length of @data
7126 *
7127 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7128 * on any of unsafe channels.
7129 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7130 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7131 *
7132 * Return: 0 on success; errno on failure
7133 */
7134static int
7135__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7136 struct wireless_dev *wdev,
7137 const void *data, int data_len)
7138{
7139 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7140 int ret;
7141 uint16_t unsafe_channel_count;
7142 int unsafe_channel_index;
7143 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7144
7145 ENTER_DEV(wdev->netdev);
7146
7147 if (!qdf_ctx) {
7148 cds_err("qdf_ctx is NULL");
7149 return -EINVAL;
7150 }
7151
7152 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7153 hdd_err("Command not allowed in FTM mode");
7154 return -EINVAL;
7155 }
7156
7157 ret = wlan_hdd_validate_context(hdd_ctx);
7158 if (0 != ret)
7159 return ret;
7160 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7161 &(hdd_ctx->unsafe_channel_count),
7162 sizeof(hdd_ctx->unsafe_channel_list));
7163
7164 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7165 (uint16_t)NUM_CHANNELS);
7166 for (unsafe_channel_index = 0;
7167 unsafe_channel_index < unsafe_channel_count;
7168 unsafe_channel_index++) {
7169 hdd_info("Channel %d is not safe",
7170 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7171 }
7172 hdd_unsafe_channel_restart_sap(hdd_ctx);
7173 return 0;
7174}
7175
7176/**
7177 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7178 * is on unsafe channel.
7179 * @wiphy: wiphy structure pointer
7180 * @wdev: Wireless device structure pointer
7181 * @data: Pointer to the data received
7182 * @data_len: Length of @data
7183 *
7184 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7185 * on any of unsafe channels.
7186 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7187 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7188 *
7189 * Return: 0 on success; errno on failure
7190 */
7191static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7192 struct wireless_dev *wdev,
7193 const void *data, int data_len)
7194{
7195 int ret;
7196
7197 cds_ssr_protect(__func__);
7198 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7199 cds_ssr_unprotect(__func__);
7200
7201 return ret;
7202}
7203
7204#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307205/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307206 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7207 * SAP is on unsafe channel.
7208 * @wiphy: wiphy structure pointer
7209 * @wdev: Wireless device structure pointer
7210 * @data: Pointer to the data received
7211 * @data_len: Length of @data
7212 *
7213 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7214 * driver.
7215 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7216 * will initiate restart of sap.
7217 *
7218 * Return: 0 on success; errno on failure
7219 */
7220static int
7221__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7222 struct wireless_dev *wdev,
7223 const void *data, int data_len)
7224{
7225 struct net_device *ndev = wdev->netdev;
7226 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7227 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7228 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7229 uint8_t config_channel = 0;
7230 hdd_ap_ctx_t *ap_ctx;
7231 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307232 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307233
7234 ENTER();
7235
7236 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007237 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307238 return -EINVAL;
7239 }
7240
7241 ret = wlan_hdd_validate_context(hdd_ctx);
7242 if (0 != ret)
7243 return -EINVAL;
7244
7245 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7246 data, data_len,
7247 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007248 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307249 return -EINVAL;
7250 }
7251
7252 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7253 if (!test_bit(SOFTAP_BSS_STARTED,
7254 &hostapd_adapter->event_flags)) {
7255 hdd_err("SAP is not started yet. Restart sap will be invalid");
7256 return -EINVAL;
7257 }
7258
7259 config_channel =
7260 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7261
7262 if (!((IS_24G_CH(config_channel)) ||
7263 (IS_5G_CH(config_channel)))) {
7264 hdd_err("Channel %d is not valid to restart SAP",
7265 config_channel);
7266 return -ENOTSUPP;
7267 }
7268
7269 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7270 ap_ctx->sapConfig.channel = config_channel;
7271 ap_ctx->sapConfig.ch_params.ch_width =
7272 ap_ctx->sapConfig.ch_width_orig;
7273
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007274 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307275 ap_ctx->sapConfig.sec_ch,
7276 &ap_ctx->sapConfig.ch_params);
7277
7278 cds_restart_sap(hostapd_adapter);
7279 }
7280
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307281 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7282 uint32_t freq_len, i;
7283 uint32_t *freq;
7284 uint8_t chans[QDF_MAX_NUM_CHAN];
7285
7286 hdd_debug("setting mandatory freq/chan list");
7287
7288 freq_len = nla_len(
7289 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7290 sizeof(uint32_t);
7291
7292 if (freq_len > QDF_MAX_NUM_CHAN) {
7293 hdd_err("insufficient space to hold channels");
7294 return -ENOMEM;
7295 }
7296
7297 freq = nla_data(
7298 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7299
7300 hdd_debug("freq_len=%d", freq_len);
7301
7302 for (i = 0; i < freq_len; i++) {
7303 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7304 hdd_debug("freq[%d]=%d", i, freq[i]);
7305 }
7306
7307 status = cds_set_sap_mandatory_channels(chans, freq_len);
7308 if (QDF_IS_STATUS_ERROR(status))
7309 return -EINVAL;
7310 }
7311
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307312 return 0;
7313}
7314
7315/**
7316 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7317 * @wiphy: wiphy structure pointer
7318 * @wdev: Wireless device structure pointer
7319 * @data: Pointer to the data received
7320 * @data_len: Length of @data
7321 *
7322 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7323 * driver.
7324 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7325 * will initiate restart of sap.
7326 *
7327 * Return: 0 on success; errno on failure
7328 */
7329static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7330 struct wireless_dev *wdev,
7331 const void *data, int data_len)
7332{
7333 int ret;
7334
7335 cds_ssr_protect(__func__);
7336 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7337 wdev, data, data_len);
7338 cds_ssr_unprotect(__func__);
7339
7340 return ret;
7341}
7342
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307343#undef BPF_INVALID
7344#undef BPF_SET_RESET
7345#undef BPF_VERSION
7346#undef BPF_ID
7347#undef BPF_PACKET_SIZE
7348#undef BPF_CURRENT_OFFSET
7349#undef BPF_PROGRAM
7350#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307351
7352/**
7353 * define short names for the global vendor params
7354 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7355 */
7356#define PARAM_TOTAL_CMD_EVENT_WAKE \
7357 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7358#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7359 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7360#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7361 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7362#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7363 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7364#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7365 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7366#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7367 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7368#define PARAM_TOTAL_RX_DATA_WAKE \
7369 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7370#define PARAM_RX_UNICAST_CNT \
7371 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7372#define PARAM_RX_MULTICAST_CNT \
7373 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7374#define PARAM_RX_BROADCAST_CNT \
7375 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7376#define PARAM_ICMP_PKT \
7377 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7378#define PARAM_ICMP6_PKT \
7379 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7380#define PARAM_ICMP6_RA \
7381 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7382#define PARAM_ICMP6_NA \
7383 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7384#define PARAM_ICMP6_NS \
7385 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7386#define PARAM_ICMP4_RX_MULTICAST_CNT \
7387 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7388#define PARAM_ICMP6_RX_MULTICAST_CNT \
7389 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7390#define PARAM_OTHER_RX_MULTICAST_CNT \
7391 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
7392
7393
7394/**
7395 * hdd_send_wakelock_stats() - API to send wakelock stats
7396 * @ctx: context to be passed to callback
7397 * @data: data passed to callback
7398 *
7399 * This function is used to send wake lock stats to HAL layer
7400 *
7401 * Return: 0 on success, error number otherwise.
7402 */
7403static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7404 const struct sir_wake_lock_stats *data)
7405{
7406 struct sk_buff *skb;
7407 uint32_t nl_buf_len;
7408 uint32_t total_rx_data_wake, rx_multicast_cnt;
7409 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307410 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307411
7412 ENTER();
7413
7414 nl_buf_len = NLMSG_HDRLEN;
7415 nl_buf_len +=
7416 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7417 (NLMSG_HDRLEN + sizeof(uint32_t));
7418
7419 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7420
7421 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007422 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307423 return -ENOMEM;
7424 }
7425
Jeff Johnson64943bd2016-08-23 13:14:06 -07007426 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307427 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007428 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307429 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007430 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307431 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007432 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307433 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007434 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307435 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007436 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307437 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007438 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307439 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007440 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7441 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307442 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307443
7444 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307445 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307446
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307447 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307448 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307449
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307450 rx_multicast_cnt =
7451 data->wow_ipv4_mcast_wake_up_count +
7452 ipv6_rx_multicast_addr_cnt;
7453
7454 total_rx_data_wake =
7455 data->wow_ucast_wake_up_count +
7456 data->wow_bcast_wake_up_count +
7457 rx_multicast_cnt;
7458
7459 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7460 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7461 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7462 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7463 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7464 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7465 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7466 total_rx_data_wake) ||
7467 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7468 data->wow_ucast_wake_up_count) ||
7469 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7470 rx_multicast_cnt) ||
7471 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7472 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307473 nla_put_u32(skb, PARAM_ICMP_PKT,
7474 data->wow_icmpv4_count) ||
7475 nla_put_u32(skb, PARAM_ICMP6_PKT,
7476 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307477 nla_put_u32(skb, PARAM_ICMP6_RA,
7478 data->wow_ipv6_mcast_ra_stats) ||
7479 nla_put_u32(skb, PARAM_ICMP6_NA,
7480 data->wow_ipv6_mcast_na_stats) ||
7481 nla_put_u32(skb, PARAM_ICMP6_NS,
7482 data->wow_ipv6_mcast_ns_stats) ||
7483 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7484 data->wow_ipv4_mcast_wake_up_count) ||
7485 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7486 ipv6_rx_multicast_addr_cnt) ||
7487 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007488 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307489 goto nla_put_failure;
7490 }
7491
7492 cfg80211_vendor_cmd_reply(skb);
7493
7494 EXIT();
7495 return 0;
7496
7497nla_put_failure:
7498 kfree_skb(skb);
7499 return -EINVAL;
7500}
7501
7502/**
7503 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7504 * @wiphy: wiphy pointer
7505 * @wdev: pointer to struct wireless_dev
7506 * @data: pointer to incoming NL vendor data
7507 * @data_len: length of @data
7508 *
7509 * This function parses the incoming NL vendor command data attributes and
7510 * invokes the SME Api and blocks on a completion variable.
7511 * WMA copies required data and invokes callback
7512 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7513 *
7514 * Return: 0 on success; error number otherwise.
7515 */
7516static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7517 struct wireless_dev *wdev,
7518 const void *data,
7519 int data_len)
7520{
7521 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7522 int status, ret;
7523 struct sir_wake_lock_stats wake_lock_stats;
7524 QDF_STATUS qdf_status;
7525
7526 ENTER();
7527
7528 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007529 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307530 return -EINVAL;
7531 }
7532
7533 status = wlan_hdd_validate_context(hdd_ctx);
7534 if (0 != status)
7535 return -EINVAL;
7536
7537 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7538 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007539 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307540 return -EINVAL;
7541 }
7542
7543 ret = hdd_send_wakelock_stats(hdd_ctx,
7544 &wake_lock_stats);
7545 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007546 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307547
7548 EXIT();
7549 return ret;
7550}
7551
7552/**
7553 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7554 * @wiphy: wiphy pointer
7555 * @wdev: pointer to struct wireless_dev
7556 * @data: pointer to incoming NL vendor data
7557 * @data_len: length of @data
7558 *
7559 * This function parses the incoming NL vendor command data attributes and
7560 * invokes the SME Api and blocks on a completion variable.
7561 * WMA copies required data and invokes callback
7562 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7563 *
7564 * Return: 0 on success; error number otherwise.
7565 */
7566static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7567 struct wireless_dev *wdev,
7568 const void *data, int data_len)
7569{
7570 int ret;
7571
7572 cds_ssr_protect(__func__);
7573 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7574 data_len);
7575 cds_ssr_protect(__func__);
7576
7577 return ret;
7578}
7579
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307580/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307581 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7582 * @wiphy: wiphy structure pointer
7583 * @wdev: Wireless device structure pointer
7584 * @data: Pointer to the data received
7585 * @data_len: Length of @data
7586 *
7587 * This function reads wmi max bus size and fill in the skb with
7588 * NL attributes and send up the NL event.
7589 * Return: 0 on success; errno on failure
7590 */
7591static int
7592__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7593 struct wireless_dev *wdev,
7594 const void *data, int data_len)
7595{
7596 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7597 int ret_val;
7598 struct sk_buff *skb;
7599 uint32_t nl_buf_len;
7600
7601 ENTER();
7602
7603 ret_val = wlan_hdd_validate_context(hdd_ctx);
7604 if (ret_val)
7605 return ret_val;
7606
7607 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7608 hdd_err("Command not allowed in FTM mode");
7609 return -EINVAL;
7610 }
7611
7612 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7613
7614 nl_buf_len = NLMSG_HDRLEN;
7615 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7616
7617 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7618 if (!skb) {
7619 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7620 return -ENOMEM;
7621 }
7622
7623 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7624 hdd_ctx->wmi_max_len)) {
7625 hdd_err("nla put failure");
7626 goto nla_put_failure;
7627 }
7628
7629 cfg80211_vendor_cmd_reply(skb);
7630
7631 EXIT();
7632
7633 return 0;
7634
7635nla_put_failure:
7636 kfree_skb(skb);
7637 return -EINVAL;
7638}
7639
7640/**
7641 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7642 * @wiphy: wiphy structure pointer
7643 * @wdev: Wireless device structure pointer
7644 * @data: Pointer to the data received
7645 * @data_len: Length of @data
7646 *
7647 * Return: 0 on success; errno on failure
7648 */
7649static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7650 struct wireless_dev *wdev,
7651 const void *data, int data_len)
7652{
7653 int ret;
7654
7655 cds_ssr_protect(__func__);
7656 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7657 cds_ssr_unprotect(__func__);
7658
7659 return ret;
7660}
7661
7662/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307663 *__wlan_hdd_cfg80211_setband() - set band
7664 * @wiphy: Pointer to wireless phy
7665 * @wdev: Pointer to wireless device
7666 * @data: Pointer to data
7667 * @data_len: Length of @data
7668 *
7669 * Return: 0 on success, negative errno on failure
7670 */
7671static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7672 struct wireless_dev *wdev,
7673 const void *data, int data_len)
7674{
7675 struct net_device *dev = wdev->netdev;
7676 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7677 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7678 int ret;
7679 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7680 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7681
7682 ENTER();
7683
7684 ret = wlan_hdd_validate_context(hdd_ctx);
7685 if (ret)
7686 return ret;
7687
7688 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7689 hdd_err(FL("Invalid ATTR"));
7690 return -EINVAL;
7691 }
7692
7693 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7694 hdd_err(FL("attr SETBAND_VALUE failed"));
7695 return -EINVAL;
7696 }
7697
7698 ret = hdd_set_band(dev,
7699 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7700
7701 EXIT();
7702 return ret;
7703}
7704
7705/**
7706 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7707 * @wiphy: wiphy structure pointer
7708 * @wdev: Wireless device structure pointer
7709 * @data: Pointer to the data received
7710 * @data_len: Length of @data
7711 *
7712 * Return: 0 on success; errno on failure
7713 */
7714static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7715 struct wireless_dev *wdev,
7716 const void *data, int data_len)
7717{
7718 int ret;
7719
7720 cds_ssr_protect(__func__);
7721 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7722 cds_ssr_unprotect(__func__);
7723
7724 return ret;
7725}
7726
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307727static const struct
7728nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7729 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7730 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7731 .len = QDF_MAC_ADDR_SIZE},
7732};
7733
7734/**
7735 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7736 * @wiphy: Pointer to wireless phy
7737 * @wdev: Pointer to wireless device
7738 * @data: Pointer to data
7739 * @data_len: Length of @data
7740 *
7741 * This function is used to enable/disable roaming using vendor commands
7742 *
7743 * Return: 0 on success, negative errno on failure
7744 */
7745static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7746 struct wireless_dev *wdev,
7747 const void *data, int data_len)
7748{
7749 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7750 struct net_device *dev = wdev->netdev;
7751 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7752 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7753 uint32_t is_fast_roam_enabled;
7754 int ret;
7755
7756 ENTER_DEV(dev);
7757
7758 ret = wlan_hdd_validate_context(hdd_ctx);
7759 if (0 != ret)
7760 return ret;
7761
7762 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7763 hdd_err("Command not allowed in FTM mode");
7764 return -EINVAL;
7765 }
7766
7767 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
7768 qca_wlan_vendor_attr);
7769 if (ret) {
7770 hdd_err("Invalid ATTR");
7771 return -EINVAL;
7772 }
7773
7774 /* Parse and fetch Enable flag */
7775 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
7776 hdd_err("attr enable failed");
7777 return -EINVAL;
7778 }
7779
7780 is_fast_roam_enabled = nla_get_u32(
7781 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
7782 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
7783
7784 /* Update roaming */
7785 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
7786 is_fast_roam_enabled);
7787 if (ret)
7788 hdd_err("sme_config_fast_roaming failed");
7789 EXIT();
7790 return ret;
7791}
7792
7793/**
7794 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7795 * @wiphy: Pointer to wireless phy
7796 * @wdev: Pointer to wireless device
7797 * @data: Pointer to data
7798 * @data_len: Length of @data
7799 *
7800 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
7801 *
7802 * Return: 0 on success, negative errno on failure
7803 */
7804static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7805 struct wireless_dev *wdev,
7806 const void *data, int data_len)
7807{
7808 int ret;
7809
7810 cds_ssr_protect(__func__);
7811 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
7812 cds_ssr_unprotect(__func__);
7813
7814 return ret;
7815}
7816
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007817const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
7818 {
7819 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7820 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
7821 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05307822 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007823 .doit = is_driver_dfs_capable
7824 },
7825
7826#ifdef WLAN_FEATURE_NAN
7827 {
7828 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7829 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
7830 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7831 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7832 .doit = wlan_hdd_cfg80211_nan_request
7833 },
7834#endif
7835
7836#ifdef WLAN_FEATURE_STATS_EXT
7837 {
7838 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7839 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
7840 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7841 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7842 .doit = wlan_hdd_cfg80211_stats_ext_request
7843 },
7844#endif
7845#ifdef FEATURE_WLAN_EXTSCAN
7846 {
7847 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7848 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
7849 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7850 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7851 .doit = wlan_hdd_cfg80211_extscan_start
7852 },
7853 {
7854 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7855 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
7856 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7857 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7858 .doit = wlan_hdd_cfg80211_extscan_stop
7859 },
7860 {
7861 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7862 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
7863 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7864 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
7865 },
7866 {
7867 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7868 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
7869 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7870 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7871 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
7872 },
7873 {
7874 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7875 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
7876 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7877 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7878 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
7879 },
7880 {
7881 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7882 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
7883 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7884 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7885 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
7886 },
7887 {
7888 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7889 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
7890 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7891 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7892 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
7893 },
7894 {
7895 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7896 .info.subcmd =
7897 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
7898 .flags =
7899 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7900 WIPHY_VENDOR_CMD_NEED_RUNNING,
7901 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
7902 },
7903 {
7904 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7905 .info.subcmd =
7906 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
7907 .flags =
7908 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7909 WIPHY_VENDOR_CMD_NEED_RUNNING,
7910 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
7911 },
7912 {
7913 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7914 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
7915 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7916 WIPHY_VENDOR_CMD_NEED_NETDEV |
7917 WIPHY_VENDOR_CMD_NEED_RUNNING,
7918 .doit = wlan_hdd_cfg80211_set_epno_list
7919 },
7920#endif /* FEATURE_WLAN_EXTSCAN */
7921
7922#ifdef WLAN_FEATURE_LINK_LAYER_STATS
7923 {
7924 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7925 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
7926 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7927 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7928 .doit = wlan_hdd_cfg80211_ll_stats_clear
7929 },
7930
7931 {
7932 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7933 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
7934 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7935 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7936 .doit = wlan_hdd_cfg80211_ll_stats_set
7937 },
7938
7939 {
7940 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7941 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
7942 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7943 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7944 .doit = wlan_hdd_cfg80211_ll_stats_get
7945 },
7946#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
7947#ifdef FEATURE_WLAN_TDLS
7948 {
7949 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7950 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
7951 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7952 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7953 .doit = wlan_hdd_cfg80211_exttdls_enable
7954 },
7955 {
7956 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7957 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
7958 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7959 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7960 .doit = wlan_hdd_cfg80211_exttdls_disable
7961 },
7962 {
7963 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7964 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
7965 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7966 .doit = wlan_hdd_cfg80211_exttdls_get_status
7967 },
7968#endif
7969 {
7970 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7971 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
7972 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7973 .doit = wlan_hdd_cfg80211_get_supported_features
7974 },
7975 {
7976 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7977 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
7978 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7979 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
7980 },
7981 {
7982 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7983 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
7984 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05307985 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007986 },
7987 {
7988 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7989 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
7990 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7991 WIPHY_VENDOR_CMD_NEED_NETDEV,
7992 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
7993 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07007994 {
7995 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7996 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
7997 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7998 WIPHY_VENDOR_CMD_NEED_NETDEV,
7999 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8000 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008001 {
8002 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308003 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8004 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8005 WIPHY_VENDOR_CMD_NEED_NETDEV |
8006 WIPHY_VENDOR_CMD_NEED_RUNNING,
8007 .doit = hdd_cfg80211_get_station_cmd
8008 },
8009 {
8010 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008011 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8012 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8013 WIPHY_VENDOR_CMD_NEED_NETDEV |
8014 WIPHY_VENDOR_CMD_NEED_RUNNING,
8015 .doit = wlan_hdd_cfg80211_do_acs
8016 },
8017
8018 {
8019 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8020 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8021 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8022 WIPHY_VENDOR_CMD_NEED_NETDEV,
8023 .doit = wlan_hdd_cfg80211_get_features
8024 },
8025#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8026 {
8027 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8028 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8029 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8030 WIPHY_VENDOR_CMD_NEED_NETDEV |
8031 WIPHY_VENDOR_CMD_NEED_RUNNING,
8032 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8033 },
8034#endif
8035#ifdef FEATURE_WLAN_EXTSCAN
8036 {
8037 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8038 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8039 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8040 WIPHY_VENDOR_CMD_NEED_NETDEV |
8041 WIPHY_VENDOR_CMD_NEED_RUNNING,
8042 .doit = wlan_hdd_cfg80211_set_passpoint_list
8043 },
8044 {
8045 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8046 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8047 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8048 WIPHY_VENDOR_CMD_NEED_NETDEV |
8049 WIPHY_VENDOR_CMD_NEED_RUNNING,
8050 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8051 },
8052 {
8053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8055 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8056 WIPHY_VENDOR_CMD_NEED_NETDEV |
8057 WIPHY_VENDOR_CMD_NEED_RUNNING,
8058 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8059 },
8060 {
8061 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8062 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8063 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8064 WIPHY_VENDOR_CMD_NEED_NETDEV |
8065 WIPHY_VENDOR_CMD_NEED_RUNNING,
8066 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8067 },
8068#endif /* FEATURE_WLAN_EXTSCAN */
8069 {
8070 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8071 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8072 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8073 WIPHY_VENDOR_CMD_NEED_NETDEV,
8074 .doit = wlan_hdd_cfg80211_get_wifi_info
8075 },
8076 {
8077 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8078 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8079 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8080 WIPHY_VENDOR_CMD_NEED_NETDEV |
8081 WIPHY_VENDOR_CMD_NEED_RUNNING,
8082 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8083 },
8084 {
8085 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8086 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8087 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8088 WIPHY_VENDOR_CMD_NEED_NETDEV,
8089 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8090 },
8091 {
8092 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8093 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8094 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8095 WIPHY_VENDOR_CMD_NEED_NETDEV,
8096 .doit = wlan_hdd_cfg80211_wifi_logger_start
8097 },
8098 {
8099 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8100 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8101 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8102 WIPHY_VENDOR_CMD_NEED_NETDEV,
8103 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8104 },
8105 {
8106 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8107 .info.subcmd =
8108 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8109 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8110 WIPHY_VENDOR_CMD_NEED_NETDEV |
8111 WIPHY_VENDOR_CMD_NEED_RUNNING,
8112 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8113 },
8114 {
8115 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8116 .info.subcmd =
8117 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8118 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8119 WIPHY_VENDOR_CMD_NEED_NETDEV |
8120 WIPHY_VENDOR_CMD_NEED_RUNNING,
8121 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8122 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008123#ifdef WLAN_FEATURE_TSF
8124 {
8125 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8126 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8127 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8128 WIPHY_VENDOR_CMD_NEED_NETDEV |
8129 WIPHY_VENDOR_CMD_NEED_RUNNING,
8130 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8131 },
8132#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008133#ifdef FEATURE_WLAN_TDLS
8134 {
8135 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8136 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8137 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8138 WIPHY_VENDOR_CMD_NEED_NETDEV |
8139 WIPHY_VENDOR_CMD_NEED_RUNNING,
8140 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8141 },
8142#endif
8143#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8144 {
8145 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8146 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8147 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8148 WIPHY_VENDOR_CMD_NEED_NETDEV |
8149 WIPHY_VENDOR_CMD_NEED_RUNNING,
8150 .doit = wlan_hdd_cfg80211_offloaded_packets
8151 },
8152#endif
8153 {
8154 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8155 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8156 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8157 WIPHY_VENDOR_CMD_NEED_NETDEV |
8158 WIPHY_VENDOR_CMD_NEED_RUNNING,
8159 .doit = wlan_hdd_cfg80211_monitor_rssi
8160 },
8161 {
8162 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308163 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8164 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8165 WIPHY_VENDOR_CMD_NEED_NETDEV |
8166 WIPHY_VENDOR_CMD_NEED_RUNNING,
8167 .doit = wlan_hdd_cfg80211_set_ns_offload
8168 },
8169 {
8170 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008171 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8172 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8173 WIPHY_VENDOR_CMD_NEED_NETDEV |
8174 WIPHY_VENDOR_CMD_NEED_RUNNING,
8175 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8176 },
8177#ifdef WLAN_FEATURE_MEMDUMP
8178 {
8179 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8180 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8181 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8182 WIPHY_VENDOR_CMD_NEED_NETDEV |
8183 WIPHY_VENDOR_CMD_NEED_RUNNING,
8184 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8185 },
8186#endif /* WLAN_FEATURE_MEMDUMP */
8187 {
8188 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8189 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8190 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8191 WIPHY_VENDOR_CMD_NEED_NETDEV |
8192 WIPHY_VENDOR_CMD_NEED_RUNNING,
8193 .doit = wlan_hdd_cfg80211_vendor_scan
8194 },
8195
8196 /* OCB commands */
8197 {
8198 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8199 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8200 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8201 WIPHY_VENDOR_CMD_NEED_NETDEV |
8202 WIPHY_VENDOR_CMD_NEED_RUNNING,
8203 .doit = wlan_hdd_cfg80211_ocb_set_config
8204 },
8205 {
8206 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8207 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8208 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8209 WIPHY_VENDOR_CMD_NEED_NETDEV |
8210 WIPHY_VENDOR_CMD_NEED_RUNNING,
8211 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8212 },
8213 {
8214 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8215 .info.subcmd =
8216 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8217 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8218 WIPHY_VENDOR_CMD_NEED_NETDEV |
8219 WIPHY_VENDOR_CMD_NEED_RUNNING,
8220 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8221 },
8222 {
8223 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8224 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8225 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8226 WIPHY_VENDOR_CMD_NEED_NETDEV |
8227 WIPHY_VENDOR_CMD_NEED_RUNNING,
8228 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8229 },
8230 {
8231 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8232 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8233 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8234 WIPHY_VENDOR_CMD_NEED_NETDEV |
8235 WIPHY_VENDOR_CMD_NEED_RUNNING,
8236 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8237 },
8238 {
8239 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8240 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8241 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8242 WIPHY_VENDOR_CMD_NEED_NETDEV |
8243 WIPHY_VENDOR_CMD_NEED_RUNNING,
8244 .doit = wlan_hdd_cfg80211_dcc_get_stats
8245 },
8246 {
8247 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8248 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8249 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8250 WIPHY_VENDOR_CMD_NEED_NETDEV |
8251 WIPHY_VENDOR_CMD_NEED_RUNNING,
8252 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8253 },
8254 {
8255 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8256 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8257 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8258 WIPHY_VENDOR_CMD_NEED_NETDEV |
8259 WIPHY_VENDOR_CMD_NEED_RUNNING,
8260 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8261 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308262 {
8263 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8264 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8265 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8266 WIPHY_VENDOR_CMD_NEED_NETDEV |
8267 WIPHY_VENDOR_CMD_NEED_RUNNING,
8268 .doit = wlan_hdd_cfg80211_get_link_properties
8269 },
Peng Xu278d0122015-09-24 16:34:17 -07008270 {
Peng Xud2220962016-07-11 17:59:17 -07008271 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008272 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8273 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8274 WIPHY_VENDOR_CMD_NEED_NETDEV |
8275 WIPHY_VENDOR_CMD_NEED_RUNNING,
8276 .doit = wlan_hdd_cfg80211_set_ota_test
8277 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008278#ifdef FEATURE_LFR_SUBNET_DETECTION
8279 {
8280 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8281 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8282 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8283 WIPHY_VENDOR_CMD_NEED_NETDEV |
8284 WIPHY_VENDOR_CMD_NEED_RUNNING,
8285 .doit = wlan_hdd_cfg80211_set_gateway_params
8286 },
8287#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008288 {
Peng Xud2220962016-07-11 17:59:17 -07008289 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008290 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8291 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8292 WIPHY_VENDOR_CMD_NEED_NETDEV |
8293 WIPHY_VENDOR_CMD_NEED_RUNNING,
8294 .doit = wlan_hdd_cfg80211_txpower_scale
8295 },
8296 {
8297 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8298 .info.subcmd =
8299 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8300 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8301 WIPHY_VENDOR_CMD_NEED_NETDEV |
8302 WIPHY_VENDOR_CMD_NEED_RUNNING,
8303 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8304 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308305 {
8306 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8307 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8308 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8309 WIPHY_VENDOR_CMD_NEED_NETDEV |
8310 WIPHY_VENDOR_CMD_NEED_RUNNING,
8311 .doit = wlan_hdd_cfg80211_bpf_offload
8312 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308313 {
8314 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308315 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8316 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8317 WIPHY_VENDOR_CMD_NEED_NETDEV |
8318 WIPHY_VENDOR_CMD_NEED_RUNNING,
8319 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8320 },
8321 {
8322 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308323 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8324 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8325 WIPHY_VENDOR_CMD_NEED_NETDEV |
8326 WIPHY_VENDOR_CMD_NEED_RUNNING,
8327 .doit = wlan_hdd_cfg80211_sta_roam_policy
8328 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308329#ifdef FEATURE_WLAN_CH_AVOID
8330 {
8331 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8332 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8333 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8334 WIPHY_VENDOR_CMD_NEED_NETDEV |
8335 WIPHY_VENDOR_CMD_NEED_RUNNING,
8336 .doit = wlan_hdd_cfg80211_avoid_freq
8337 },
8338#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308339 {
8340 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308341 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8342 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8343 WIPHY_VENDOR_CMD_NEED_NETDEV |
8344 WIPHY_VENDOR_CMD_NEED_RUNNING,
8345 .doit = wlan_hdd_cfg80211_sap_configuration_set
8346 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008347 {
Peng Xu4225c152016-07-14 21:18:14 -07008348 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008349 .info.subcmd =
8350 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8351 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8352 WIPHY_VENDOR_CMD_NEED_NETDEV |
8353 WIPHY_VENDOR_CMD_NEED_RUNNING,
8354 .doit = wlan_hdd_cfg80211_p2p_lo_start
8355 },
8356 {
8357 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8358 .info.subcmd =
8359 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8360 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8361 WIPHY_VENDOR_CMD_NEED_NETDEV |
8362 WIPHY_VENDOR_CMD_NEED_RUNNING,
8363 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8364 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308365 {
8366 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8367 .info.subcmd =
8368 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8369 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8370 WIPHY_VENDOR_CMD_NEED_NETDEV |
8371 WIPHY_VENDOR_CMD_NEED_RUNNING,
8372 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8373 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008374#ifdef WLAN_FEATURE_NAN_DATAPATH
8375 {
8376 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8377 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8378 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8379 WIPHY_VENDOR_CMD_NEED_NETDEV |
8380 WIPHY_VENDOR_CMD_NEED_RUNNING,
8381 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8382 },
8383#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308384 {
8385 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8386 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8387 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8388 WIPHY_VENDOR_CMD_NEED_NETDEV |
8389 WIPHY_VENDOR_CMD_NEED_RUNNING,
8390 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8391 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308392 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308393 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8394 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8395 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8396 WIPHY_VENDOR_CMD_NEED_NETDEV |
8397 WIPHY_VENDOR_CMD_NEED_RUNNING,
8398 .doit = wlan_hdd_cfg80211_get_bus_size
8399 },
8400 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308401 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8402 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8403 WIPHY_VENDOR_CMD_NEED_NETDEV |
8404 WIPHY_VENDOR_CMD_NEED_RUNNING,
8405 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308406 },
8407 {
8408 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8409 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8410 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8411 WIPHY_VENDOR_CMD_NEED_NETDEV |
8412 WIPHY_VENDOR_CMD_NEED_RUNNING,
8413 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308414 },
8415#ifdef WLAN_FEATURE_DISA
8416 {
8417 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8418 .info.subcmd =
8419 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8420 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8421 WIPHY_VENDOR_CMD_NEED_NETDEV |
8422 WIPHY_VENDOR_CMD_NEED_RUNNING,
8423 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8424 },
8425#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008426};
8427
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008428/**
8429 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8430 * @priv_size: Size of the hdd context.
8431 *
8432 * Allocate wiphy context and hdd context.
8433 *
8434 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008435 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008436hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008437{
8438 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008439 hdd_context_t *hdd_ctx;
8440
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008441 ENTER();
8442
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008443 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8444
8445 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008446 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008447 return NULL;
8448 }
8449
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008450 hdd_ctx = wiphy_priv(wiphy);
8451
8452 hdd_ctx->wiphy = wiphy;
8453
8454 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008455}
8456
8457/*
8458 * FUNCTION: wlan_hdd_cfg80211_update_band
8459 * This function is called from the supplicant through a
8460 * private ioctl to change the band value
8461 */
8462int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8463{
8464 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008465 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008466
8467 ENTER();
8468
8469 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8470
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008471 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008472 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008473
8474 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8475 struct ieee80211_supported_band *band = wiphy->bands[i];
8476
8477 channelEnabledState =
8478 cds_get_channel_state(band->channels[j].
8479 hw_value);
8480
8481 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
8482 /* 5G only */
8483#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8484 /* Enable Social channels for P2P */
8485 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8486 (band->channels[j].center_freq)
8487 && CHANNEL_STATE_ENABLE ==
8488 channelEnabledState)
8489 band->channels[j].flags &=
8490 ~IEEE80211_CHAN_DISABLED;
8491 else
8492#endif
8493 band->channels[j].flags |=
8494 IEEE80211_CHAN_DISABLED;
8495 continue;
8496 } else if (IEEE80211_BAND_5GHZ == i &&
8497 eCSR_BAND_24 == eBand) {
8498 /* 2G only */
8499 band->channels[j].flags |=
8500 IEEE80211_CHAN_DISABLED;
8501 continue;
8502 }
8503
Amar Singhal6842e8f2016-02-23 16:30:32 -08008504 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008505 band->channels[j].flags &=
8506 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008507 }
8508 }
8509 return 0;
8510}
8511
8512/*
8513 * FUNCTION: wlan_hdd_cfg80211_init
8514 * This function is called by hdd_wlan_startup()
8515 * during initialization.
8516 * This function is used to initialize and register wiphy structure.
8517 */
8518int wlan_hdd_cfg80211_init(struct device *dev,
8519 struct wiphy *wiphy, struct hdd_config *pCfg)
8520{
8521 int i, j;
8522 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8523
8524 ENTER();
8525
8526 /* Now bind the underlying wlan device with wiphy */
8527 set_wiphy_dev(wiphy, dev);
8528
8529 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8530
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008531#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8532 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008533 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008534#else
8535 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008536 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008537#endif
8538
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008539 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8540 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8541 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8542#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8543 | WIPHY_FLAG_4ADDR_STATION
8544#endif
8545 | WIPHY_FLAG_OFFCHAN_TX;
8546
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008547#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8548 wiphy->wowlan = &wowlan_support_cfg80211_init;
8549#else
8550 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8551 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8552 wiphy->wowlan.pattern_min_len = 1;
8553 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8554#endif
8555
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008556 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008557#ifdef FEATURE_WLAN_ESE
8558 || pCfg->isEseIniFeatureEnabled
8559#endif
8560 ) {
8561 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8562 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008563#ifdef FEATURE_WLAN_TDLS
8564 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8565 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8566#endif
8567
8568 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8569
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008570#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8571 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8572#endif
8573
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008574#ifdef FEATURE_WLAN_SCAN_PNO
8575 if (pCfg->configPNOScanSupport) {
8576 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8577 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8578 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8579 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008580#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8581 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8582#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008583 }
8584#endif /*FEATURE_WLAN_SCAN_PNO */
8585
8586#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308587 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008588#endif
8589
8590 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8591 driver can still register regulatory callback and
8592 it will get regulatory settings in wiphy->band[], but
8593 driver need to determine what to do with both
8594 regulatory settings */
8595
8596 wiphy->reg_notifier = hdd_reg_notifier;
8597
8598#if defined QCA_WIFI_FTM
8599}
8600#endif
8601
8602 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8603
8604 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8605
8606 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8607
Arun Khandavallifae92942016-08-01 13:31:08 +05308608 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8609 | BIT(NL80211_IFTYPE_ADHOC)
8610 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8611 | BIT(NL80211_IFTYPE_P2P_GO)
8612 | BIT(NL80211_IFTYPE_AP)
8613 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008614
Arun Khandavallifae92942016-08-01 13:31:08 +05308615 if (pCfg->advertiseConcurrentOperation) {
8616 if (pCfg->enableMCC) {
8617 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008618
Arun Khandavallifae92942016-08-01 13:31:08 +05308619 for (i = 0;
8620 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8621 i++) {
8622 if (!pCfg->allowMCCGODiffBI)
8623 wlan_hdd_iface_combination[i].
8624 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008625 }
8626 }
8627 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308628 ARRAY_SIZE(wlan_hdd_iface_combination);
8629 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008630 }
8631
8632 /* Before registering we need to update the ht capabilitied based
8633 * on ini values*/
8634 if (!pCfg->ShortGI20MhzEnable) {
8635 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8636 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008637 }
8638
8639 if (!pCfg->ShortGI40MhzEnable) {
8640 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8641 }
8642
8643 if (!pCfg->nChannelBondingMode5GHz) {
8644 wlan_hdd_band_5_ghz.ht_cap.cap &=
8645 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8646 }
8647
Abhishek Singhf512bf32016-05-04 16:47:46 +05308648 /*
8649 * In case of static linked driver at the time of driver unload,
8650 * module exit doesn't happens. Module cleanup helps in cleaning
8651 * of static memory.
8652 * If driver load happens statically, at the time of driver unload,
8653 * wiphy flags don't get reset because of static memory.
8654 * It's better not to store channel in static memory.
8655 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008656 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308657 wiphy->bands[IEEE80211_BAND_2GHZ]->channels =
8658 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
8659 if (wiphy->bands[IEEE80211_BAND_2GHZ]->channels == NULL) {
8660 hdd_err("Not enough memory to allocate channels");
8661 return -ENOMEM;
8662 }
8663 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_2GHZ]->channels,
8664 &hdd_channels_2_4_ghz[0],
8665 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308666 if ((hdd_is_5g_supported(pHddCtx)) &&
8667 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8668 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8669 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8670 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008671 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308672 wiphy->bands[IEEE80211_BAND_5GHZ]->channels =
8673 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
8674 if (wiphy->bands[IEEE80211_BAND_5GHZ]->channels == NULL) {
8675 hdd_err("Not enough memory to allocate channels");
8676 qdf_mem_free(wiphy->
8677 bands[IEEE80211_BAND_2GHZ]->channels);
8678 wiphy->bands[IEEE80211_BAND_2GHZ]->channels = NULL;
8679 return -ENOMEM;
8680 }
8681 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_5GHZ]->channels,
8682 &hdd_channels_5_ghz[0],
8683 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008684 }
8685
8686 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8687
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008688 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008689 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008690
8691 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8692 struct ieee80211_supported_band *band = wiphy->bands[i];
8693
8694 if (IEEE80211_BAND_2GHZ == i &&
8695 eCSR_BAND_5G == pCfg->nBandCapability) {
8696 /* 5G only */
8697#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8698 /* Enable social channels for P2P */
8699 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8700 (band->channels[j].center_freq))
8701 band->channels[j].flags &=
8702 ~IEEE80211_CHAN_DISABLED;
8703 else
8704#endif
8705 band->channels[j].flags |=
8706 IEEE80211_CHAN_DISABLED;
8707 continue;
8708 } else if (IEEE80211_BAND_5GHZ == i &&
8709 eCSR_BAND_24 == pCfg->nBandCapability) {
8710 /* 2G only */
8711 band->channels[j].flags |=
8712 IEEE80211_CHAN_DISABLED;
8713 continue;
8714 }
8715 }
8716 }
8717 /*Initialise the supported cipher suite details */
8718 wiphy->cipher_suites = hdd_cipher_suites;
8719 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8720
8721 /*signal strength in mBm (100*dBm) */
8722 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8723 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8724
Anurag Chouhan6d760662016-02-20 16:05:43 +05308725 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008726 wiphy->n_vendor_commands =
8727 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8728 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8729
8730 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8731 wiphy->n_vendor_events =
8732 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8733 }
8734
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008735 if (pCfg->enableDFSMasterCap) {
8736 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8737 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008738
8739 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8740
8741#ifdef QCA_HT_2040_COEX
8742 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8743#endif
8744
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308745 hdd_add_channel_switch_support(&wiphy->flags);
8746
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008747 EXIT();
8748 return 0;
8749}
8750
Abhishek Singhf512bf32016-05-04 16:47:46 +05308751/**
8752 * wlan_hdd_cfg80211_deinit - Deinit cfg80211
8753 * @ wiphy: the wiphy to validate against
8754 *
8755 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308756 * memory allocated in wlan_hdd_cfg80211_init also
8757 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308758 *
8759 * Return: void
8760 */
8761void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8762{
8763 int i;
8764
8765 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8766 if (NULL != wiphy->bands[i] &&
8767 (NULL != wiphy->bands[i]->channels)) {
8768 qdf_mem_free(wiphy->bands[i]->channels);
8769 wiphy->bands[i]->channels = NULL;
8770 }
8771 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308772 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05308773}
8774
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008775/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308776 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008777 * initialization. In wlan_hdd_cfg80211_init, only the
8778 * default values will be initialized. The final initialization
8779 * of all required members can be done here.
8780 */
8781void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
8782{
8783 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8784}
8785
8786/* In this function we are registering wiphy. */
8787int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
8788{
8789 ENTER();
8790 /* Register our wiphy dev with cfg80211 */
8791 if (0 > wiphy_register(wiphy)) {
8792 /* print error */
Jeff Johnson77848112016-06-29 14:52:06 -07008793 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008794 return -EIO;
8795 }
8796
8797 EXIT();
8798 return 0;
8799}
8800
8801/*
8802 HDD function to update wiphy capability based on target offload status.
8803
8804 wlan_hdd_cfg80211_init() does initialization of all wiphy related
8805 capability even before downloading firmware to the target. In discrete
8806 case, host will get know certain offload capability (say sched_scan
8807 caps) only after downloading firmware to the target and target boots up.
8808 This function is used to override setting done in wlan_hdd_cfg80211_init()
8809 based on target capability.
8810 */
8811void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
8812{
8813#ifdef FEATURE_WLAN_SCAN_PNO
8814 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8815 struct hdd_config *pCfg = pHddCtx->config;
8816
8817 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
8818 * control comes here. Here just we need to clear it if firmware doesn't
8819 * have PNO support. */
8820 if (!pCfg->PnoOffload) {
8821 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8822 wiphy->max_sched_scan_ssids = 0;
8823 wiphy->max_match_sets = 0;
8824 wiphy->max_sched_scan_ie_len = 0;
8825 }
8826#endif
8827}
8828
8829/* This function registers for all frame which supplicant is interested in */
8830void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
8831{
8832 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8833 /* Register for all P2P action, public action etc frames */
8834 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8835
8836 ENTER();
8837
Abhishek Singh7996eb72015-12-30 17:24:02 +05308838 /* Register frame indication call back */
8839 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
8840
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05308841 /* Register for p2p ack indication */
8842 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
8843
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008844 /* Right now we are registering these frame when driver is getting
8845 initialized. Once we will move to 2.6.37 kernel, in which we have
8846 frame register ops, we will move this code as a part of that */
8847 /* GAS Initial Request */
8848 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8849 (uint8_t *) GAS_INITIAL_REQ,
8850 GAS_INITIAL_REQ_SIZE);
8851
8852 /* GAS Initial Response */
8853 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8854 (uint8_t *) GAS_INITIAL_RSP,
8855 GAS_INITIAL_RSP_SIZE);
8856
8857 /* GAS Comeback Request */
8858 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8859 (uint8_t *) GAS_COMEBACK_REQ,
8860 GAS_COMEBACK_REQ_SIZE);
8861
8862 /* GAS Comeback Response */
8863 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8864 (uint8_t *) GAS_COMEBACK_RSP,
8865 GAS_COMEBACK_RSP_SIZE);
8866
8867 /* P2P Public Action */
8868 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8869 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
8870 P2P_PUBLIC_ACTION_FRAME_SIZE);
8871
8872 /* P2P Action */
8873 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8874 (uint8_t *) P2P_ACTION_FRAME,
8875 P2P_ACTION_FRAME_SIZE);
8876
8877 /* WNM BSS Transition Request frame */
8878 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8879 (uint8_t *) WNM_BSS_ACTION_FRAME,
8880 WNM_BSS_ACTION_FRAME_SIZE);
8881
8882 /* WNM-Notification */
8883 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
8884 (uint8_t *) WNM_NOTIFICATION_FRAME,
8885 WNM_NOTIFICATION_FRAME_SIZE);
8886}
8887
8888void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
8889{
8890 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8891 /* Register for all P2P action, public action etc frames */
8892 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8893
8894 ENTER();
8895
8896 /* Right now we are registering these frame when driver is getting
8897 initialized. Once we will move to 2.6.37 kernel, in which we have
8898 frame register ops, we will move this code as a part of that */
8899 /* GAS Initial Request */
8900
8901 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8902 (uint8_t *) GAS_INITIAL_REQ,
8903 GAS_INITIAL_REQ_SIZE);
8904
8905 /* GAS Initial Response */
8906 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8907 (uint8_t *) GAS_INITIAL_RSP,
8908 GAS_INITIAL_RSP_SIZE);
8909
8910 /* GAS Comeback Request */
8911 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8912 (uint8_t *) GAS_COMEBACK_REQ,
8913 GAS_COMEBACK_REQ_SIZE);
8914
8915 /* GAS Comeback Response */
8916 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8917 (uint8_t *) GAS_COMEBACK_RSP,
8918 GAS_COMEBACK_RSP_SIZE);
8919
8920 /* P2P Public Action */
8921 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8922 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
8923 P2P_PUBLIC_ACTION_FRAME_SIZE);
8924
8925 /* P2P Action */
8926 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8927 (uint8_t *) P2P_ACTION_FRAME,
8928 P2P_ACTION_FRAME_SIZE);
8929
8930 /* WNM-Notification */
8931 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
8932 (uint8_t *) WNM_NOTIFICATION_FRAME,
8933 WNM_NOTIFICATION_FRAME_SIZE);
8934}
8935
8936#ifdef FEATURE_WLAN_WAPI
8937void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
8938 const uint8_t *mac_addr, const uint8_t *key,
8939 int key_Len)
8940{
8941 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8942 tCsrRoamSetKey setKey;
8943 bool isConnected = true;
8944 int status = 0;
8945 uint32_t roamId = 0xFF;
8946 uint8_t *pKeyPtr = NULL;
8947 int n = 0;
8948
Jeff Johnson46b40792016-06-29 14:03:14 -07008949 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008950 hdd_device_mode_to_string(pAdapter->device_mode),
8951 pAdapter->device_mode);
8952
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308953 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008954 setKey.keyId = key_index; /* Store Key ID */
8955 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
8956 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
8957 setKey.paeRole = 0; /* the PAE role */
8958 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05308959 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008960 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308961 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008962 }
8963 setKey.keyLength = key_Len;
8964 pKeyPtr = setKey.Key;
8965 memcpy(pKeyPtr, key, key_Len);
8966
Jeff Johnson46b40792016-06-29 14:03:14 -07008967 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008968 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07008969 hdd_notice("WAPI KEY Data[%d]:%02x ",
8970 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008971
8972 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
8973 if (isConnected) {
8974 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
8975 pAdapter->sessionId, &setKey, &roamId);
8976 }
8977 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07008978 hdd_err("sme_roam_set_key returned ERROR status= %d",
8979 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008980 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
8981 }
8982}
8983#endif /* FEATURE_WLAN_WAPI */
8984
8985uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
8986 uint8_t eid)
8987{
8988 int left = length;
8989 uint8_t *ptr = (uint8_t *)ies_ptr;
8990 uint8_t elem_id, elem_len;
8991
8992 while (left >= 2) {
8993 elem_id = ptr[0];
8994 elem_len = ptr[1];
8995 left -= 2;
8996 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07008997 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008998 eid, elem_len, left);
8999 return NULL;
9000 }
9001 if (elem_id == eid) {
9002 return ptr;
9003 }
9004
9005 left -= elem_len;
9006 ptr += (elem_len + 2);
9007 }
9008 return NULL;
9009}
9010
9011/*
9012 * FUNCTION: wlan_hdd_validate_operation_channel
9013 * called by wlan_hdd_cfg80211_start_bss() and
9014 * wlan_hdd_set_channel()
9015 * This function validates whether given channel is part of valid
9016 * channel list.
9017 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309018QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009019 int channel)
9020{
9021
9022 uint32_t num_ch = 0;
9023 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9024 u32 indx = 0;
9025 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9026 uint8_t fValidChannel = false, count = 0;
9027 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9028
9029 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9030
9031 if (hdd_pConfig_ini->sapAllowAllChannel) {
9032 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009033 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009034 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009035 fValidChannel = true;
9036 break;
9037 }
9038 }
9039 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009040 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309041 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009042 }
9043 } else {
9044 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9045 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009046 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309047 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009048 }
9049 for (indx = 0; indx < num_ch; indx++) {
9050 if (channel == valid_ch[indx]) {
9051 break;
9052 }
9053 }
9054
9055 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009056 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309057 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009058 }
9059 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309060 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009061
9062}
9063
9064#ifdef DHCP_SERVER_OFFLOAD
9065static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9066{
9067 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9068 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9069 uint8_t numEntries = 0;
9070 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9071 uint8_t num;
9072 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309073 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009074 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009075 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009076 return;
9077 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309078 qdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009079 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9080 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9081 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9082 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9083 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9084 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009085 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009086 goto end;
9087 }
9088 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009089 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009090 goto end;
9091 }
9092 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009093 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009094 goto end;
9095 }
9096 for (num = 0; num < numEntries; num++) {
9097 temp = srv_ip[num];
9098 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9099 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309100 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009101 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009102 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009103 goto end;
9104 }
Jeff Johnson77848112016-06-29 14:52:06 -07009105 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009106end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309107 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009108 return;
9109}
9110#endif /* DHCP_SERVER_OFFLOAD */
9111
9112static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9113 struct net_device *dev,
9114 struct bss_parameters *params)
9115{
9116 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9117 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9118 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309119 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009120
9121 ENTER();
9122
Anurag Chouhan6d760662016-02-20 16:05:43 +05309123 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009124 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009125 return -EINVAL;
9126 }
9127
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309128 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009129 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9130 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009131 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009132 hdd_device_mode_to_string(pAdapter->device_mode),
9133 pAdapter->device_mode, params->ap_isolate);
9134
9135 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9136 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309137 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009138 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009139
Krunal Sonib4326f22016-03-10 13:05:51 -08009140 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9141 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009142 return -EOPNOTSUPP;
9143 }
9144
9145 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9146 * want to update this parameter */
9147 if (-1 != params->ap_isolate) {
9148 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9149 !!params->ap_isolate;
9150
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309151 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009152 pAdapter->sessionId,
9153 pAdapter->sessionCtx.
9154 ap.
9155 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309156 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009157 ret = -EINVAL;
9158 }
9159 }
9160
9161 EXIT();
9162 return ret;
9163}
9164
Krunal Soni8c37e322016-02-03 16:08:37 -08009165/**
9166 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9167 * @ndev: pointer to net device provided by supplicant
9168 * @type: type of the interface, upper layer wanted to change
9169 *
9170 * Upper layer provides the new interface mode that needs to be changed
9171 * for given net device
9172 *
9173 * Return: success or failure in terms of integer value
9174 */
9175static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009176 enum nl80211_iftype type)
9177{
Krunal Soni8c37e322016-02-03 16:08:37 -08009178 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9179 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9180 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009181 hdd_wext_state_t *wext;
9182 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309183 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009184
9185 ENTER();
9186
Krunal Soni8c37e322016-02-03 16:08:37 -08009187 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009188 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009189 return 0;
9190 }
9191
9192 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009193 hdd_stop_adapter(hdd_ctx, adapter, true);
9194 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009195 wdev->iftype = type;
9196 /*Check for sub-string p2p to confirm its a p2p interface */
9197 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009198 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009199 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009200 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009201 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009202 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009203 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009204 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009205 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009206 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009207 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009208 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9209 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009210 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9211 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009212 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009213 adapter->scan_info.scanAddIE.length;
9214 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309215 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009216 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9217 wext->roamProfile.phyMode =
9218 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9219 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009220 EXIT();
9221 return status;
9222}
9223
9224static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9225 struct net_device *dev,
9226 struct bss_parameters *params)
9227{
9228 int ret;
9229
9230 cds_ssr_protect(__func__);
9231 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9232 cds_ssr_unprotect(__func__);
9233
9234 return ret;
9235}
9236
9237/* FUNCTION: wlan_hdd_change_country_code_cd
9238 * to wait for contry code completion
9239 */
9240void *wlan_hdd_change_country_code_cb(void *pAdapter)
9241{
9242 hdd_adapter_t *call_back_pAdapter = pAdapter;
9243 complete(&call_back_pAdapter->change_country_code);
9244 return NULL;
9245}
9246
Rajeev Kumar98edb772016-01-19 12:42:19 -08009247/**
9248 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9249 * @wiphy: Pointer to the wiphy structure
9250 * @ndev: Pointer to the net device
9251 * @type: Interface type
9252 * @flags: Flags for change interface
9253 * @params: Pointer to change interface parameters
9254 *
9255 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009256 */
9257static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9258 struct net_device *ndev,
9259 enum nl80211_iftype type,
9260 u32 *flags,
9261 struct vif_params *params)
9262{
9263 struct wireless_dev *wdev;
9264 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9265 hdd_context_t *pHddCtx;
9266 tCsrRoamProfile *pRoamProfile = NULL;
9267 eCsrRoamBssType LastBSSType;
9268 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309269 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009270 int status;
9271
9272 ENTER();
9273
Anurag Chouhan6d760662016-02-20 16:05:43 +05309274 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009275 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009276 return -EINVAL;
9277 }
9278
9279 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9280 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309281 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009282 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009283
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309284 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009285 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9286 pAdapter->sessionId, type));
9287
Jeff Johnson77848112016-06-29 14:52:06 -07009288 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009289 pAdapter->device_mode, type);
9290
Arun Khandavallifae92942016-08-01 13:31:08 +05309291 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9292 if (status) {
9293 hdd_err("Failed to start modules");
9294 return -EINVAL;
9295 }
9296
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009297 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009298 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9299 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009300 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009301 return -EINVAL;
9302 }
9303
9304 pConfig = pHddCtx->config;
9305 wdev = ndev->ieee80211_ptr;
9306
9307 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009308 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009309
9310 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9311
Krunal Sonib4326f22016-03-10 13:05:51 -08009312 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9313 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9314 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9315 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009316 hdd_wext_state_t *pWextState =
9317 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9318
9319 pRoamProfile = &pWextState->roamProfile;
9320 LastBSSType = pRoamProfile->BSSType;
9321
9322 switch (type) {
9323 case NL80211_IFTYPE_STATION:
9324 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009325 case NL80211_IFTYPE_ADHOC:
9326 if (type == NL80211_IFTYPE_ADHOC) {
9327 wlan_hdd_tdls_exit(pAdapter);
9328 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009329 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009330 }
9331 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9332 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309333 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009334 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309335 if (hdd_start_adapter(pAdapter)) {
9336 hdd_err("Failed to start adapter :%d",
9337 pAdapter->device_mode);
9338 return -EINVAL;
9339 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009340 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009341 case NL80211_IFTYPE_AP:
9342 case NL80211_IFTYPE_P2P_GO:
9343 {
Jeff Johnson77848112016-06-29 14:52:06 -07009344 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009345 (type ==
9346 NL80211_IFTYPE_AP) ? "SoftAP" :
9347 "P2pGo");
9348
9349 /* Cancel any remain on channel for GO mode */
9350 if (NL80211_IFTYPE_P2P_GO == type) {
9351 wlan_hdd_cancel_existing_remain_on_channel
9352 (pAdapter);
9353 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009354
Arun Khandavallifae92942016-08-01 13:31:08 +05309355 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009356 /* De-init the adapter */
9357 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9358 memset(&pAdapter->sessionCtx, 0,
9359 sizeof(pAdapter->sessionCtx));
9360 pAdapter->device_mode =
9361 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009362 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9363 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009364
9365 /*
9366 * Fw will take care incase of concurrency
9367 */
9368
Krunal Sonib4326f22016-03-10 13:05:51 -08009369 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009370 && (pConfig->apRandomBssidEnabled)) {
9371 /* To meet Android requirements create a randomized
9372 MAC address of the form 02:1A:11:Fx:xx:xx */
9373 get_random_bytes(&ndev->dev_addr[3], 3);
9374 ndev->dev_addr[0] = 0x02;
9375 ndev->dev_addr[1] = 0x1A;
9376 ndev->dev_addr[2] = 0x11;
9377 ndev->dev_addr[3] |= 0xF0;
9378 memcpy(pAdapter->macAddressCurrent.
9379 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309380 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009381 pr_info("wlan: Generated HotSpot BSSID "
9382 MAC_ADDRESS_STR "\n",
9383 MAC_ADDR_ARRAY(ndev->dev_addr));
9384 }
9385
9386 hdd_set_ap_ops(pAdapter->dev);
9387
Arun Khandavallifae92942016-08-01 13:31:08 +05309388 if (hdd_start_adapter(pAdapter)) {
9389 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009390 return -EINVAL;
9391 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009392 /* Interface type changed update in wiphy structure */
9393 if (wdev) {
9394 wdev->iftype = type;
9395 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009396 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009397 return -EINVAL;
9398 }
9399 goto done;
9400 }
9401
9402 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009403 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009404 type);
9405 return -EOPNOTSUPP;
9406 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009407 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9408 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009409 switch (type) {
9410 case NL80211_IFTYPE_STATION:
9411 case NL80211_IFTYPE_P2P_CLIENT:
9412 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009413 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9414 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309415 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009416 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309417 if (hdd_start_adapter(pAdapter)) {
9418 hdd_err("Failed to start adapter :%d",
9419 pAdapter->device_mode);
9420 return -EINVAL;
9421 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009422 goto done;
9423
9424 case NL80211_IFTYPE_AP:
9425 case NL80211_IFTYPE_P2P_GO:
9426 wdev->iftype = type;
9427 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009428 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009429 goto done;
9430
9431 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009432 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009433 type);
9434 return -EOPNOTSUPP;
9435 }
9436 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009437 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009438 pAdapter->device_mode);
9439 return -EOPNOTSUPP;
9440 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009441done:
9442 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009443 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009444
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009445 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009446
9447 EXIT();
9448 return 0;
9449}
9450
Rajeev Kumar98edb772016-01-19 12:42:19 -08009451/**
9452 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9453 * @wiphy: Pointer to the wiphy structure
9454 * @ndev: Pointer to the net device
9455 * @type: Interface type
9456 * @flags: Flags for change interface
9457 * @params: Pointer to change interface parameters
9458 *
9459 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009460 */
9461static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9462 struct net_device *ndev,
9463 enum nl80211_iftype type,
9464 u32 *flags,
9465 struct vif_params *params)
9466{
9467 int ret;
9468
9469 cds_ssr_protect(__func__);
9470 ret =
9471 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9472 cds_ssr_unprotect(__func__);
9473
9474 return ret;
9475}
9476
9477#ifdef FEATURE_WLAN_TDLS
9478static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9479 int index, uint8_t match)
9480{
9481 int i;
9482 for (i = 0; i < index; i++) {
9483 if (arr[i] == match)
9484 return true;
9485 }
9486 return false;
9487}
9488#endif
9489
9490/**
9491 * __wlan_hdd_change_station() - change station
9492 * @wiphy: Pointer to the wiphy structure
9493 * @dev: Pointer to the net device.
9494 * @mac: bssid
9495 * @params: Pointer to station parameters
9496 *
9497 * Return: 0 for success, error number on failure.
9498 */
9499#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9500static int __wlan_hdd_change_station(struct wiphy *wiphy,
9501 struct net_device *dev,
9502 const uint8_t *mac,
9503 struct station_parameters *params)
9504#else
9505static int __wlan_hdd_change_station(struct wiphy *wiphy,
9506 struct net_device *dev,
9507 uint8_t *mac,
9508 struct station_parameters *params)
9509#endif
9510{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309511 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009512 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9513 hdd_context_t *pHddCtx;
9514 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309515 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009516#ifdef FEATURE_WLAN_TDLS
9517 tCsrStaParams StaParams = { 0 };
9518 uint8_t isBufSta = 0;
9519 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309520 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009521#endif
9522 int ret;
9523
9524 ENTER();
9525
Anurag Chouhan6d760662016-02-20 16:05:43 +05309526 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009527 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009528 return -EINVAL;
9529 }
9530
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309531 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009532 TRACE_CODE_HDD_CHANGE_STATION,
9533 pAdapter->sessionId, params->listen_interval));
9534
9535 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9536 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309537 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009538 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009539
9540 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9541
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309542 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009543
Krunal Sonib4326f22016-03-10 13:05:51 -08009544 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9545 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009546 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9547 status =
9548 hdd_softap_change_sta_state(pAdapter,
9549 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009550 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009551
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309552 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009553 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009554 return -EINVAL;
9555 }
9556 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009557 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9558 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009559#ifdef FEATURE_WLAN_TDLS
9560 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009561
9562 if (cds_is_sub_20_mhz_enabled()) {
9563 hdd_err("TDLS not allowed with sub 20 MHz");
9564 return -EINVAL;
9565 }
9566
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009567 StaParams.capability = params->capability;
9568 StaParams.uapsd_queues = params->uapsd_queues;
9569 StaParams.max_sp = params->max_sp;
9570
9571 /* Convert (first channel , number of channels) tuple to
9572 * the total list of channels. This goes with the assumption
9573 * that if the first channel is < 14, then the next channels
9574 * are an incremental of 1 else an incremental of 4 till the number
9575 * of channels.
9576 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009577 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009578 if (0 != params->supported_channels_len) {
9579 int i = 0, j = 0, k = 0, no_of_channels = 0;
9580 int num_unique_channels;
9581 int next;
9582 for (i = 0;
9583 i < params->supported_channels_len
9584 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9585 int wifi_chan_index;
9586 if (!wlan_hdd_is_duplicate_channel
9587 (StaParams.supported_channels, j,
9588 params->supported_channels[i])) {
9589 StaParams.
9590 supported_channels[j] =
9591 params->
9592 supported_channels[i];
9593 } else {
9594 continue;
9595 }
9596 wifi_chan_index =
9597 ((StaParams.supported_channels[j] <=
9598 HDD_CHANNEL_14) ? 1 : 4);
9599 no_of_channels =
9600 params->supported_channels[i + 1];
9601
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009602 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 -08009603 StaParams.
9604 supported_channels[j],
9605 wifi_chan_index,
9606 no_of_channels);
9607 for (k = 1; k <= no_of_channels &&
9608 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9609 k++) {
9610 next =
9611 StaParams.
9612 supported_channels[j] +
9613 wifi_chan_index;
9614 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9615 StaParams.
9616 supported_channels[j
9617 +
9618 1]
9619 = next;
9620 } else {
9621 continue;
9622 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009623 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009624 j + 1,
9625 StaParams.
9626 supported_channels[j +
9627 1]);
9628 j += 1;
9629 }
9630 }
9631 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009632 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009633 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009634 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009635 StaParams.
9636 supported_channels[i]);
9637 }
9638 if (MAX_CHANNEL < num_unique_channels)
9639 num_unique_channels = MAX_CHANNEL;
9640 StaParams.supported_channels_len =
9641 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009642 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009643 StaParams.supported_channels_len);
9644 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309645 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009646 params->supported_oper_classes,
9647 params->supported_oper_classes_len);
9648 StaParams.supported_oper_classes_len =
9649 params->supported_oper_classes_len;
9650
9651 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309652 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009653 params->ext_capab,
9654 sizeof(StaParams.extn_capability));
9655
9656 if (NULL != params->ht_capa) {
9657 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309658 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009659 sizeof(tSirHTCap));
9660 }
9661
9662 StaParams.supported_rates_len =
9663 params->supported_rates_len;
9664
9665 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9666 * The supported_rates array , for all the structures propogating till Add Sta
9667 * to the firmware has to be modified , if the supplicant (ieee80211) is
9668 * modified to send more rates.
9669 */
9670
9671 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
9672 */
9673 if (StaParams.supported_rates_len >
9674 SIR_MAC_MAX_SUPP_RATES)
9675 StaParams.supported_rates_len =
9676 SIR_MAC_MAX_SUPP_RATES;
9677
9678 if (0 != StaParams.supported_rates_len) {
9679 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309680 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009681 params->supported_rates,
9682 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009683 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009684 StaParams.supported_rates_len);
9685 for (i = 0; i < StaParams.supported_rates_len;
9686 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009687 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009688 StaParams.supported_rates[i]);
9689 }
9690
9691 if (NULL != params->vht_capa) {
9692 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309693 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009694 params->vht_capa,
9695 sizeof(tSirVHTCap));
9696 }
9697
9698 if (0 != params->ext_capab_len) {
9699 /*Define A Macro : TODO Sunil */
9700 if ((1 << 4) & StaParams.extn_capability[3]) {
9701 isBufSta = 1;
9702 }
9703 /* TDLS Channel Switching Support */
9704 if ((1 << 6) & StaParams.extn_capability[3]) {
9705 isOffChannelSupported = 1;
9706 }
9707 }
9708
Nitesh Shah99934ac2016-09-05 15:54:08 +05309709 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +05309710 (params->ht_capa || params->vht_capa ||
9711 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +05309712 is_qos_wmm_sta = true;
9713
9714 hdd_notice("%s: TDLS Peer is QOS capable"
9715 " is_qos_wmm_sta= %d HTcapPresent = %d",
9716 __func__, is_qos_wmm_sta,
9717 StaParams.htcap_present);
9718
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009719 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +05309720 &StaParams,
9721 isBufSta,
9722 isOffChannelSupported,
9723 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309724 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009725 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009726 return -EINVAL;
9727 }
9728
9729 status =
9730 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
9731 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309732 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009733 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009734 return -EINVAL;
9735 }
9736 }
9737#endif
9738 }
9739 EXIT();
9740 return ret;
9741}
9742
9743/**
9744 * wlan_hdd_change_station() - cfg80211 change station handler function
9745 * @wiphy: Pointer to the wiphy structure
9746 * @dev: Pointer to the net device.
9747 * @mac: bssid
9748 * @params: Pointer to station parameters
9749 *
9750 * This is the cfg80211 change station handler function which invokes
9751 * the internal function @__wlan_hdd_change_station with
9752 * SSR protection.
9753 *
9754 * Return: 0 for success, error number on failure.
9755 */
9756#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
9757static int wlan_hdd_change_station(struct wiphy *wiphy,
9758 struct net_device *dev,
9759 const u8 *mac,
9760 struct station_parameters *params)
9761#else
9762static int wlan_hdd_change_station(struct wiphy *wiphy,
9763 struct net_device *dev,
9764 u8 *mac,
9765 struct station_parameters *params)
9766#endif
9767{
9768 int ret;
9769
9770 cds_ssr_protect(__func__);
9771 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
9772 cds_ssr_unprotect(__func__);
9773
9774 return ret;
9775}
9776
9777/*
9778 * FUNCTION: __wlan_hdd_cfg80211_add_key
9779 * This function is used to initialize the key information
9780 */
9781static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
9782 struct net_device *ndev,
9783 u8 key_index, bool pairwise,
9784 const u8 *mac_addr,
9785 struct key_params *params)
9786{
9787 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9788 tCsrRoamSetKey setKey;
9789 int status;
9790 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009791 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309792 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009793 hdd_context_t *pHddCtx;
9794 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9795
9796 ENTER();
9797
Anurag Chouhan6d760662016-02-20 16:05:43 +05309798 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009799 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009800 return -EINVAL;
9801 }
9802
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309803 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009804 TRACE_CODE_HDD_CFG80211_ADD_KEY,
9805 pAdapter->sessionId, params->key_len));
9806 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9807 status = wlan_hdd_validate_context(pHddCtx);
9808
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309809 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009810 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009811
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009812 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009813 hdd_device_mode_to_string(pAdapter->device_mode),
9814 pAdapter->device_mode);
9815
9816 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009817 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009818
9819 return -EINVAL;
9820 }
9821
9822 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009823 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009824
9825 return -EINVAL;
9826 }
9827
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009828 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009829
9830 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309831 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009832 setKey.keyId = key_index;
9833 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309834 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009835
9836 switch (params->cipher) {
9837 case WLAN_CIPHER_SUITE_WEP40:
9838 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9839 break;
9840
9841 case WLAN_CIPHER_SUITE_WEP104:
9842 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
9843 break;
9844
9845 case WLAN_CIPHER_SUITE_TKIP:
9846 {
9847 u8 *pKey = &setKey.Key[0];
9848 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
9849
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309850 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009851
9852 /*Supplicant sends the 32bytes key in this order
9853
9854 |--------------|----------|----------|
9855 | Tk1 |TX-MIC | RX Mic |
9856 |||--------------|----------|----------|
9857 <---16bytes---><--8bytes--><--8bytes-->
9858
9859 */
9860 /*Sme expects the 32 bytes key to be in the below order
9861
9862 |--------------|----------|----------|
9863 | Tk1 |RX-MIC | TX Mic |
9864 |||--------------|----------|----------|
9865 <---16bytes---><--8bytes--><--8bytes-->
9866 */
9867 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309868 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009869
9870 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309871 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009872
9873 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309874 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009875
9876 break;
9877 }
9878
9879 case WLAN_CIPHER_SUITE_CCMP:
9880 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
9881 break;
9882
9883#ifdef FEATURE_WLAN_WAPI
9884 case WLAN_CIPHER_SUITE_SMS4:
9885 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309886 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009887 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
9888 mac_addr, params->key,
9889 params->key_len);
9890 return 0;
9891 }
9892#endif
9893
9894#ifdef FEATURE_WLAN_ESE
9895 case WLAN_CIPHER_SUITE_KRK:
9896 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
9897 break;
9898#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9899 case WLAN_CIPHER_SUITE_BTK:
9900 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
9901 break;
9902#endif
9903#endif
9904
9905#ifdef WLAN_FEATURE_11W
9906 case WLAN_CIPHER_SUITE_AES_CMAC:
9907 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
9908 break;
9909#endif
9910
9911 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009912 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009913 return -EOPNOTSUPP;
9914 }
9915
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009916 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009917
9918 if (!pairwise) {
9919 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009920 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009921 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05309922 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009923 } else {
9924 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009925 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009926 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309927 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009928 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009929 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009930 /* if a key is already installed, block all subsequent ones */
9931 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009932 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009933 return 0;
9934 }
9935
9936 setKey.keyDirection = eSIR_TX_RX;
9937 /*Set the group key */
9938 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9939 pAdapter->sessionId, &setKey, &roamId);
9940
9941 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009942 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009943 return -EINVAL;
9944 }
9945 /*Save the keys here and call sme_roam_set_key for setting
9946 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309947 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009948 &setKey, sizeof(tCsrRoamSetKey));
9949
9950 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
9951 return status;
9952 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009953 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9954 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009955 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9956 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -07009957 status = wlansap_set_key_sta(
9958 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309959 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009960 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009961 __LINE__, status);
9962 }
9963 }
9964
9965 /* Save the key in ap ctx for use on START_BASS and restart */
9966 if (pairwise ||
9967 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
9968 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309969 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009970 sizeof(tCsrRoamSetKey));
9971 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309972 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009973 sizeof(tCsrRoamSetKey));
9974
Krunal Sonib4326f22016-03-10 13:05:51 -08009975 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9976 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009977 hdd_wext_state_t *pWextState =
9978 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9979 hdd_station_ctx_t *pHddStaCtx =
9980 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9981
9982 if (!pairwise) {
9983 /* set group key */
9984 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009985 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009986 __func__, __LINE__);
9987 hdd_perform_roam_set_key_complete(pAdapter);
9988 }
9989 }
9990
9991 pWextState->roamProfile.Keys.KeyLength[key_index] =
9992 (u8) params->key_len;
9993
9994 pWextState->roamProfile.Keys.defaultIndex = key_index;
9995
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309996 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009997 KeyMaterial[key_index][0], params->key,
9998 params->key_len);
9999
10000 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10001
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010002 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010003 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10004 setKey.keyDirection);
10005
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010006 /* The supplicant may attempt to set the PTK once pre-authentication
10007 is done. Save the key in the UMAC and include it in the ADD BSS
10008 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010009 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010010 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010011 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010012 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010013 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010014 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010015 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010016 return -EINVAL;
10017 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010018
10019 /* issue set key request to SME */
10020 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10021 pAdapter->sessionId, &setKey, &roamId);
10022
10023 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010024 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010025 pHddStaCtx->roam_info.roamingState =
10026 HDD_ROAM_STATE_NONE;
10027 return -EINVAL;
10028 }
10029
10030 /* in case of IBSS as there was no information available about WEP keys during
10031 * IBSS join, group key intialized with NULL key, so re-initialize group key
10032 * with correct value*/
10033 if ((eCSR_BSS_TYPE_START_IBSS ==
10034 pWextState->roamProfile.BSSType)
10035 &&
10036 !((IW_AUTH_KEY_MGMT_802_1X ==
10037 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10038 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10039 pHddStaCtx->conn_info.authType)
10040 )
10041 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10042 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10043 )
10044 ) {
10045 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010046 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010047
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010048 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010049 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10050 setKey.keyDirection);
10051
10052 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10053 pAdapter->sessionId, &setKey,
10054 &roamId);
10055
10056 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010057 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010058 pHddStaCtx->roam_info.roamingState =
10059 HDD_ROAM_STATE_NONE;
10060 return -EINVAL;
10061 }
10062 }
10063 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010064 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010065 return 0;
10066}
10067
10068static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10069 struct net_device *ndev,
10070 u8 key_index, bool pairwise,
10071 const u8 *mac_addr,
10072 struct key_params *params)
10073{
10074 int ret;
10075 cds_ssr_protect(__func__);
10076 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10077 mac_addr, params);
10078 cds_ssr_unprotect(__func__);
10079
10080 return ret;
10081}
10082
10083/*
10084 * FUNCTION: __wlan_hdd_cfg80211_get_key
10085 * This function is used to get the key information
10086 */
10087static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10088 struct net_device *ndev,
10089 u8 key_index, bool pairwise,
10090 const u8 *mac_addr, void *cookie,
10091 void (*callback)(void *cookie,
10092 struct key_params *)
10093 )
10094{
10095 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10096 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10097 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10098 struct key_params params;
10099
10100 ENTER();
10101
Anurag Chouhan6d760662016-02-20 16:05:43 +053010102 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010103 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010104 return -EINVAL;
10105 }
10106
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010107 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010108 hdd_device_mode_to_string(pAdapter->device_mode),
10109 pAdapter->device_mode);
10110
10111 memset(&params, 0, sizeof(params));
10112
10113 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010114 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010115 key_index);
10116 return -EINVAL;
10117 }
10118
10119 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10120 case eCSR_ENCRYPT_TYPE_NONE:
10121 params.cipher = IW_AUTH_CIPHER_NONE;
10122 break;
10123
10124 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10125 case eCSR_ENCRYPT_TYPE_WEP40:
10126 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10127 break;
10128
10129 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10130 case eCSR_ENCRYPT_TYPE_WEP104:
10131 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10132 break;
10133
10134 case eCSR_ENCRYPT_TYPE_TKIP:
10135 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10136 break;
10137
10138 case eCSR_ENCRYPT_TYPE_AES:
10139 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10140 break;
10141
10142 default:
10143 params.cipher = IW_AUTH_CIPHER_NONE;
10144 break;
10145 }
10146
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010147 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010148 TRACE_CODE_HDD_CFG80211_GET_KEY,
10149 pAdapter->sessionId, params.cipher));
10150
10151 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10152 params.seq_len = 0;
10153 params.seq = NULL;
10154 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10155 callback(cookie, &params);
10156
10157 EXIT();
10158 return 0;
10159}
10160
10161static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10162 struct net_device *ndev,
10163 u8 key_index, bool pairwise,
10164 const u8 *mac_addr, void *cookie,
10165 void (*callback)(void *cookie,
10166 struct key_params *)
10167 )
10168{
10169 int ret;
10170
10171 cds_ssr_protect(__func__);
10172 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10173 mac_addr, cookie, callback);
10174 cds_ssr_unprotect(__func__);
10175
10176 return ret;
10177}
10178
10179/**
10180 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10181 * @wiphy: wiphy interface context
10182 * @ndev: pointer to net device
10183 * @key_index: Key index used in 802.11 frames
10184 * @unicast: true if it is unicast key
10185 * @multicast: true if it is multicast key
10186 *
10187 * This function is required for cfg80211_ops API.
10188 * It is used to delete the key information
10189 * Underlying hardware implementation does not have API to delete the
10190 * encryption key. It is automatically deleted when the peer is
10191 * removed. Hence this function currently does nothing.
10192 * Future implementation may interprete delete key operation to
10193 * replacing the key with a random junk value, effectively making it
10194 * useless.
10195 *
10196 * Return: status code, always 0.
10197 */
10198
10199static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10200 struct net_device *ndev,
10201 u8 key_index,
10202 bool pairwise, const u8 *mac_addr)
10203{
10204 EXIT();
10205 return 0;
10206}
10207
10208/**
10209 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10210 * @wiphy: Pointer to wiphy structure.
10211 * @dev: Pointer to net_device structure.
10212 * @key_index: key index
10213 * @pairwise: pairwise
10214 * @mac_addr: mac address
10215 *
10216 * This is the cfg80211 delete key handler function which invokes
10217 * the internal function @__wlan_hdd_cfg80211_del_key with
10218 * SSR protection.
10219 *
10220 * Return: 0 for success, error number on failure.
10221 */
10222static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10223 struct net_device *dev,
10224 u8 key_index,
10225 bool pairwise, const u8 *mac_addr)
10226{
10227 int ret;
10228
10229 cds_ssr_protect(__func__);
10230 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10231 pairwise, mac_addr);
10232 cds_ssr_unprotect(__func__);
10233
10234 return ret;
10235}
10236
10237/*
10238 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10239 * This function is used to set the default tx key index
10240 */
10241static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10242 struct net_device *ndev,
10243 u8 key_index,
10244 bool unicast, bool multicast)
10245{
10246 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10247 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10248 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10249 hdd_context_t *pHddCtx;
10250 int status;
10251
10252 ENTER();
10253
Anurag Chouhan6d760662016-02-20 16:05:43 +053010254 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010255 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010256 return -EINVAL;
10257 }
10258
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010259 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010260 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10261 pAdapter->sessionId, key_index));
10262
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010263 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010264 hdd_device_mode_to_string(pAdapter->device_mode),
10265 pAdapter->device_mode, key_index);
10266
10267 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010268 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010269 return -EINVAL;
10270 }
10271
10272 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10273 status = wlan_hdd_validate_context(pHddCtx);
10274
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010275 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010276 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010277
Krunal Sonib4326f22016-03-10 13:05:51 -080010278 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10279 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010280 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10281 pHddStaCtx->conn_info.ucEncryptionType) &&
10282 (eCSR_ENCRYPT_TYPE_AES !=
10283 pHddStaCtx->conn_info.ucEncryptionType)) {
10284 /* If default key index is not same as previous one,
10285 * then update the default key index */
10286
10287 tCsrRoamSetKey setKey;
10288 uint32_t roamId = 0xFF;
10289 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10290
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010291 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010292
10293 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010294 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010295 setKey.keyId = key_index;
10296 setKey.keyLength = Keys->KeyLength[key_index];
10297
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010298 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010299 &Keys->KeyMaterial[key_index][0],
10300 Keys->KeyLength[key_index]);
10301
10302 setKey.keyDirection = eSIR_TX_RX;
10303
Anurag Chouhanc5548422016-02-24 18:33:27 +053010304 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010305 &pHddStaCtx->conn_info.bssId);
10306
10307 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10308 pWextState->roamProfile.EncryptionType.
10309 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10310 /* In the case of dynamic wep supplicant hardcodes DWEP type
10311 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10312 * WEP-40 encryption. In this canse the key length is 5 but the
10313 * encryption type is 104 hence checking the key langht(5) and
10314 * encryption type(104) and switching encryption type to 40*/
10315 pWextState->roamProfile.EncryptionType.
10316 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10317 pWextState->roamProfile.mcEncryptionType.
10318 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10319 }
10320
10321 setKey.encType =
10322 pWextState->roamProfile.EncryptionType.
10323 encryptionType[0];
10324
10325 /* Issue set key request */
10326 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10327 pAdapter->sessionId, &setKey,
10328 &roamId);
10329
10330 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010331 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010332 status);
10333 return -EINVAL;
10334 }
10335 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010336 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010337 /* In SoftAp mode setting key direction for default mode */
10338 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10339 pWextState->roamProfile.EncryptionType.encryptionType[0])
10340 && (eCSR_ENCRYPT_TYPE_AES !=
10341 pWextState->roamProfile.EncryptionType.
10342 encryptionType[0])) {
10343 /* Saving key direction for default key index to TX default */
10344 hdd_ap_ctx_t *pAPCtx =
10345 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10346 pAPCtx->wepKey[key_index].keyDirection =
10347 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010348 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010349 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010350 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010351 }
10352 }
10353
10354 EXIT();
10355 return status;
10356}
10357
10358static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10359 struct net_device *ndev,
10360 u8 key_index,
10361 bool unicast, bool multicast)
10362{
10363 int ret;
10364 cds_ssr_protect(__func__);
10365 ret =
10366 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10367 multicast);
10368 cds_ssr_unprotect(__func__);
10369
10370 return ret;
10371}
10372
Abhishek Singhc9941602016-08-09 16:06:22 +053010373/*
10374 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10375 * @wiphy: wiphy pointer
10376 * @channel: channel of the BSS
10377 * @bssid: Bssid of BSS
10378 * @ssid: Ssid of the BSS
10379 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010380 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010381 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010382 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010383#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
10384struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10385 struct ieee80211_channel *channel, const u8 *bssid,
10386 const u8 *ssid, size_t ssid_len)
10387{
10388 return cfg80211_get_bss(wiphy, channel, bssid,
10389 ssid,
10390 ssid_len,
10391 WLAN_CAPABILITY_ESS,
10392 WLAN_CAPABILITY_ESS);
10393}
10394#else
10395struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10396 struct ieee80211_channel *channel, const u8 *bssid,
10397 const u8 *ssid, size_t ssid_len)
10398{
10399 return cfg80211_get_bss(wiphy, channel, bssid,
10400 ssid,
10401 ssid_len,
10402 IEEE80211_BSS_TYPE_ESS,
10403 IEEE80211_PRIVACY_ANY);
10404}
10405#endif
10406
10407
10408/*
10409 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10410 * interface that BSS might have been lost.
10411 * @pAdapter: adaptor
10412 * @bssid: bssid which might have been lost
10413 *
10414 * Return: bss which is unlinked from kernel cache
10415 */
10416struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10417 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010418{
10419 struct net_device *dev = pAdapter->dev;
10420 struct wireless_dev *wdev = dev->ieee80211_ptr;
10421 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010422 struct cfg80211_bss *bss = NULL;
10423
Abhishek Singhc9941602016-08-09 16:06:22 +053010424 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10425 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010426 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010427 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010428 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010429 hdd_info("cfg80211_unlink_bss called for BSSID "
10430 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010431 cfg80211_unlink_bss(wiphy, bss);
10432 }
10433 return bss;
10434}
10435
Abhishek Singhc9941602016-08-09 16:06:22 +053010436
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010437/**
10438 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10439 * @pAdapter: Pointer to adapter
10440 * @bss_desc: Pointer to bss descriptor
10441 *
10442 * This function is used to inform the BSS details to nl80211 interface.
10443 *
10444 * Return: struct cfg80211_bss pointer
10445 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010446struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10447 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010448{
10449 /*
10450 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10451 * already exists in bss data base of cfg80211 for that particular BSS
10452 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10453 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10454 * As of now there is no possibility to get the mgmt(probe response)
10455 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10456 * and passing to cfg80211_inform_bss_frame.
10457 */
10458 struct net_device *dev = pAdapter->dev;
10459 struct wireless_dev *wdev = dev->ieee80211_ptr;
10460 struct wiphy *wiphy = wdev->wiphy;
10461 int chan_no = bss_desc->channelId;
10462#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10463 qcom_ie_age *qie_age = NULL;
10464 int ie_length =
10465 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10466#else
10467 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10468#endif
10469 const char *ie =
10470 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10471 unsigned int freq;
10472 struct ieee80211_channel *chan;
10473 struct ieee80211_mgmt *mgmt = NULL;
10474 struct cfg80211_bss *bss_status = NULL;
10475 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10476 int rssi = 0;
10477 hdd_context_t *pHddCtx;
10478 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010479 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010480 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010481
10482 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10483 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010484 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010485 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010486
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010487 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010488 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10489 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010490 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010491 return NULL;
10492 }
10493
10494 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10495
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010496 /* Android does not want the timestamp from the frame.
10497 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010498 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010499 mgmt->u.probe_resp.timestamp =
10500 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010501
10502 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10503 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10504
10505#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10506 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10507 /* Assuming this is the last IE, copy at the end */
10508 ie_length -= sizeof(qcom_ie_age);
10509 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10510 qie_age->element_id = QCOM_VENDOR_IE_ID;
10511 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10512 qie_age->oui_1 = QCOM_OUI1;
10513 qie_age->oui_2 = QCOM_OUI2;
10514 qie_age->oui_3 = QCOM_OUI3;
10515 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
10516 qie_age->age =
Anurag Chouhan210db072016-02-22 18:42:15 +053010517 qdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010518 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010519 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10520 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010521 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10522 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010523#endif
10524
10525 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10526 if (bss_desc->fProbeRsp) {
10527 mgmt->frame_control |=
10528 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10529 } else {
10530 mgmt->frame_control |=
10531 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10532 }
10533
10534 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
10535 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
10536 freq =
10537 ieee80211_channel_to_frequency(chan_no,
10538 IEEE80211_BAND_2GHZ);
10539 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
10540 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
10541 freq =
10542 ieee80211_channel_to_frequency(chan_no,
10543 IEEE80211_BAND_5GHZ);
10544 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010545 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010546 kfree(mgmt);
10547 return NULL;
10548 }
10549
10550 chan = __ieee80211_get_channel(wiphy, freq);
10551 /* When the band is changed on the fly using the GUI, three things are done
10552 * 1. scan abort
10553 * 2. flush scan results from cache
10554 * 3. update the band with the new band user specified (refer to the
10555 * hdd_set_band_helper function) as part of the scan abort, message will be
10556 * queued to PE and we proceed with flushing and changinh the band.
10557 * PE will stop the scanning further and report back the results what ever
10558 * it had till now by calling the call back function.
10559 * if the time between update band and scandone call back is sufficient
10560 * enough the band change reflects in SME, SME validates the channels
10561 * and discards the channels correponding to previous band and calls back
10562 * with zero bss results. but if the time between band update and scan done
10563 * callback is very small then band change will not reflect in SME and SME
10564 * reports to HDD all the channels correponding to previous band.this is due
10565 * to race condition.but those channels are invalid to the new band and so
10566 * this function __ieee80211_get_channel will return NULL.Each time we
10567 * report scan result with this pointer null warning kernel trace is printed.
10568 * if the scan results contain large number of APs continuosly kernel
10569 * warning trace is printed and it will lead to apps watch dog bark.
10570 * So drop the bss and continue to next bss.
10571 */
10572 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010573 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10574 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010575 kfree(mgmt);
10576 return NULL;
10577 }
10578
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010579 /* Based on .ini configuration, raw rssi can be reported for bss.
10580 * Raw rssi is typically used for estimating power.
10581 */
10582
10583 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10584 bss_desc->rssi;
10585
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010586 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010587 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010588
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010589 hdd_notice("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010590 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010591 (int)(rssi / 100),
10592 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010593
10594 bss_status =
10595 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10596 GFP_KERNEL);
10597 kfree(mgmt);
10598 return bss_status;
10599}
10600
10601/**
10602 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10603 * @pAdapter: Pointer to adapter
10604 * @pRoamInfo: Pointer to roam info
10605 *
10606 * This function is used to update the BSS data base of CFG8011
10607 *
10608 * Return: struct cfg80211_bss pointer
10609 */
10610struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10611 tCsrRoamInfo *pRoamInfo)
10612{
10613 tCsrRoamConnectedProfile roamProfile;
10614 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10615 struct cfg80211_bss *bss = NULL;
10616
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010617 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10618 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10619
10620 if (NULL != roamProfile.pBssDesc) {
10621 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10622 roamProfile.pBssDesc);
10623
10624 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010625 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010626
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010627 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010628 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010629 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010630 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010631 return bss;
10632}
10633/**
10634 * wlan_hdd_cfg80211_update_bss() - update bss
10635 * @wiphy: Pointer to wiphy
10636 * @pAdapter: Pointer to adapter
10637 * @scan_time: scan request timestamp
10638 *
10639 * Return: zero if success, non-zero otherwise
10640 */
10641int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10642 hdd_adapter_t *pAdapter,
10643 uint32_t scan_time)
10644{
10645 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10646 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010647 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010648 tScanResultHandle pResult;
10649 struct cfg80211_bss *bss_status = NULL;
10650 hdd_context_t *pHddCtx;
10651 int ret;
10652
10653 ENTER();
10654
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010655 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010656 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10657 NO_SESSION, pAdapter->sessionId));
10658
10659 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10660 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010661 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010662 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010663
10664 /* start getting scan results and populate cgf80211 BSS database */
10665 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
10666
10667 /* no scan results */
10668 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010669 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053010670 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010671 }
10672
10673 pScanResult = sme_scan_result_get_first(hHal, pResult);
10674
10675 while (pScanResult) {
10676 /*
10677 * - cfg80211_inform_bss() is not updating ie field of bss
10678 * entry if entry already exists in bss data base of cfg80211
10679 * for that particular BSS ID. Using cfg80211_inform_bss_frame
10680 * to update thebss entry instead of cfg80211_inform_bss,
10681 * But this call expects mgmt packet as input. As of now
10682 * there is no possibility to get the mgmt(probe response)
10683 * frame from PE, converting bss_desc to
10684 * ieee80211_mgmt(probe response) and passing to c
10685 * fg80211_inform_bss_frame.
10686 * - Update BSS only if beacon timestamp is later than
10687 * scan request timestamp.
10688 */
10689 if ((scan_time == 0) ||
10690 (scan_time <
10691 pScanResult->BssDescriptor.nReceivedTime)) {
10692 bss_status =
10693 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10694 &pScanResult->BssDescriptor);
10695
10696 if (NULL == bss_status) {
10697 hdd_info("NULL returned by cfg80211_inform_bss_frame");
10698 } else {
10699 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010700 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010701 bss_status);
10702 }
10703 } else {
10704 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
10705 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
10706 }
10707 pScanResult = sme_scan_result_get_next(hHal, pResult);
10708 }
10709
10710 sme_scan_result_purge(hHal, pResult);
10711 /*
10712 * For SAP mode, scan is invoked by hostapd during SAP start
10713 * if hostapd is restarted, we need to flush previous scan
10714 * result so that it will reflect environment change
10715 */
Krunal Sonib4326f22016-03-10 13:05:51 -080010716 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010717#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
10718 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
10719#endif
10720 )
10721 sme_scan_flush_result(hHal);
10722
10723 EXIT();
10724 return 0;
10725}
10726
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010727/**
10728 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
10729 * @pAdapter: Pointer to adapter
10730 * @pRoamInfo: Pointer to roam info
10731 * @index: Index
10732 * @preauth: Preauth flag
10733 *
10734 * This function is used to notify the supplicant of a new PMKSA candidate.
10735 *
10736 * Return: 0 for success, non-zero for failure
10737 */
10738int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
10739 tCsrRoamInfo *pRoamInfo,
10740 int index, bool preauth)
10741{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010742 struct net_device *dev = pAdapter->dev;
10743 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
10744
10745 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010746 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010747
10748 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010749 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010750 return -EINVAL;
10751 }
10752
10753 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010754 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010755 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
10756 cfg80211_pmksa_candidate_notify(dev, index,
10757 pRoamInfo->bssid.bytes,
10758 preauth, GFP_KERNEL);
10759 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010760 return 0;
10761}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010762
10763#ifdef FEATURE_WLAN_LFR_METRICS
10764/**
10765 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
10766 * @pAdapter: Pointer to adapter
10767 * @pRoamInfo: Pointer to roam info
10768 *
10769 * 802.11r/LFR metrics reporting function to report preauth initiation
10770 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010771 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010772 */
10773#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010774QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010775 tCsrRoamInfo *pRoamInfo)
10776{
10777 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10778 union iwreq_data wrqu;
10779
10780 ENTER();
10781
10782 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010783 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010784 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010785 }
10786
10787 /* create the event */
10788 memset(&wrqu, 0, sizeof(wrqu));
10789 memset(metrics_notification, 0, sizeof(metrics_notification));
10790
10791 wrqu.data.pointer = metrics_notification;
10792 wrqu.data.length = scnprintf(metrics_notification,
10793 sizeof(metrics_notification),
10794 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
10795 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10796
10797 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10798 metrics_notification);
10799
10800 EXIT();
10801
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010802 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010803}
10804
10805/**
10806 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10807 * @pAdapter: Pointer to adapter
10808 * @pRoamInfo: Pointer to roam info
10809 * @preauth_status: Preauth status
10810 *
10811 * 802.11r/LFR metrics reporting function to report handover initiation
10812 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010813 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010814 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010815QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010816wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
10817 tCsrRoamInfo *pRoamInfo,
10818 bool preauth_status)
10819{
10820 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10821 union iwreq_data wrqu;
10822
10823 ENTER();
10824
10825 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010826 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010827 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010828 }
10829
10830 /* create the event */
10831 memset(&wrqu, 0, sizeof(wrqu));
10832 memset(metrics_notification, 0, sizeof(metrics_notification));
10833
10834 scnprintf(metrics_notification, sizeof(metrics_notification),
10835 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
10836 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10837
10838 if (1 == preauth_status)
10839 strlcat(metrics_notification, " true",
10840 sizeof(metrics_notification));
10841 else
10842 strlcat(metrics_notification, " false",
10843 sizeof(metrics_notification));
10844
10845 wrqu.data.pointer = metrics_notification;
10846 wrqu.data.length = strlen(metrics_notification);
10847
10848 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10849 metrics_notification);
10850
10851 EXIT();
10852
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010853 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010854}
10855
10856/**
10857 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10858 * @pAdapter: Pointer to adapter
10859 * @pRoamInfo: Pointer to roam info
10860 *
10861 * 802.11r/LFR metrics reporting function to report handover initiation
10862 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010863 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010864 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010865QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010866 tCsrRoamInfo *pRoamInfo)
10867{
10868 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10869 union iwreq_data wrqu;
10870
10871 ENTER();
10872
10873 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010874 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010875 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010876 }
10877
10878 /* create the event */
10879 memset(&wrqu, 0, sizeof(wrqu));
10880 memset(metrics_notification, 0, sizeof(metrics_notification));
10881
10882 wrqu.data.pointer = metrics_notification;
10883 wrqu.data.length = scnprintf(metrics_notification,
10884 sizeof(metrics_notification),
10885 "QCOM: LFR_PREAUTH_HANDOVER "
10886 MAC_ADDRESS_STR,
10887 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10888
10889 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10890 metrics_notification);
10891
10892 EXIT();
10893
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010894 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010895}
10896#endif
10897
10898/**
10899 * hdd_select_cbmode() - select channel bonding mode
10900 * @pAdapter: Pointer to adapter
10901 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010902 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010903 *
10904 * Return: none
10905 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010906void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
10907 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010908{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010909 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010910 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010911 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010912
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010913 /*
10914 * CDS api expects secondary channel for calculating
10915 * the channel params
10916 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010917 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010918 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
10919 if (operationChannel >= 1 && operationChannel <= 5)
10920 sec_ch = operationChannel + 4;
10921 else if (operationChannel >= 6 && operationChannel <= 13)
10922 sec_ch = operationChannel - 4;
10923 }
10924
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010925 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010926 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010927
10928 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010929 eHddDot11Mode hdd_dot11_mode;
10930 uint8_t iniDot11Mode =
10931 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
10932
10933 hdd_notice("Dot11Mode is %u", iniDot11Mode);
10934 switch (iniDot11Mode) {
10935 case eHDD_DOT11_MODE_AUTO:
10936 case eHDD_DOT11_MODE_11ac:
10937 case eHDD_DOT11_MODE_11ac_ONLY:
10938 if (sme_is_feature_supported_by_fw(DOT11AC))
10939 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
10940 else
10941 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
10942 break;
10943 case eHDD_DOT11_MODE_11n:
10944 case eHDD_DOT11_MODE_11n_ONLY:
10945 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
10946 break;
10947 default:
10948 hdd_dot11_mode = iniDot11Mode;
10949 break;
10950 }
10951 ch_info->channel_width = ch_params->ch_width;
10952 ch_info->phy_mode =
10953 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010954 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010955 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010956 hdd_info("ch_info width %d, phymode %d channel %d",
10957 ch_info->channel_width, ch_info->phy_mode,
10958 ch_info->channel);
10959 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960}
10961
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070010962/**
10963 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
10964 * @adapter: STA adapter
10965 * @roam_profile: STA roam profile
10966 *
10967 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
10968 *
10969 * Return: false if sta-sap conc is not allowed, else return true
10970 */
10971static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
10972 tCsrRoamProfile *roam_profile)
10973{
10974 hdd_context_t *hdd_ctx;
10975 hdd_adapter_t *ap_adapter;
10976 hdd_ap_ctx_t *hdd_ap_ctx;
10977 hdd_hostapd_state_t *hostapd_state;
10978 uint8_t channel = 0;
10979 QDF_STATUS status;
10980
10981 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10982 if (!hdd_ctx) {
10983 hdd_err("HDD context is NULL");
10984 return true;
10985 }
10986
10987 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
10988 /* probably no sap running, no handling required */
10989 if (ap_adapter == NULL)
10990 return true;
10991
10992 /*
10993 * sap is not in started state, so it is fine to go ahead with sta.
10994 * if sap is currently doing CAC then don't allow sta to go further.
10995 */
10996 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
10997 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
10998 return true;
10999
11000 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11001 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11002 return false;
11003 }
11004
11005 /*
11006 * log and return error, if we allow STA to go through, we don't
11007 * know what is going to happen better stop sta connection
11008 */
11009 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11010 if (NULL == hdd_ap_ctx) {
11011 hdd_err("AP context not found");
11012 return false;
11013 }
11014
11015 /* sap is on non-dfs channel, nothing to handle */
11016 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11017 hdd_info("sap is on non-dfs channel, sta is allowed");
11018 return true;
11019 }
11020 /*
11021 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011022 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011023 */
11024 status = cds_get_channel_from_scan_result(adapter,
11025 roam_profile, &channel);
11026
Nitesh Shah59774522016-09-16 15:14:21 +053011027 /*
11028 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11029 * channels for roaming case.
11030 */
11031 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11032 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11033 return true;
11034 }
11035
11036 /*
11037 * If channel is 0 or DFS then better to call pcl and find out the
11038 * best channel. If channel is non-dfs 5 GHz then better move SAP
11039 * to STA's channel to make scc, so we have room for 3port MCC
11040 * scenario.
11041 */
11042 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011043 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11044 true);
11045
11046 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11047 qdf_event_reset(&hostapd_state->qdf_event);
11048 status = wlansap_set_channel_change_with_csa(
11049 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11050 hdd_ap_ctx->sapConfig.ch_width_orig);
11051
11052 if (QDF_STATUS_SUCCESS != status) {
11053 hdd_err("Set channel with CSA IE failed, can't allow STA");
11054 return false;
11055 }
11056
11057 /*
11058 * wait here for SAP to finish the channel switch. When channel
11059 * switch happens, SAP sends few beacons with CSA_IE. After
11060 * successfully Transmission of those beacons, it will move its
11061 * state from started to disconnected and move to new channel.
11062 * once it moves to new channel, sap again moves its state
11063 * machine from disconnected to started and set this event.
11064 * wait for 10 secs to finish this.
11065 */
11066 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11067 if (!QDF_IS_STATUS_SUCCESS(status)) {
11068 hdd_err("wait for qdf_event failed, STA not allowed!!");
11069 return false;
11070 }
11071
11072 return true;
11073}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011074
Krunal Soni31949422016-07-29 17:17:53 -070011075/**
11076 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011077 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011078 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011079 * @ssid_len: Length of ssid
11080 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011081 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011082 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011083 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011084 *
11085 * This function is used to start the association process
11086 *
11087 * Return: 0 for success, non-zero for failure
11088 */
Krunal Soni31949422016-07-29 17:17:53 -070011089static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011090 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011091 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011092 u8 operatingChannel,
11093 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011094{
11095 int status = 0;
11096 hdd_wext_state_t *pWextState;
11097 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011098 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011099 uint32_t roamId;
11100 tCsrRoamProfile *pRoamProfile;
11101 eCsrAuthType RSNAuthType;
11102 tSmeConfigParams *sme_config;
11103
11104 ENTER();
11105
11106 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11107 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011108 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011109
11110 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011111 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011112 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011113
11114 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011115 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011116 return -EINVAL;
11117 }
11118
11119 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011120 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11121 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011122
11123 if (pRoamProfile) {
11124 hdd_station_ctx_t *pHddStaCtx;
11125 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11126
11127 if (HDD_WMM_USER_MODE_NO_QOS ==
11128 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11129 /*QoS not enabled in cfg file */
11130 pRoamProfile->uapsd_mask = 0;
11131 } else {
11132 /*QoS enabled, update uapsd mask from cfg file */
11133 pRoamProfile->uapsd_mask =
11134 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11135 }
11136
11137 pRoamProfile->SSIDs.numOfSSIDs = 1;
11138 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011139 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011140 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011141 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011142 ssid, ssid_len);
11143
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011144 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011145 if (bssid) {
11146 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011147 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011148 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011149 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011150 /*
11151 * Save BSSID in seperate variable as
11152 * pRoamProfile's BSSID is getting zeroed out in the
11153 * association process. In case of join failure
11154 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011155 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011156 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011157 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011158 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011159 } else if (bssid_hint) {
11160 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011161 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011162 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011163 /*
11164 * Save BSSID in a separate variable as
11165 * pRoamProfile's BSSID is getting zeroed out in the
11166 * association process. In case of join failure
11167 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011168 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011169 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011170 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011171 hdd_info("bssid_hint is given by upper layer %pM",
11172 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011173 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011174 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011175 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011176 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011177 }
11178
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011179 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011180 pRoamProfile->SSIDs.SSIDList->SSID.length,
11181 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11182 operatingChannel);
11183
11184 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11185 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011186 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011187 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11188 }
11189#ifdef FEATURE_WLAN_WAPI
11190 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011191 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011192 switch (pAdapter->wapi_info.wapiAuthMode) {
11193 case WAPI_AUTH_MODE_PSK:
11194 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011195 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011196 pAdapter->wapi_info.wapiAuthMode);
11197 pRoamProfile->AuthType.authType[0] =
11198 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11199 break;
11200 }
11201 case WAPI_AUTH_MODE_CERT:
11202 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011203 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011204 pAdapter->wapi_info.wapiAuthMode);
11205 pRoamProfile->AuthType.authType[0] =
11206 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11207 break;
11208 }
11209 } /* End of switch */
11210 if (pAdapter->wapi_info.wapiAuthMode ==
11211 WAPI_AUTH_MODE_PSK
11212 || pAdapter->wapi_info.wapiAuthMode ==
11213 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011214 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011215 pRoamProfile->AuthType.numEntries = 1;
11216 pRoamProfile->EncryptionType.numEntries = 1;
11217 pRoamProfile->EncryptionType.encryptionType[0] =
11218 eCSR_ENCRYPT_TYPE_WPI;
11219 pRoamProfile->mcEncryptionType.numEntries = 1;
11220 pRoamProfile->mcEncryptionType.
11221 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11222 }
11223 }
Krunal Soni31949422016-07-29 17:17:53 -070011224#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011225#ifdef WLAN_FEATURE_GTK_OFFLOAD
11226 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011227 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11228 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011229 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11230 sizeof(tSirGtkOffloadParams));
11231 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11232 GTK_OFFLOAD_DISABLE;
11233 }
11234#endif
11235 pRoamProfile->csrPersona = pAdapter->device_mode;
11236
11237 if (operatingChannel) {
11238 pRoamProfile->ChannelInfo.ChannelList =
11239 &operatingChannel;
11240 pRoamProfile->ChannelInfo.numOfChannels = 1;
11241 } else {
11242 pRoamProfile->ChannelInfo.ChannelList = NULL;
11243 pRoamProfile->ChannelInfo.numOfChannels = 0;
11244 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011245 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011246 && operatingChannel) {
11247 /*
11248 * Need to post the IBSS power save parameters
11249 * to WMA. WMA will configure this parameters
11250 * to firmware if power save is enabled by the
11251 * firmware.
11252 */
11253 status = hdd_set_ibss_power_save_params(pAdapter);
11254
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011255 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011256 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011257 return -EINVAL;
11258 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011259 pRoamProfile->ch_params.ch_width =
11260 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011261 /*
11262 * In IBSS mode while operating in 2.4 GHz,
11263 * the device supports only 20 MHz.
11264 */
11265 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11266 pRoamProfile->ch_params.ch_width =
11267 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011268 hdd_select_cbmode(pAdapter, operatingChannel,
11269 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011271 /*
11272 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11273 * or pmf=2 is an explicit configuration in the supplicant
11274 * configuration, drop the connection request.
11275 */
11276 if (pWextState->roamProfile.MFPEnabled &&
11277 !(pWextState->roamProfile.MFPRequired ||
11278 pWextState->roamProfile.MFPCapable)) {
11279 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11280 pWextState->roamProfile.MFPEnabled,
11281 pWextState->roamProfile.MFPRequired,
11282 pWextState->roamProfile.MFPCapable);
11283 return -EINVAL;
11284 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011285
Krunal Soni3091bcc2016-06-23 12:28:21 -070011286 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011287 hdd_err("Connection refused: conn in progress");
11288 return -EINVAL;
11289 }
11290
Krunal Soni31949422016-07-29 17:17:53 -070011291 /*
11292 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011293 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011294 * enhancements, the supplicant is not issuing the scan command
11295 * now. So the unicast frames which are sent from the host are
11296 * not having the additional IEs. If it is P2P CLIENT and there
11297 * is no additional IE present in roamProfile, then use the
11298 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011299 */
11300
Krunal Sonib4326f22016-03-10 13:05:51 -080011301 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011302 (!pRoamProfile->pAddIEScan)) {
11303 pRoamProfile->pAddIEScan =
11304 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11305 pRoamProfile->nAddIEScanLength =
11306 pAdapter->scan_info.scanAddIE.length;
11307 }
11308 /*
11309 * When policy manager is enabled from ini file, we shouldn't
11310 * check for other concurrency rules.
11311 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011312 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011313 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011314 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011315 pAdapter, pRoamProfile, &roamId))
11316 return 0;
11317 }
11318
Krunal Soni3091bcc2016-06-23 12:28:21 -070011319 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011320 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11321 pRoamProfile))) {
11322 hdd_err("sap-sta conc will fail, can't allow sta");
11323 hdd_conn_set_connection_state(pAdapter,
11324 eConnectionState_NotConnected);
11325 return -ENOMEM;
11326 }
11327
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011328 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011329 if (!sme_config) {
11330 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011331 hdd_conn_set_connection_state(pAdapter,
11332 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011333 return -ENOMEM;
11334 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011335 qdf_mem_zero(sme_config, sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011336 sme_get_config_param(pHddCtx->hHal, sme_config);
11337 /* These values are not sessionized. So, any change in these SME
11338 * configs on an older or parallel interface will affect the
11339 * cb mode. So, restoring the default INI params before starting
11340 * interfaces such as sta, cli etc.,
11341 */
11342 sme_config->csrConfig.channelBondingMode5GHz =
11343 pHddCtx->config->nChannelBondingMode5GHz;
11344 sme_config->csrConfig.channelBondingMode24GHz =
11345 pHddCtx->config->nChannelBondingMode24GHz;
11346 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011347 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011348 /*
11349 * Change conn_state to connecting before sme_roam_connect(),
11350 * because sme_roam_connect() has a direct path to call
11351 * hdd_sme_roam_callback(), which will change the conn_state
11352 * If direct path, conn_state will be accordingly changed to
11353 * NotConnected or Associated by either
11354 * hdd_association_completion_handler() or
11355 * hdd_dis_connect_handler() in sme_RoamCallback()if
11356 * sme_RomConnect is to be queued,
11357 * Connecting state will remain until it is completed.
11358 *
11359 * If connection state is not changed, connection state will
11360 * remain in eConnectionState_NotConnected state.
11361 * In hdd_association_completion_handler, "hddDisconInProgress"
11362 * is set to true if conn state is
11363 * eConnectionState_NotConnected.
11364 * If "hddDisconInProgress" is set to true then cfg80211 layer
11365 * is not informed of connect result indication which
11366 * is an issue.
11367 */
11368 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011369 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011370 hdd_conn_set_connection_state(pAdapter,
11371 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011372
11373 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11374 pAdapter->sessionId, pRoamProfile,
11375 &roamId);
11376
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011377 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011378 (QDF_STA_MODE == pAdapter->device_mode ||
11379 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011380 hdd_err("sme_roam_connect (session %d) failed with "
11381 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011382 pAdapter->sessionId, status);
11383 /* change back to NotAssociated */
11384 hdd_conn_set_connection_state(pAdapter,
11385 eConnectionState_NotConnected);
11386 }
11387
11388 pRoamProfile->ChannelInfo.ChannelList = NULL;
11389 pRoamProfile->ChannelInfo.numOfChannels = 0;
11390
11391 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011392 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011393 return -EINVAL;
11394 }
11395 EXIT();
11396 return status;
11397}
11398
11399/**
11400 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11401 * @pAdapter: Pointer to adapter
11402 * @auth_type: Auth type
11403 *
11404 * This function is used to set the authentication type (OPEN/SHARED).
11405 *
11406 * Return: 0 for success, non-zero for failure
11407 */
11408static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11409 enum nl80211_auth_type auth_type)
11410{
11411 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11412 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11413
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011414 /*set authentication type */
11415 switch (auth_type) {
11416 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011417 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011418 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11419 break;
11420
11421 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011422 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011423 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011424 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11425 break;
11426
11427 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011428 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011429 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11430 break;
11431#ifdef FEATURE_WLAN_ESE
11432 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011433 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011434 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11435 break;
11436#endif
11437
11438 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011439 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011440 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11441 return -EINVAL;
11442 }
11443
11444 pWextState->roamProfile.AuthType.authType[0] =
11445 pHddStaCtx->conn_info.authType;
11446 return 0;
11447}
11448
11449/**
11450 * wlan_hdd_set_akm_suite() - set key management type
11451 * @pAdapter: Pointer to adapter
11452 * @key_mgmt: Key management type
11453 *
11454 * This function is used to set the key mgmt type(PSK/8021x).
11455 *
11456 * Return: 0 for success, non-zero for failure
11457 */
11458static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11459{
11460 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011462#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11463#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11464 /*set key mgmt type */
11465 switch (key_mgmt) {
11466 case WLAN_AKM_SUITE_PSK:
11467 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011468 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011469 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011470 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11471 break;
11472
11473 case WLAN_AKM_SUITE_8021X_SHA256:
11474 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011475 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011476 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011477 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11478 break;
11479#ifdef FEATURE_WLAN_ESE
11480#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11481#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11482 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011483 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011484 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11485 break;
11486#endif
11487#ifndef WLAN_AKM_SUITE_OSEN
11488#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11489#endif
11490 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011491 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011492 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11493 break;
11494
11495 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011496 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011497 return -EINVAL;
11498
11499 }
11500 return 0;
11501}
11502
11503/**
11504 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11505 * @pAdapter: Pointer to adapter
11506 * @cipher: Cipher type
11507 * @ucast: Unicast flag
11508 *
11509 * This function is used to set the encryption type
11510 * (NONE/WEP40/WEP104/TKIP/CCMP).
11511 *
11512 * Return: 0 for success, non-zero for failure
11513 */
11514static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11515 u32 cipher, bool ucast)
11516{
11517 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11518 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11519 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11520
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011521 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011522 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011523 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11524 } else {
11525
11526 /*set encryption method */
11527 switch (cipher) {
11528 case IW_AUTH_CIPHER_NONE:
11529 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11530 break;
11531
11532 case WLAN_CIPHER_SUITE_WEP40:
11533 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11534 break;
11535
11536 case WLAN_CIPHER_SUITE_WEP104:
11537 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11538 break;
11539
11540 case WLAN_CIPHER_SUITE_TKIP:
11541 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11542 break;
11543
11544 case WLAN_CIPHER_SUITE_CCMP:
11545 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11546 break;
11547#ifdef FEATURE_WLAN_WAPI
11548 case WLAN_CIPHER_SUITE_SMS4:
11549 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11550 break;
11551#endif
11552
11553#ifdef FEATURE_WLAN_ESE
11554 case WLAN_CIPHER_SUITE_KRK:
11555 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11556 break;
11557#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11558 case WLAN_CIPHER_SUITE_BTK:
11559 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11560 break;
11561#endif
11562#endif
11563 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011564 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011565 return -EOPNOTSUPP;
11566 }
11567 }
11568
11569 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011570 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011571 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11572 pWextState->roamProfile.EncryptionType.numEntries = 1;
11573 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11574 encryptionType;
11575 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011576 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011577 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11578 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11579 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11580 encryptionType;
11581 }
11582
11583 return 0;
11584}
11585
11586/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011587 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11588 * @wext_state: Pointer to wext state
11589 * @gen_ie: Pointer to IE data
11590 * @len: length of IE data
11591 *
11592 * Return: 0 for success, non-zero for failure
11593 */
11594static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11595 const uint8_t *gen_ie, uint16_t len)
11596{
11597 uint16_t cur_add_ie_len =
11598 wext_state->assocAddIE.length;
11599
11600 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11601 (wext_state->assocAddIE.length + len)) {
11602 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11603 QDF_ASSERT(0);
11604 return -ENOMEM;
11605 }
11606 memcpy(wext_state->assocAddIE.addIEdata +
11607 cur_add_ie_len, gen_ie, len);
11608 wext_state->assocAddIE.length += len;
11609
11610 wext_state->roamProfile.pAddIEAssoc =
11611 wext_state->assocAddIE.addIEdata;
11612 wext_state->roamProfile.nAddIEAssocLength =
11613 wext_state->assocAddIE.length;
11614 return 0;
11615}
11616
11617/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011618 * wlan_hdd_cfg80211_set_ie() - set IEs
11619 * @pAdapter: Pointer to adapter
11620 * @ie: Pointer ot ie
11621 * @ie: IE length
11622 *
11623 * Return: 0 for success, non-zero for failure
11624 */
11625int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
11626 size_t ie_len)
11627{
11628 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11629 const uint8_t *genie = ie;
11630 uint16_t remLen = ie_len;
11631#ifdef FEATURE_WLAN_WAPI
11632 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
11633 u16 *tmp;
11634 uint16_t akmsuiteCount;
11635 int *akmlist;
11636#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011637 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011638
11639 /* clear previous assocAddIE */
11640 pWextState->assocAddIE.length = 0;
11641 pWextState->roamProfile.bWPSAssociation = false;
11642 pWextState->roamProfile.bOSENAssociation = false;
11643
11644 while (remLen >= 2) {
11645 uint16_t eLen = 0;
11646 uint8_t elementId;
11647 elementId = *genie++;
11648 eLen = *genie++;
11649 remLen -= 2;
11650
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011651 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011652
11653 switch (elementId) {
11654 case DOT11F_EID_WPA:
11655 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 -070011656 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011657 return -EINVAL;
11658 } else if (0 ==
11659 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
11660 uint16_t curAddIELen =
11661 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011662 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011663
11664 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11665 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011666 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011667 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011668 return -ENOMEM;
11669 }
11670 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11671 memcpy(pWextState->assocAddIE.addIEdata +
11672 curAddIELen, genie - 2, eLen + 2);
11673 pWextState->assocAddIE.length += eLen + 2;
11674
11675 pWextState->roamProfile.bWPSAssociation = true;
11676 pWextState->roamProfile.pAddIEAssoc =
11677 pWextState->assocAddIE.addIEdata;
11678 pWextState->roamProfile.nAddIEAssocLength =
11679 pWextState->assocAddIE.length;
11680 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011681 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011682 memset(pWextState->WPARSNIE, 0,
11683 MAX_WPA_RSN_IE_LEN);
11684 memcpy(pWextState->WPARSNIE, genie - 2,
11685 (eLen + 2));
11686 pWextState->roamProfile.pWPAReqIE =
11687 pWextState->WPARSNIE;
11688 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
11689 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
11690 P2P_OUI_TYPE_SIZE))) {
11691 uint16_t curAddIELen =
11692 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011693 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011694
11695 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11696 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011697 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011698 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011699 return -ENOMEM;
11700 }
11701 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11702 memcpy(pWextState->assocAddIE.addIEdata +
11703 curAddIELen, genie - 2, eLen + 2);
11704 pWextState->assocAddIE.length += eLen + 2;
11705
11706 pWextState->roamProfile.pAddIEAssoc =
11707 pWextState->assocAddIE.addIEdata;
11708 pWextState->roamProfile.nAddIEAssocLength =
11709 pWextState->assocAddIE.length;
11710 }
11711#ifdef WLAN_FEATURE_WFD
11712 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
11713 WFD_OUI_TYPE_SIZE)) &&
11714 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080011715 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011716 pAdapter->device_mode)) {
11717 uint16_t curAddIELen =
11718 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011719 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011720
11721 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11722 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011723 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011724 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011725 return -ENOMEM;
11726 }
11727 /* WFD IE is saved to Additional IE ; it should
11728 * be accumulated to handle WPS IE + P2P IE +
11729 * WFD IE */
11730 memcpy(pWextState->assocAddIE.addIEdata +
11731 curAddIELen, genie - 2, eLen + 2);
11732 pWextState->assocAddIE.length += eLen + 2;
11733
11734 pWextState->roamProfile.pAddIEAssoc =
11735 pWextState->assocAddIE.addIEdata;
11736 pWextState->roamProfile.nAddIEAssocLength =
11737 pWextState->assocAddIE.length;
11738 }
11739#endif
11740 /* Appending HS 2.0 Indication Element in Assiciation Request */
11741 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
11742 HS20_OUI_TYPE_SIZE))) {
11743 uint16_t curAddIELen =
11744 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011745 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011746
11747 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11748 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011749 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011750 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011751 return -ENOMEM;
11752 }
11753 memcpy(pWextState->assocAddIE.addIEdata +
11754 curAddIELen, genie - 2, eLen + 2);
11755 pWextState->assocAddIE.length += eLen + 2;
11756
11757 pWextState->roamProfile.pAddIEAssoc =
11758 pWextState->assocAddIE.addIEdata;
11759 pWextState->roamProfile.nAddIEAssocLength =
11760 pWextState->assocAddIE.length;
11761 }
11762 /* Appending OSEN Information Element in Assiciation Request */
11763 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
11764 OSEN_OUI_TYPE_SIZE))) {
11765 uint16_t curAddIELen =
11766 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011767 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011768
11769 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11770 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011771 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011772 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011773 return -ENOMEM;
11774 }
11775 memcpy(pWextState->assocAddIE.addIEdata +
11776 curAddIELen, genie - 2, eLen + 2);
11777 pWextState->assocAddIE.length += eLen + 2;
11778
11779 pWextState->roamProfile.bOSENAssociation = true;
11780 pWextState->roamProfile.pAddIEAssoc =
11781 pWextState->assocAddIE.addIEdata;
11782 pWextState->roamProfile.nAddIEAssocLength =
11783 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011784 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
11785 MBO_OUI_TYPE_SIZE))){
11786 hdd_info("Set MBO IE(len %d)", eLen + 2);
11787 status = wlan_hdd_add_assoc_ie(pWextState,
11788 genie - 2, eLen + 2);
11789 if (status)
11790 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011791 } else {
11792 uint16_t add_ie_len =
11793 pWextState->assocAddIE.length;
11794
11795 hdd_info("Set OSEN IE(len %d)", eLen + 2);
11796
11797 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11798 (pWextState->assocAddIE.length + eLen)) {
11799 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011800 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011801 return -ENOMEM;
11802 }
11803
11804 memcpy(pWextState->assocAddIE.addIEdata +
11805 add_ie_len, genie - 2, eLen + 2);
11806 pWextState->assocAddIE.length += eLen + 2;
11807
11808 pWextState->roamProfile.pAddIEAssoc =
11809 pWextState->assocAddIE.addIEdata;
11810 pWextState->roamProfile.nAddIEAssocLength =
11811 pWextState->assocAddIE.length;
11812 }
11813 break;
11814 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011815 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011816 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
11817 memcpy(pWextState->WPARSNIE, genie - 2,
11818 (eLen + 2));
11819 pWextState->roamProfile.pRSNReqIE =
11820 pWextState->WPARSNIE;
11821 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
11822 break;
11823 /*
11824 * Appending Extended Capabilities with Interworking bit set
11825 * in Assoc Req.
11826 *
11827 * In assoc req this EXT Cap will only be taken into account if
11828 * interworkingService bit is set to 1. Currently
11829 * driver is only interested in interworkingService capability
11830 * from supplicant. If in future any other EXT Cap info is
11831 * required from supplicat, it needs to be handled while
11832 * sending Assoc Req in LIM.
11833 */
11834 case DOT11F_EID_EXTCAP:
11835 {
11836 uint16_t curAddIELen =
11837 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011838 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011839
11840 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11841 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011842 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011843 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011844 return -ENOMEM;
11845 }
11846 memcpy(pWextState->assocAddIE.addIEdata +
11847 curAddIELen, genie - 2, eLen + 2);
11848 pWextState->assocAddIE.length += eLen + 2;
11849
11850 pWextState->roamProfile.pAddIEAssoc =
11851 pWextState->assocAddIE.addIEdata;
11852 pWextState->roamProfile.nAddIEAssocLength =
11853 pWextState->assocAddIE.length;
11854 break;
11855 }
11856#ifdef FEATURE_WLAN_WAPI
11857 case WLAN_EID_WAPI:
11858 /* Setting WAPI Mode to ON=1 */
11859 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011860 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011861 tmp = (u16 *) ie;
11862 tmp = tmp + 2; /* Skip element Id and Len, Version */
11863 akmsuiteCount = WPA_GET_LE16(tmp);
11864 tmp = tmp + 1;
11865 akmlist = (int *)(tmp);
11866 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
11867 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
11868 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011869 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011870 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011871 return -EINVAL;
11872 }
11873
11874 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011875 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011876 pAdapter->wapi_info.wapiAuthMode =
11877 WAPI_AUTH_MODE_PSK;
11878 }
11879 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011880 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011881 pAdapter->wapi_info.wapiAuthMode =
11882 WAPI_AUTH_MODE_CERT;
11883 }
11884 break;
11885#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011886 case DOT11F_EID_SUPPOPERATINGCLASSES:
11887 {
11888 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
11889 status = wlan_hdd_add_assoc_ie(pWextState,
11890 genie - 2, eLen + 2);
11891 if (status)
11892 return status;
11893 break;
11894 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011895 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011896 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011897 /* when Unknown IE is received we should break and continue
11898 * to the next IE in the buffer instead we were returning
11899 * so changing this to break */
11900 break;
11901 }
11902 genie += eLen;
11903 remLen -= eLen;
11904 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011905 return 0;
11906}
11907
11908/**
11909 * hdd_is_wpaie_present() - check for WPA ie
11910 * @ie: Pointer to ie
11911 * @ie_len: Ie length
11912 *
11913 * Parse the received IE to find the WPA IE
11914 *
11915 * Return: true if wpa ie is found else false
11916 */
11917static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
11918{
11919 uint8_t eLen = 0;
11920 uint16_t remLen = ie_len;
11921 uint8_t elementId = 0;
11922
11923 while (remLen >= 2) {
11924 elementId = *ie++;
11925 eLen = *ie++;
11926 remLen -= 2;
11927 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011928 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011929 return false;
11930 }
11931 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
11932 /* OUI - 0x00 0X50 0XF2
11933 * WPA Information Element - 0x01
11934 * WPA version - 0x01
11935 */
11936 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
11937 return true;
11938 }
11939 ie += eLen;
11940 remLen -= eLen;
11941 }
11942 return false;
11943}
11944
11945/**
11946 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
11947 * @pAdapter: Pointer to adapter
11948 * @req: Pointer to security parameters
11949 *
11950 * Return: 0 for success, non-zero for failure
11951 */
11952int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
11953 struct cfg80211_connect_params *req)
11954{
11955 int status = 0;
11956 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11957 ENTER();
11958
11959 /*set wpa version */
11960 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
11961
11962 if (req->crypto.wpa_versions) {
11963 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
11964 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
11965 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
11966 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
11967 }
11968 }
11969
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011970 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011971
11972 /*set authentication type */
11973 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
11974
11975 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011976 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011977 return status;
11978 }
11979
11980 /*set key mgmt type */
11981 if (req->crypto.n_akm_suites) {
11982 status =
11983 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
11984 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011985 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011986 return status;
11987 }
11988 }
11989
11990 /*set pairwise cipher type */
11991 if (req->crypto.n_ciphers_pairwise) {
11992 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
11993 req->crypto.
11994 ciphers_pairwise[0],
11995 true);
11996 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011997 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011998 return status;
11999 }
12000 } else {
12001 /*Reset previous cipher suite to none */
12002 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12003 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012004 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012005 return status;
12006 }
12007 }
12008
12009 /*set group cipher type */
12010 status =
12011 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12012 false);
12013
12014 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012015 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012016 return status;
12017 }
12018#ifdef WLAN_FEATURE_11W
12019 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12020#endif
12021
12022 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12023 if (req->ie_len) {
12024 status =
12025 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12026 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012027 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012028 return status;
12029 }
12030 }
12031
12032 /*incase of WEP set default key information */
12033 if (req->key && req->key_len) {
12034 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12035 || (WLAN_CIPHER_SUITE_WEP104 ==
12036 req->crypto.ciphers_pairwise[0])
12037 ) {
12038 if (IW_AUTH_KEY_MGMT_802_1X
12039 ==
12040 (pWextState->
12041 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012042 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012043 return -EOPNOTSUPP;
12044 } else {
12045 u8 key_len = req->key_len;
12046 u8 key_idx = req->key_idx;
12047
12048 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12049 key_len)
12050 && (CSR_MAX_NUM_KEY > key_idx)
12051 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012052 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012053 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012054 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012055 Keys.
12056 KeyMaterial[key_idx][0],
12057 req->key, key_len);
12058 pWextState->roamProfile.Keys.
12059 KeyLength[key_idx] = (u8) key_len;
12060 pWextState->roamProfile.Keys.
12061 defaultIndex = (u8) key_idx;
12062 }
12063 }
12064 }
12065 }
12066
12067 return status;
12068}
12069
12070/**
12071 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12072 * @pAdapter: Pointer to adapter
12073 *
12074 * This function is used to disconnect from previous connection
12075 *
12076 * Return: 0 for success, non-zero for failure
12077 */
12078static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12079{
12080 unsigned long rc;
12081 hdd_station_ctx_t *pHddStaCtx;
12082 eMib_dot11DesiredBssType connectedBssType;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012083 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012084
12085 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12086
12087 hdd_conn_get_connected_bss_type(pHddStaCtx, &connectedBssType);
12088
12089 if ((eMib_dot11DesiredBssType_independent == connectedBssType) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012090 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12091 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12092 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012093 hdd_conn_set_connection_state(pAdapter,
12094 eConnectionState_Disconnecting);
12095 /* Issue disconnect to CSR */
12096 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012097
12098 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12099 pAdapter->sessionId,
12100 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12101 /*
12102 * Wait here instead of returning directly, this will block the
12103 * next connect command and allow processing of the scan for
12104 * ssid and the previous connect command in CSR. Else we might
12105 * hit some race conditions leading to SME and HDD out of sync.
12106 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012107 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012108 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12109 } else if (0 != status) {
12110 hdd_err("csrRoamDisconnect failure, returned %d",
12111 (int)status);
12112 pHddStaCtx->staDebugState = status;
12113 result = -EINVAL;
12114 goto disconnected;
12115 }
12116
12117 rc = wait_for_completion_timeout(
12118 &pAdapter->disconnect_comp_var,
12119 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012120 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012121 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12122 pAdapter->sessionId, pHddStaCtx->staDebugState);
12123 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012124 }
12125 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012126 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012127 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012128 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012129 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012130 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012131 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012132 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012133 }
12134 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012135disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012136 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12137 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012138}
12139
12140/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012141 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12142 * @adapter: Pointer to the HDD adapter
12143 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012144 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012145 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012146 * This function will start reassociation if prev_bssid is set and bssid/
12147 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012148 *
Naveen Rawat07332902016-07-27 09:13:17 -070012149 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012150 */
12151#ifdef CFG80211_CONNECT_PREV_BSSID
Naveen Rawat07332902016-07-27 09:13:17 -070012152static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12153 struct cfg80211_connect_params *req,
12154 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012155{
Naveen Rawat07332902016-07-27 09:13:17 -070012156 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012157 const uint8_t *bssid = NULL;
12158 uint16_t channel = 0;
12159
12160 if (req->bssid)
12161 bssid = req->bssid;
12162 else if (req->bssid_hint)
12163 bssid = req->bssid_hint;
12164
12165 if (req->channel)
12166 channel = req->channel->hw_value;
12167 else if (req->channel_hint)
12168 channel = req->channel_hint->hw_value;
12169
12170 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012171 reassoc = true;
12172 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012173 channel, MAC_ADDR_ARRAY(bssid));
12174 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012175 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012176 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012177 }
Naveen Rawat07332902016-07-27 09:13:17 -070012178 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012179}
12180#else
Naveen Rawat07332902016-07-27 09:13:17 -070012181static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12182 struct cfg80211_connect_params *req,
12183 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012184{
Naveen Rawat07332902016-07-27 09:13:17 -070012185 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012186}
12187#endif
12188
12189/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012190 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12191 * @wiphy: Pointer to wiphy
12192 * @dev: Pointer to network device
12193 * @req: Pointer to cfg80211 connect request
12194 *
12195 * This function is used to start the association process
12196 *
12197 * Return: 0 for success, non-zero for failure
12198 */
12199static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12200 struct net_device *ndev,
12201 struct cfg80211_connect_params *req)
12202{
12203 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012204 u16 channel;
12205#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12206 const u8 *bssid_hint = req->bssid_hint;
12207#else
12208 const u8 *bssid_hint = NULL;
12209#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012210 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12211 hdd_context_t *pHddCtx;
12212
12213 ENTER();
12214
Anurag Chouhan6d760662016-02-20 16:05:43 +053012215 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012216 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012217 return -EINVAL;
12218 }
12219
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012220 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012221 TRACE_CODE_HDD_CFG80211_CONNECT,
12222 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012223 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012224 hdd_device_mode_to_string(pAdapter->device_mode),
12225 pAdapter->device_mode);
12226
Krunal Sonib4326f22016-03-10 13:05:51 -080012227 if (pAdapter->device_mode != QDF_STA_MODE &&
12228 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012229 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012230 hdd_device_mode_to_string(pAdapter->device_mode),
12231 pAdapter->device_mode);
12232 return -EINVAL;
12233 }
12234
12235 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12236 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012237 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012238 return -EINVAL;
12239 }
12240
12241 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012242 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012243 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012244
Naveen Rawat07332902016-07-27 09:13:17 -070012245 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012246 return status;
12247
Agrawal Ashishf156e942016-08-04 14:54:47 +053012248 wlan_hdd_disable_roaming(pAdapter);
12249
12250 /* Try disconnecting if already in connected state */
12251 status = wlan_hdd_try_disconnect(pAdapter);
12252 if (0 > status) {
12253 hdd_err("Failed to disconnect the existing connection");
12254 return -EALREADY;
12255 }
12256
12257 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012258 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012259 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012260 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012261 pAdapter->device_mode),
12262 req->channel->hw_value, HW_MODE_20_MHZ)) {
12263 hdd_err("This concurrency combination is not allowed");
12264 return -ECONNREFUSED;
12265 }
12266 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012267 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012268 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012269 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12270 hdd_err("This concurrency combination is not allowed");
12271 return -ECONNREFUSED;
12272 }
12273 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012274
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012275 /*initialise security parameters */
12276 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12277
12278 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012279 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012280 return status;
12281 }
12282
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012283 if (req->channel)
12284 channel = req->channel->hw_value;
12285 else
12286 channel = 0;
12287 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12288 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012289 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012290 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012291 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012292 return status;
12293 }
12294 EXIT();
12295 return status;
12296}
12297
12298/**
12299 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12300 * @wiphy: Pointer to wiphy
12301 * @dev: Pointer to network device
12302 * @req: Pointer to cfg80211 connect request
12303 *
12304 * Return: 0 for success, non-zero for failure
12305 */
12306static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12307 struct net_device *ndev,
12308 struct cfg80211_connect_params *req)
12309{
12310 int ret;
12311 cds_ssr_protect(__func__);
12312 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12313 cds_ssr_unprotect(__func__);
12314
12315 return ret;
12316}
12317
12318/**
12319 * wlan_hdd_disconnect() - hdd disconnect api
12320 * @pAdapter: Pointer to adapter
12321 * @reason: Disconnect reason code
12322 *
12323 * This function is used to issue a disconnect request to SME
12324 *
12325 * Return: 0 for success, non-zero for failure
12326 */
12327int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
12328{
12329 int status, result = 0;
12330 unsigned long rc;
12331 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12332 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12333
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012334 ENTER();
12335
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012336 status = wlan_hdd_validate_context(pHddCtx);
12337
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012338 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012339 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012340
12341 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012342 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012343 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12344 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012345 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012346 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12347 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12348
12349 /*issue disconnect */
12350
12351 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12352 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012353 /*
12354 * Wait here instead of returning directly, this will block the next
12355 * connect command and allow processing of the scan for ssid and
12356 * the previous connect command in CSR. Else we might hit some
12357 * race conditions leading to SME and HDD out of sync.
12358 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012359 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012360 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012361 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012362 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012363 (int)status);
12364 pHddStaCtx->staDebugState = status;
12365 result = -EINVAL;
12366 goto disconnected;
12367 }
12368 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12369 msecs_to_jiffies
12370 (WLAN_WAIT_TIME_DISCONNECT));
12371
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012372 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012373 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012374 result = -ETIMEDOUT;
12375 }
12376disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012377 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12378#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12379 /* Sending disconnect event to userspace for kernel version < 3.11
12380 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12381 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012382 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012383 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12384 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012385#endif
12386
12387 return result;
12388}
12389
12390/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012391 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12392 * @reason: ieee80211 reason code.
12393 *
12394 * This utility function helps log string conversion of reason code.
12395 *
12396 * Return: string conversion of reason code, if match found;
12397 * "Unknown" otherwise.
12398 */
12399static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12400{
12401 switch (reason) {
12402 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12403 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12404 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12405 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12406 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12407 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12408 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12409 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12410 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12411 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12412 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12413 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12414 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12415 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12416 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12417 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12418 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12419 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12420 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12421 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12422 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12423 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12424 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12425 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12426 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12427 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12428 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12429 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12430 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12431 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12432 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12433 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12434 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12435 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12436 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12437 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12438 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12439 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12440 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12441 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12442 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12443 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12444 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12445 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12446 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12447 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12448 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12449 default:
12450 return "Unknown";
12451 }
12452}
12453
12454/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012455 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12456 * @wiphy: Pointer to wiphy
12457 * @dev: Pointer to network device
12458 * @reason: Disconnect reason code
12459 *
12460 * This function is used to issue a disconnect request to SME
12461 *
12462 * Return: 0 for success, non-zero for failure
12463 */
12464static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12465 struct net_device *dev, u16 reason)
12466{
12467 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12468 int status;
12469 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12470 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12471#ifdef FEATURE_WLAN_TDLS
12472 uint8_t staIdx;
12473#endif
12474
12475 ENTER();
12476
Anurag Chouhan6d760662016-02-20 16:05:43 +053012477 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012478 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012479 return -EINVAL;
12480 }
12481
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012482 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012483 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12484 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012485 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012486 hdd_device_mode_to_string(pAdapter->device_mode),
12487 pAdapter->device_mode, reason);
12488
12489 status = wlan_hdd_validate_context(pHddCtx);
12490
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012491 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012492 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012493
12494 /* Issue disconnect request to SME, if station is in connected state */
12495 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12496 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12497 eCsrRoamDisconnectReason reasonCode =
12498 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12499 hdd_scaninfo_t *pScanInfo;
12500
12501 switch (reason) {
12502 case WLAN_REASON_MIC_FAILURE:
12503 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12504 break;
12505
12506 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12507 case WLAN_REASON_DISASSOC_AP_BUSY:
12508 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12509 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12510 break;
12511
12512 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12513 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12514 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12515 break;
12516
12517 case WLAN_REASON_DEAUTH_LEAVING:
12518 reasonCode =
12519 pHddCtx->config->
12520 gEnableDeauthToDisassocMap ?
12521 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12522 eCSR_DISCONNECT_REASON_DEAUTH;
12523 break;
12524 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12525 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12526 break;
12527 default:
12528 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12529 break;
12530 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012531 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012532 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012533 pScanInfo = &pAdapter->scan_info;
12534 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012535 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012536 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12537 eCSR_SCAN_ABORT_DEFAULT);
12538 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012539 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012540#ifdef FEATURE_WLAN_TDLS
12541 /* First clean up the tdls peers if any */
12542 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12543 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12544 pAdapter->sessionId)
12545 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12546 uint8_t *mac;
12547 mac =
12548 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012549 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12550 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012551 pHddCtx->tdlsConnInfo[staIdx].staId,
12552 pAdapter->sessionId,
12553 MAC_ADDR_ARRAY(mac));
12554 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12555 (pAdapter),
12556 pAdapter->sessionId, mac);
12557 }
12558 }
12559#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012560 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012561 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012562 hdd_info("Disconnect request from user space with reason: %s",
12563 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012564 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12565 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012566 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012567 return -EINVAL;
12568 }
12569 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012570 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012571 pHddStaCtx->conn_info.connState);
12572 }
12573
12574 return status;
12575}
12576
12577/**
12578 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12579 * @wiphy: Pointer to wiphy
12580 * @dev: Pointer to network device
12581 * @reason: Disconnect reason code
12582 *
12583 * Return: 0 for success, non-zero for failure
12584 */
12585static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12586 struct net_device *dev, u16 reason)
12587{
12588 int ret;
12589 cds_ssr_protect(__func__);
12590 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12591 cds_ssr_unprotect(__func__);
12592
12593 return ret;
12594}
12595
12596/**
12597 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12598 * @pAdapter: Pointer to adapter
12599 * @param: Pointer to IBSS parameters
12600 *
12601 * This function is used to initialize the security settings in IBSS mode
12602 *
12603 * Return: 0 for success, non-zero for failure
12604 */
12605static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12606 struct cfg80211_ibss_params
12607 *params)
12608{
12609 int status = 0;
12610 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12611 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12612 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12613
12614 ENTER();
12615
12616 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012617 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012618 pHddStaCtx->ibss_enc_key_installed = 0;
12619
12620 if (params->ie_len && (NULL != params->ie)) {
12621 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12622 params->ie_len, WLAN_EID_RSN)) {
12623 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12624 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12625 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
12626 tDot11fIEWPA dot11WPAIE;
12627 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12628 u8 *ie;
12629
12630 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12631 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12632 params->ie_len,
12633 DOT11F_EID_WPA);
12634 if (NULL != ie) {
12635 pWextState->wpaVersion =
12636 IW_AUTH_WPA_VERSION_WPA;
12637 /* Unpack the WPA IE */
12638 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
12639 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
12640 &ie[2 + 4],
12641 ie[1] - 4, &dot11WPAIE);
12642 /*Extract the multicast cipher, the encType for unicast
12643 cipher for wpa-none is none */
12644 encryptionType =
12645 hdd_translate_wpa_to_csr_encryption_type
12646 (dot11WPAIE.multicast_cipher);
12647 }
12648 }
12649
12650 status =
12651 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
12652 params->ie_len);
12653
12654 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012655 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012656 return status;
12657 }
12658 }
12659
12660 pWextState->roamProfile.AuthType.authType[0] =
12661 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12662
12663 if (params->privacy) {
12664 /* Security enabled IBSS, At this time there is no information
12665 * available about the security paramters, so initialise the
12666 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
12667 * The correct security parameters will be updated later in
12668 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
12669 * set inorder enable privacy bit in beacons
12670 */
12671
12672 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12673 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012674 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012675 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12676 pWextState->roamProfile.EncryptionType.numEntries = 1;
12677 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12678 encryptionType;
12679 return status;
12680}
12681
12682/**
12683 * __wlan_hdd_cfg80211_join_ibss() - join ibss
12684 * @wiphy: Pointer to wiphy
12685 * @dev: Pointer to network device
12686 * @param: Pointer to IBSS join parameters
12687 *
12688 * This function is used to create/join an IBSS network
12689 *
12690 * Return: 0 for success, non-zero for failure
12691 */
12692static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12693 struct net_device *dev,
12694 struct cfg80211_ibss_params *params)
12695{
12696 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12697 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12698 tCsrRoamProfile *pRoamProfile;
12699 int status;
12700 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12701 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053012702 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012703 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012704
12705 ENTER();
12706
Anurag Chouhan6d760662016-02-20 16:05:43 +053012707 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012708 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012709 return -EINVAL;
12710 }
12711
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012712 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012713 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
12714 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012715 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012716 hdd_device_mode_to_string(pAdapter->device_mode),
12717 pAdapter->device_mode);
12718
12719 status = wlan_hdd_validate_context(pHddCtx);
12720
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012721 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012722 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012723
12724 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053012725 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012726 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12727 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
12728 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12729 int indx;
12730
12731 /* Get channel number */
12732 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012733 params->
12734 chandef.
12735 chan->
12736 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012737
12738 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12739 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012740 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012741 return -EOPNOTSUPP;
12742 }
12743
12744 for (indx = 0; indx < numChans; indx++) {
12745 if (channelNum == validChan[indx]) {
12746 break;
12747 }
12748 }
12749 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012750 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012751 return -EINVAL;
12752 }
12753 }
12754
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012755 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012756 HW_MODE_20_MHZ)) {
12757 hdd_err("This concurrency combination is not allowed");
12758 return -ECONNREFUSED;
12759 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012760
Krunal Soni3091bcc2016-06-23 12:28:21 -070012761 status = qdf_reset_connection_update();
12762 if (!QDF_IS_STATUS_SUCCESS(status))
12763 hdd_err("ERR: clear event failed");
12764
12765 status = cds_current_connections_update(pAdapter->sessionId,
12766 channelNum,
12767 SIR_UPDATE_REASON_JOIN_IBSS);
12768 if (QDF_STATUS_E_FAILURE == status) {
12769 hdd_err("ERROR: connections update failed!!");
12770 return -EINVAL;
12771 }
12772
12773 if (QDF_STATUS_SUCCESS == status) {
12774 status = qdf_wait_for_connection_update();
12775 if (!QDF_IS_STATUS_SUCCESS(status)) {
12776 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012777 return -EINVAL;
12778 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012779 }
12780
12781 /*Try disconnecting if already in connected state */
12782 status = wlan_hdd_try_disconnect(pAdapter);
12783 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012784 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012785 return -EALREADY;
12786 }
12787
12788 pRoamProfile = &pWextState->roamProfile;
12789
12790 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012791 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012792 return -EINVAL;
12793 }
12794
12795 /* enable selected protection checks in IBSS mode */
12796 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
12797
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012798 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012799 WNI_CFG_IBSS_ATIM_WIN_SIZE,
12800 pHddCtx->config->
12801 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012802 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012803 }
12804
12805 /* BSSID is provided by upper layers hence no need to AUTO generate */
12806 if (NULL != params->bssid) {
12807 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012808 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012809 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012810 return -EIO;
12811 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012812 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012813 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
12814 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012815 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012816 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012817 return -EIO;
12818 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053012819 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012820 }
12821 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
12822 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
12823 pRoamProfile->beaconInterval = params->beacon_interval;
12824 else {
12825 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012826 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012827 params->beacon_interval, pRoamProfile->beaconInterval);
12828 }
12829
12830 /* Set Channel */
12831 if (channelNum) {
12832 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012833 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012834 pRoamProfile->ChannelInfo.numOfChannels = 1;
12835 pHddStaCtx->conn_info.operationChannel = channelNum;
12836 pRoamProfile->ChannelInfo.ChannelList =
12837 &pHddStaCtx->conn_info.operationChannel;
12838 }
12839
12840 /* Initialize security parameters */
12841 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
12842 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012843 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012844 return status;
12845 }
12846
12847 /* Issue connect start */
12848 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
12849 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012850 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012851 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012852 operationChannel,
12853 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012854
12855 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012856 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012857 return status;
12858 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012859 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012860 return 0;
12861}
12862
12863/**
12864 * wlan_hdd_cfg80211_join_ibss() - join ibss
12865 * @wiphy: Pointer to wiphy
12866 * @dev: Pointer to network device
12867 * @param: Pointer to IBSS join parameters
12868 *
12869 * This function is used to create/join an IBSS network
12870 *
12871 * Return: 0 for success, non-zero for failure
12872 */
12873static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12874 struct net_device *dev,
12875 struct cfg80211_ibss_params *params)
12876{
12877 int ret = 0;
12878
12879 cds_ssr_protect(__func__);
12880 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
12881 cds_ssr_unprotect(__func__);
12882
12883 return ret;
12884}
12885
12886/**
12887 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
12888 * @wiphy: Pointer to wiphy
12889 * @dev: Pointer to network device
12890 *
12891 * This function is used to leave an IBSS network
12892 *
12893 * Return: 0 for success, non-zero for failure
12894 */
12895static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
12896 struct net_device *dev)
12897{
12898 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12899 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12900 tCsrRoamProfile *pRoamProfile;
12901 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12902 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012903 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053012904 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012905 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012906
12907 ENTER();
12908
Anurag Chouhan6d760662016-02-20 16:05:43 +053012909 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012910 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012911 return -EINVAL;
12912 }
12913
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012914 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012915 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
12916 pAdapter->sessionId,
12917 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
12918 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012919 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012920 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012921
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012922 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012923 hdd_device_mode_to_string(pAdapter->device_mode),
12924 pAdapter->device_mode);
12925 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012926 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012927 return -EIO;
12928 }
12929
12930 pRoamProfile = &pWextState->roamProfile;
12931
12932 /* Issue disconnect only if interface type is set to IBSS */
12933 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012934 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012935 return -EINVAL;
12936 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012937 /* Clearing add IE of beacon */
12938 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
12939 sizeof(tSirMacAddr));
12940 updateIE.smeSessionId = pAdapter->sessionId;
12941 updateIE.ieBufferlength = 0;
12942 updateIE.pAdditionIEBuffer = NULL;
12943 updateIE.append = true;
12944 updateIE.notify = true;
12945 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
12946 &updateIE,
12947 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012948 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012949 }
12950
12951 /* Reset WNI_CFG_PROBE_RSP Flags */
12952 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012953
12954 /* Issue Disconnect request */
12955 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12956 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12957 pAdapter->sessionId,
12958 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012959 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012960 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012961 hal_status);
12962 return -EAGAIN;
12963 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053012964
12965 /* wait for mc thread to cleanup and then return to upper stack
12966 * so by the time upper layer calls the change interface, we are
12967 * all set to proceed further
12968 */
12969 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12970 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
12971 if (!rc) {
12972 hdd_err("Failed to disconnect, timed out");
12973 return -ETIMEDOUT;
12974 }
12975
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012976 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012977 return 0;
12978}
12979
12980/**
12981 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
12982 * @wiphy: Pointer to wiphy
12983 * @dev: Pointer to network device
12984 *
12985 * This function is used to leave an IBSS network
12986 *
12987 * Return: 0 for success, non-zero for failure
12988 */
12989static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
12990 struct net_device *dev)
12991{
12992 int ret = 0;
12993
12994 cds_ssr_protect(__func__);
12995 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
12996 cds_ssr_unprotect(__func__);
12997
12998 return ret;
12999}
13000
13001/**
13002 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13003 * @wiphy: Pointer to wiphy
13004 * @changed: Parameters changed
13005 *
13006 * This function is used to set the phy parameters. RTS Threshold/FRAG
13007 * Threshold/Retry Count etc.
13008 *
13009 * Return: 0 for success, non-zero for failure
13010 */
13011static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13012 u32 changed)
13013{
13014 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13015 tHalHandle hHal = pHddCtx->hHal;
13016 int status;
13017
13018 ENTER();
13019
Anurag Chouhan6d760662016-02-20 16:05:43 +053013020 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013021 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013022 return -EINVAL;
13023 }
13024
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013025 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013026 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13027 NO_SESSION, wiphy->rts_threshold));
13028 status = wlan_hdd_validate_context(pHddCtx);
13029
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013030 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013031 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013032
13033 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13034 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13035 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13036
13037 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13038 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013039 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013040 rts_threshold);
13041 return -EINVAL;
13042 }
13043
13044 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13045 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013046 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013047 rts_threshold);
13048 return -EIO;
13049 }
13050
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013051 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013052 }
13053
13054 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13055 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13056 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13057 wiphy->frag_threshold;
13058
13059 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13060 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013061 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013062 frag_threshold);
13063 return -EINVAL;
13064 }
13065
13066 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13067 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013068 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013069 frag_threshold);
13070 return -EIO;
13071 }
13072
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013073 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013074 }
13075
13076 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13077 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13078 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13079 wiphy->retry_short : wiphy->retry_long;
13080
13081 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13082 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013083 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013084 return -EINVAL;
13085 }
13086
13087 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13088 if (0 != sme_cfg_set_int(hHal,
13089 WNI_CFG_LONG_RETRY_LIMIT,
13090 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013091 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013092 retry_value);
13093 return -EIO;
13094 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013095 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013096 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13097 if (0 != sme_cfg_set_int(hHal,
13098 WNI_CFG_SHORT_RETRY_LIMIT,
13099 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013100 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013101 retry_value);
13102 return -EIO;
13103 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013104 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013105 }
13106 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013107 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013108 return 0;
13109}
13110
13111/**
13112 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13113 * @wiphy: Pointer to wiphy
13114 * @changed: Parameters changed
13115 *
13116 * Return: 0 for success, non-zero for failure
13117 */
13118static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13119{
13120 int ret;
13121
13122 cds_ssr_protect(__func__);
13123 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13124 cds_ssr_unprotect(__func__);
13125
13126 return ret;
13127}
13128
13129/**
13130 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13131 * key
13132 * @wiphy: Pointer to wiphy
13133 * @dev: Pointer to network device
13134 * @key_index: Key index
13135 *
13136 * Return: 0
13137 */
13138static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13139 struct net_device *netdev,
13140 u8 key_index)
13141{
13142 ENTER();
13143 return 0;
13144}
13145
13146/**
13147 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13148 * wlan_hdd_set_default_mgmt_key
13149 * @wiphy: pointer to wiphy
13150 * @netdev: pointer to net_device structure
13151 * @key_index: key index
13152 *
13153 * Return: 0 on success, error number on failure
13154 */
13155static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13156 struct net_device *netdev,
13157 u8 key_index)
13158{
13159 int ret;
13160
13161 cds_ssr_protect(__func__);
13162 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13163 cds_ssr_unprotect(__func__);
13164
13165 return ret;
13166}
13167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013168/**
13169 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13170 * @wiphy: Pointer to wiphy
13171 * @dev: Pointer to network device
13172 * @params: Pointer to tx queue parameters
13173 *
13174 * Return: 0
13175 */
13176static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13177 struct net_device *dev,
13178 struct ieee80211_txq_params *params)
13179{
13180 ENTER();
13181 return 0;
13182}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013183
13184/**
13185 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13186 * @wiphy: pointer to wiphy
13187 * @netdev: pointer to net_device structure
13188 * @params: pointer to ieee80211_txq_params
13189 *
13190 * Return: 0 on success, error number on failure
13191 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013192static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13193 struct net_device *dev,
13194 struct ieee80211_txq_params *params)
13195{
13196 int ret;
13197
13198 cds_ssr_protect(__func__);
13199 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13200 cds_ssr_unprotect(__func__);
13201
13202 return ret;
13203}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013204
13205/**
13206 * __wlan_hdd_cfg80211_del_station() - delete station v2
13207 * @wiphy: Pointer to wiphy
13208 * @param: Pointer to delete station parameter
13209 *
13210 * Return: 0 for success, non-zero for failure
13211 */
13212static
13213int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13214 struct net_device *dev,
13215 struct tagCsrDelStaParams *pDelStaParams)
13216{
13217 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13218 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013219 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013220 hdd_hostapd_state_t *hapd_state;
13221 int status;
13222 uint8_t staId;
13223 uint8_t *mac;
13224
13225 ENTER();
13226
Anurag Chouhan6d760662016-02-20 16:05:43 +053013227 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013228 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013229 return -EINVAL;
13230 }
13231
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013232 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233 TRACE_CODE_HDD_CFG80211_DEL_STA,
13234 pAdapter->sessionId, pAdapter->device_mode));
13235
13236 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13237 status = wlan_hdd_validate_context(pHddCtx);
13238
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013239 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013240 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013241
13242 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13243
Krunal Sonib4326f22016-03-10 13:05:51 -080013244 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13245 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013246
13247 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13248 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013249 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013250 return 0;
13251 }
13252
Anurag Chouhanc5548422016-02-24 18:33:27 +053013253 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013254 uint16_t i;
13255 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13256 if ((pAdapter->aStaInfo[i].isUsed) &&
13257 (!pAdapter->aStaInfo[i].
13258 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013259 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013260 mac,
13261 pAdapter->aStaInfo[i].
13262 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013263 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013264 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13265 hdd_ipa_wlan_evt(pAdapter,
13266 pAdapter->
13267 aStaInfo[i].
13268 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013269 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013270 mac);
13271 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013272 hdd_notice("Delete STA with MAC::"
13273 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013274 MAC_ADDR_ARRAY(mac));
13275
13276 if (pHddCtx->dev_dfs_cac_status ==
13277 DFS_CAC_IN_PROGRESS)
13278 goto fn_end;
13279
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013280 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013281 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013282 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013283 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013284 hdd_softap_sta_deauth(pAdapter,
13285 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013286 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013287 pAdapter->aStaInfo[i].
13288 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013289 qdf_status =
13290 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013291 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013292 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013293 if (!QDF_IS_STATUS_SUCCESS(
13294 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013295 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013296 }
13297 }
13298 }
13299 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013300 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013301 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013302 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013303 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013304 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013305 hdd_notice("Skip DEL STA as this is not used::"
13306 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013307 MAC_ADDR_ARRAY(mac));
13308 return -ENOENT;
13309 }
13310
13311 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13312 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013313 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013314 }
13315
13316 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13317 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013318 hdd_notice("Skip DEL STA as deauth is in progress::"
13319 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013320 MAC_ADDR_ARRAY(mac));
13321 return -ENOENT;
13322 }
13323
13324 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13325
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013326 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013327 MAC_ADDR_ARRAY(mac));
13328
13329 /* Case: SAP in ACS selected DFS ch and client connected
13330 * Now Radar detected. Then if random channel is another
13331 * DFS ch then new CAC is initiated and no TX allowed.
13332 * So do not send any mgmt frames as it will timeout
13333 * during CAC.
13334 */
13335
13336 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13337 goto fn_end;
13338
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013339 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013340 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13341 (pAdapter), pAdapter->sessionId,
13342 (uint8_t *)&pDelStaParams->peerMacAddr,
13343 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013344 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013345 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013346 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013347 pAdapter->aStaInfo[staId].isDeauthInProgress =
13348 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013349 hdd_notice("STA removal failed for ::"
13350 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013351 MAC_ADDR_ARRAY(mac));
13352 return -ENOENT;
13353 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013354 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013355 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013356 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013357 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013358 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013359 }
13360 }
13361 }
13362
13363fn_end:
13364 EXIT();
13365 return 0;
13366}
13367
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013368#if defined(USE_CFG80211_DEL_STA_V2)
13369/**
13370 * wlan_hdd_del_station() - delete station wrapper
13371 * @adapter: pointer to the hdd adapter
13372 *
13373 * Return: None
13374 */
13375void wlan_hdd_del_station(hdd_adapter_t *adapter)
13376{
13377 struct station_del_parameters del_sta;
13378 del_sta.mac = NULL;
13379 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13380 del_sta.reason_code = eCsrForcedDeauthSta;
13381
13382 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13383 &del_sta);
13384}
13385#else
13386void wlan_hdd_del_station(hdd_adapter_t *adapter)
13387{
13388 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13389}
13390#endif
13391
13392#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013393/**
13394 * wlan_hdd_cfg80211_del_station() - delete station v2
13395 * @wiphy: Pointer to wiphy
13396 * @param: Pointer to delete station parameter
13397 *
13398 * Return: 0 for success, non-zero for failure
13399 */
13400int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13401 struct net_device *dev,
13402 struct station_del_parameters *param)
13403#else
13404/**
13405 * wlan_hdd_cfg80211_del_station() - delete station
13406 * @wiphy: Pointer to wiphy
13407 * @mac: Pointer to station mac address
13408 *
13409 * Return: 0 for success, non-zero for failure
13410 */
13411#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13412int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13413 struct net_device *dev,
13414 const uint8_t *mac)
13415#else
13416int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13417 struct net_device *dev,
13418 uint8_t *mac)
13419#endif
13420#endif
13421{
13422 int ret;
13423 struct tagCsrDelStaParams delStaParams;
13424
13425 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013426#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013427 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013428 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013429 return -EINVAL;
13430 }
13431 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13432 param->subtype, &delStaParams);
13433#else
13434 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13435 (SIR_MAC_MGMT_DEAUTH >> 4),
13436 &delStaParams);
13437#endif
13438 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13439 cds_ssr_unprotect(__func__);
13440
13441 return ret;
13442}
13443
13444/**
13445 * __wlan_hdd_cfg80211_add_station() - add station
13446 * @wiphy: Pointer to wiphy
13447 * @mac: Pointer to station mac address
13448 * @pmksa: Pointer to add station parameter
13449 *
13450 * Return: 0 for success, non-zero for failure
13451 */
13452static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13453 struct net_device *dev,
13454 const uint8_t *mac,
13455 struct station_parameters *params)
13456{
13457 int status = -EPERM;
13458#ifdef FEATURE_WLAN_TDLS
13459 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13460 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13461 u32 mask, set;
13462
13463 ENTER();
13464
Anurag Chouhan6d760662016-02-20 16:05:43 +053013465 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013466 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013467 return -EINVAL;
13468 }
13469
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013470 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013471 TRACE_CODE_HDD_CFG80211_ADD_STA,
13472 pAdapter->sessionId, params->listen_interval));
13473
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013474 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013475 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013476
13477 mask = params->sta_flags_mask;
13478
13479 set = params->sta_flags_set;
13480
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013481 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013482 MAC_ADDR_ARRAY(mac));
13483
13484 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13485 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13486 status =
13487 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13488 }
13489 }
13490#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013491 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013492 return status;
13493}
13494
13495/**
13496 * wlan_hdd_cfg80211_add_station() - add station
13497 * @wiphy: Pointer to wiphy
13498 * @mac: Pointer to station mac address
13499 * @pmksa: Pointer to add station parameter
13500 *
13501 * Return: 0 for success, non-zero for failure
13502 */
13503#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13504static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13505 struct net_device *dev,
13506 const uint8_t *mac,
13507 struct station_parameters *params)
13508#else
13509static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13510 struct net_device *dev, uint8_t *mac,
13511 struct station_parameters *params)
13512#endif
13513{
13514 int ret;
13515
13516 cds_ssr_protect(__func__);
13517 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13518 cds_ssr_unprotect(__func__);
13519
13520 return ret;
13521}
13522
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013523/**
13524 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13525 * @wiphy: Pointer to wiphy
13526 * @dev: Pointer to network device
13527 * @pmksa: Pointer to set pmksa parameter
13528 *
13529 * Return: 0 for success, non-zero for failure
13530 */
13531static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13532 struct net_device *dev,
13533 struct cfg80211_pmksa *pmksa)
13534{
13535 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13536 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13537 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013538 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013539 int status;
13540 tPmkidCacheInfo pmk_id;
13541
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013542 ENTER();
13543
Anurag Chouhan6d760662016-02-20 16:05:43 +053013544 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013545 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013546 return -EINVAL;
13547 }
13548
13549 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013550 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013551 return -EINVAL;
13552 }
13553
13554 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013555 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013556 pmksa->bssid, pmksa->pmkid);
13557 return -EINVAL;
13558 }
13559
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013560 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013561 MAC_ADDR_ARRAY(pmksa->bssid));
13562
13563 status = wlan_hdd_validate_context(pHddCtx);
13564
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013565 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013566 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013567
13568 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13569
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013570 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13571 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013572
13573 /* Add to the PMKSA ID Cache in CSR */
13574 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13575 &pmk_id, 1, false);
13576
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013577 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013578 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
13579 pAdapter->sessionId, result));
13580
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013581 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013582 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013583}
13584
13585/**
13586 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13587 * @wiphy: Pointer to wiphy
13588 * @dev: Pointer to network device
13589 * @pmksa: Pointer to set pmksa parameter
13590 *
13591 * Return: 0 for success, non-zero for failure
13592 */
13593static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13594 struct net_device *dev,
13595 struct cfg80211_pmksa *pmksa)
13596{
13597 int ret;
13598
13599 cds_ssr_protect(__func__);
13600 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
13601 cds_ssr_unprotect(__func__);
13602
13603 return ret;
13604}
13605
13606/**
13607 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13608 * @wiphy: Pointer to wiphy
13609 * @dev: Pointer to network device
13610 * @pmksa: Pointer to pmksa parameter
13611 *
13612 * Return: 0 for success, non-zero for failure
13613 */
13614static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13615 struct net_device *dev,
13616 struct cfg80211_pmksa *pmksa)
13617{
13618 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13619 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13620 tHalHandle halHandle;
13621 int status = 0;
13622
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013623 ENTER();
13624
Anurag Chouhan6d760662016-02-20 16:05:43 +053013625 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013626 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013627 return -EINVAL;
13628 }
13629
13630 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013631 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013632 return -EINVAL;
13633 }
13634
13635 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013636 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013637 return -EINVAL;
13638 }
13639
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013640 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013641 MAC_ADDR_ARRAY(pmksa->bssid));
13642
13643 status = wlan_hdd_validate_context(pHddCtx);
13644
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013645 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013646 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013647
13648 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13649
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013650 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053013651 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
13652 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013653 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013654 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013655 sme_roam_del_pmkid_from_cache(halHandle,
13656 pAdapter->sessionId, pmksa->bssid,
13657 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013658 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013659 MAC_ADDR_ARRAY(pmksa->bssid));
13660 status = -EINVAL;
13661 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013662 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013663 return status;
13664}
13665
13666/**
13667 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13668 * @wiphy: Pointer to wiphy
13669 * @dev: Pointer to network device
13670 * @pmksa: Pointer to pmksa parameter
13671 *
13672 * Return: 0 for success, non-zero for failure
13673 */
13674static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13675 struct net_device *dev,
13676 struct cfg80211_pmksa *pmksa)
13677{
13678 int ret;
13679
13680 cds_ssr_protect(__func__);
13681 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
13682 cds_ssr_unprotect(__func__);
13683
13684 return ret;
13685
13686}
13687
13688/**
13689 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13690 * @wiphy: Pointer to wiphy
13691 * @dev: Pointer to network device
13692 *
13693 * Return: 0 for success, non-zero for failure
13694 */
13695static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13696 struct net_device *dev)
13697{
13698 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13699 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13700 tHalHandle halHandle;
13701 int status = 0;
13702
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013703 ENTER();
13704
Anurag Chouhan6d760662016-02-20 16:05:43 +053013705 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013706 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013707 return -EINVAL;
13708 }
13709
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013710 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013711
13712 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13713 status = wlan_hdd_validate_context(pHddCtx);
13714
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013715 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013716 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013717
13718 /* Retrieve halHandle */
13719 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13720
13721 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013722 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013723 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
13724 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013725 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013726 status = -EINVAL;
13727 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013728 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013729 return status;
13730}
13731
13732/**
13733 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13734 * @wiphy: Pointer to wiphy
13735 * @dev: Pointer to network device
13736 *
13737 * Return: 0 for success, non-zero for failure
13738 */
13739static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13740 struct net_device *dev)
13741{
13742 int ret;
13743
13744 cds_ssr_protect(__func__);
13745 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
13746 cds_ssr_unprotect(__func__);
13747
13748 return ret;
13749}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013750
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080013751#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013752/**
13753 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13754 * @wiphy: Pointer to wiphy
13755 * @dev: Pointer to network device
13756 * @ftie: Pointer to fast transition ie parameter
13757 *
13758 * Return: 0 for success, non-zero for failure
13759 */
13760static int
13761__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13762 struct net_device *dev,
13763 struct cfg80211_update_ft_ies_params *ftie)
13764{
13765 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
13766 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13767 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13768 int status;
13769
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013770 ENTER();
13771
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013772 status = wlan_hdd_validate_context(hdd_ctx);
13773 if (status)
13774 return status;
13775
Anurag Chouhan6d760662016-02-20 16:05:43 +053013776 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013777 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013778 return -EINVAL;
13779 }
13780
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013781 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013782 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
13783 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
13784 /* Added for debug on reception of Re-assoc Req. */
13785 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013786 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013787 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013788 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013789 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013790 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013791 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013792
13793 /* Pass the received FT IEs to SME */
13794 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
13795 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013796 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013797 return 0;
13798}
13799
13800/**
13801 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13802 * @wiphy: Pointer to wiphy
13803 * @dev: Pointer to network device
13804 * @ftie: Pointer to fast transition ie parameter
13805 *
13806 * Return: 0 for success, non-zero for failure
13807 */
13808static int
13809wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13810 struct net_device *dev,
13811 struct cfg80211_update_ft_ies_params *ftie)
13812{
13813 int ret;
13814
13815 cds_ssr_protect(__func__);
13816 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
13817 cds_ssr_unprotect(__func__);
13818
13819 return ret;
13820}
13821#endif
13822
13823#ifdef WLAN_FEATURE_GTK_OFFLOAD
13824/**
13825 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
13826 * @callbackContext: Callback context
13827 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
13828 *
13829 * Callback rountine called upon receiving response for get offload info
13830 *
13831 * Return: none
13832 */
13833void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
13834 tpSirGtkOffloadGetInfoRspParams
13835 pGtkOffloadGetInfoRsp)
13836{
13837 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
13838 uint8_t tempReplayCounter[8];
13839 hdd_station_ctx_t *pHddStaCtx;
13840
13841 ENTER();
13842
13843 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013844 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013845 return;
13846 }
13847
13848 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013849 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013850 return;
13851 }
13852
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013853 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013854 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013855 return;
13856 }
13857
13858 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13859 /* Update replay counter */
13860 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
13861 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13862
13863 {
13864 /* changing from little to big endian since supplicant
13865 * works on big endian format
13866 */
13867 int i;
13868 uint8_t *p =
13869 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13870
13871 for (i = 0; i < 8; i++) {
13872 tempReplayCounter[7 - i] = (uint8_t) p[i];
13873 }
13874 }
13875
13876 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080013877 cfg80211_gtk_rekey_notify(pAdapter->dev,
13878 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013879 tempReplayCounter, GFP_KERNEL);
13880}
13881
13882/**
13883 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
13884 * @wiphy: Pointer to wiphy
13885 * @dev: Pointer to network device
13886 * @data: Pointer to rekey data
13887 *
13888 * This function is used to offload GTK rekeying job to the firmware.
13889 *
13890 * Return: 0 for success, non-zero for failure
13891 */
13892int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
13893 struct net_device *dev,
13894 struct cfg80211_gtk_rekey_data *data)
13895{
13896 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13897 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13898 hdd_station_ctx_t *pHddStaCtx;
13899 tHalHandle hHal;
13900 int result;
13901 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013902 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013903
13904 ENTER();
13905
Anurag Chouhan6d760662016-02-20 16:05:43 +053013906 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013907 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013908 return -EINVAL;
13909 }
13910
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013911 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013912 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
13913 pAdapter->sessionId, pAdapter->device_mode));
13914
13915 result = wlan_hdd_validate_context(pHddCtx);
13916
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013917 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013918 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013919
13920 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13921 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13922 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013923 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013924 return -EAGAIN;
13925 }
13926
13927 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
13928 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
13929 NL80211_KCK_LEN);
13930 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
13931 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053013932 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080013933 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013934 {
13935 /* changing from big to little endian since driver
13936 * works on little endian format
13937 */
13938 uint8_t *p =
13939 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
13940 ullKeyReplayCounter;
13941 int i;
13942
13943 for (i = 0; i < 8; i++) {
13944 p[7 - i] = data->replay_ctr[i];
13945 }
13946 }
13947
13948 if (true == pHddCtx->hdd_wlan_suspended) {
13949 /* if wlan is suspended, enable GTK offload directly from here */
13950 memcpy(&hddGtkOffloadReqParams,
13951 &pHddStaCtx->gtkOffloadReqParams,
13952 sizeof(tSirGtkOffloadParams));
13953 status =
13954 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
13955 pAdapter->sessionId);
13956
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013957 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013958 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013959 status);
13960 return -EINVAL;
13961 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013962 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013963 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013964 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013965 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013966 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013967 return result;
13968}
13969
13970/**
13971 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
13972 * @wiphy: Pointer to wiphy
13973 * @dev: Pointer to network device
13974 * @data: Pointer to rekey data
13975 *
13976 * This function is used to offload GTK rekeying job to the firmware.
13977 *
13978 * Return: 0 for success, non-zero for failure
13979 */
13980int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
13981 struct net_device *dev,
13982 struct cfg80211_gtk_rekey_data *data)
13983{
13984 int ret;
13985
13986 cds_ssr_protect(__func__);
13987 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
13988 cds_ssr_unprotect(__func__);
13989
13990 return ret;
13991}
13992#endif /*WLAN_FEATURE_GTK_OFFLOAD */
13993
13994/**
13995 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
13996 * @wiphy: Pointer to wiphy
13997 * @dev: Pointer to network device
13998 * @param: Pointer to access control parameter
13999 *
14000 * Return: 0 for success, non-zero for failure
14001 */
14002static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14003 struct net_device *dev,
14004 const struct cfg80211_acl_data *params)
14005{
14006 int i;
14007 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14008 hdd_hostapd_state_t *pHostapdState;
14009 tsap_Config_t *pConfig;
14010 v_CONTEXT_t p_cds_context = NULL;
14011 hdd_context_t *pHddCtx;
14012 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014013 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014014
14015 ENTER();
14016
Anurag Chouhan6d760662016-02-20 16:05:43 +053014017 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014018 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014019 return -EINVAL;
14020 }
14021
14022 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014023 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014024 return -EINVAL;
14025 }
14026
14027 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14028 status = wlan_hdd_validate_context(pHddCtx);
14029
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014030 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014031 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014032
14033 p_cds_context = pHddCtx->pcds_context;
14034 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14035
14036 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014037 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014038 return -EINVAL;
14039 }
14040
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014041 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014042 params->n_acl_entries);
14043
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014044 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014045 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14046 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014047 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014048 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14049
14050 /* default value */
14051 pConfig->num_accept_mac = 0;
14052 pConfig->num_deny_mac = 0;
14053
14054 /**
14055 * access control policy
14056 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14057 * listed in hostapd.deny file.
14058 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14059 * listed in hostapd.accept file.
14060 */
14061 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14062 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14063 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14064 params->acl_policy) {
14065 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14066 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014067 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014068 params->acl_policy);
14069 return -ENOTSUPP;
14070 }
14071
14072 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14073 pConfig->num_accept_mac = params->n_acl_entries;
14074 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014075 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14076 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014077 MAC_ADDR_ARRAY(
14078 params->mac_addrs[i].addr));
14079
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014080 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014081 params->mac_addrs[i].addr,
14082 sizeof(qcmacaddr));
14083 }
14084 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14085 pConfig->num_deny_mac = params->n_acl_entries;
14086 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014087 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14088 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014089 MAC_ADDR_ARRAY(
14090 params->mac_addrs[i].addr));
14091
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014092 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014093 params->mac_addrs[i].addr,
14094 sizeof(qcmacaddr));
14095 }
14096 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014097 qdf_status = wlansap_set_mac_acl(
14098 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014099 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014100 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014101 return -EINVAL;
14102 }
14103 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014104 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014105 hdd_device_mode_to_string(pAdapter->device_mode),
14106 pAdapter->device_mode);
14107 return -EINVAL;
14108 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014109 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014110 return 0;
14111}
14112
14113/**
14114 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14115 * __wlan_hdd_cfg80211_set_mac_acl
14116 * @wiphy: pointer to wiphy structure
14117 * @dev: pointer to net_device
14118 * @params: pointer to cfg80211_acl_data
14119 *
14120 * Return; 0 on success, error number otherwise
14121 */
14122static int
14123wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14124 struct net_device *dev,
14125 const struct cfg80211_acl_data *params)
14126{
14127 int ret;
14128
14129 cds_ssr_protect(__func__);
14130 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14131 cds_ssr_unprotect(__func__);
14132
14133 return ret;
14134}
14135
14136#ifdef WLAN_NL80211_TESTMODE
14137#ifdef FEATURE_WLAN_LPHB
14138/**
14139 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14140 * @pHddCtx: Pointer to hdd context
14141 * @lphbInd: Pointer to low power heart beat indication parameter
14142 *
14143 * Return: none
14144 */
14145void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx, tSirLPHBInd *lphbInd)
14146{
14147 struct sk_buff *skb;
14148
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014149 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014150
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014151 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014152 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014153
14154 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014155 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014156 return;
14157 }
14158
14159 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14160 wiphy, sizeof(tSirLPHBInd),
14161 GFP_ATOMIC);
14162 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014163 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014164 return;
14165 }
14166
14167 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014168 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014169 goto nla_put_failure;
14170 }
14171 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014172 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014173 goto nla_put_failure;
14174 }
14175 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014176 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014177 goto nla_put_failure;
14178 }
14179 cfg80211_testmode_event(skb, GFP_ATOMIC);
14180 return;
14181
14182nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014183 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014184 kfree_skb(skb);
14185
14186 return;
14187}
14188#endif /* FEATURE_WLAN_LPHB */
14189
14190/**
14191 * __wlan_hdd_cfg80211_testmode() - test mode
14192 * @wiphy: Pointer to wiphy
14193 * @data: Data pointer
14194 * @len: Data length
14195 *
14196 * Return: 0 for success, non-zero for failure
14197 */
14198static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14199 void *data, int len)
14200{
14201 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14202 int err;
14203 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14204
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014205 ENTER();
14206
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014207 err = wlan_hdd_validate_context(pHddCtx);
14208 if (err)
14209 return err;
14210
14211 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14212 len, wlan_hdd_tm_policy);
14213 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014214 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014215 return err;
14216 }
14217
14218 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014219 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014220 return -EINVAL;
14221 }
14222
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014223 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014224 TRACE_CODE_HDD_CFG80211_TESTMODE,
14225 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014226 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14227#ifdef FEATURE_WLAN_LPHB
14228 /* Low Power Heartbeat configuration request */
14229 case WLAN_HDD_TM_CMD_WLAN_HB:
14230 {
14231 int buf_len;
14232 void *buf;
14233 tSirLPHBReq *hb_params = NULL;
14234 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014235 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014236
14237 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014238 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014239 return -EINVAL;
14240 }
14241
14242 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14243 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14244
14245 hb_params_temp = (tSirLPHBReq *) buf;
14246 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14247 && (hb_params_temp->params.lphbTcpParamReq.
14248 timePeriodSec == 0))
14249 return -EINVAL;
14250
14251 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014252 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014253 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014254 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014255 return -ENOMEM;
14256 }
14257
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014258 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014259 smeStatus =
14260 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14261 hb_params,
14262 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014263 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014264 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014265 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014266 }
14267 return 0;
14268 }
14269#endif /* FEATURE_WLAN_LPHB */
14270
14271#if defined(QCA_WIFI_FTM)
14272 case WLAN_HDD_TM_CMD_WLAN_FTM:
14273 {
14274 int buf_len;
14275 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014276 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014277 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014278 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014279 return -EINVAL;
14280 }
14281
14282 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14283 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14284
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014285 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014286
14287 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14288
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014289 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014290 err = -EBUSY;
14291 break;
14292 }
14293#endif
14294
14295 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014296 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014297 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14298 return -EOPNOTSUPP;
14299 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014300 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014301 return err;
14302}
14303
14304/**
14305 * wlan_hdd_cfg80211_testmode() - test mode
14306 * @wiphy: Pointer to wiphy
14307 * @dev: Pointer to network device
14308 * @data: Data pointer
14309 * @len: Data length
14310 *
14311 * Return: 0 for success, non-zero for failure
14312 */
14313static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14314#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14315 struct wireless_dev *wdev,
14316#endif
14317 void *data, int len)
14318{
14319 int ret;
14320
14321 cds_ssr_protect(__func__);
14322 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14323 cds_ssr_unprotect(__func__);
14324
14325 return ret;
14326}
14327
14328#if defined(QCA_WIFI_FTM)
14329/**
14330 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14331 * @buf: Pointer to buffer
14332 * @buf_len: Buffer length
14333 *
14334 * Return: none
14335 */
14336void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14337{
14338 struct sk_buff *skb;
14339 hdd_context_t *hdd_ctx;
14340
14341 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014342 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014343 return;
14344 }
14345
Anurag Chouhan6d760662016-02-20 16:05:43 +053014346 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014348 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014349 return;
14350 }
14351
14352 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14353 buf_len, GFP_KERNEL);
14354 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014355 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014356 return;
14357 }
14358
14359 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14360 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14361 goto nla_put_failure;
14362
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014363 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014364
14365 cfg80211_testmode_event(skb, GFP_KERNEL);
14366 return;
14367
14368nla_put_failure:
14369 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014370 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014371}
14372#endif
14373#endif /* CONFIG_NL80211_TESTMODE */
14374
14375#ifdef QCA_HT_2040_COEX
14376/**
14377 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14378 * @wiphy: Pointer to wiphy
14379 * @dev: Pointer to network device
14380 * @chandef: Pointer to channel definition parameter
14381 *
14382 * Return: 0 for success, non-zero for failure
14383 */
14384static int
14385__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14386 struct net_device *dev,
14387 struct cfg80211_chan_def *chandef)
14388{
14389 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14390 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014391 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014392 tSmeConfigParams sme_config;
14393 bool cbModeChange;
14394
Anurag Chouhan6d760662016-02-20 16:05:43 +053014395 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014396 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014397 return -EINVAL;
14398 }
14399
14400 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14401 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014402 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014403 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014404
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014405 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014406 sme_get_config_param(pHddCtx->hHal, &sme_config);
14407 switch (chandef->width) {
14408 case NL80211_CHAN_WIDTH_20:
14409 if (sme_config.csrConfig.channelBondingMode24GHz !=
14410 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14411 sme_config.csrConfig.channelBondingMode24GHz =
14412 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14413 sme_update_config(pHddCtx->hHal, &sme_config);
14414 cbModeChange = true;
14415 }
14416 break;
14417
14418 case NL80211_CHAN_WIDTH_40:
14419 if (sme_config.csrConfig.channelBondingMode24GHz ==
14420 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14421 if (NL80211_CHAN_HT40MINUS ==
14422 cfg80211_get_chandef_type(chandef))
14423 sme_config.csrConfig.channelBondingMode24GHz =
14424 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14425 else
14426 sme_config.csrConfig.channelBondingMode24GHz =
14427 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14428 sme_update_config(pHddCtx->hHal, &sme_config);
14429 cbModeChange = true;
14430 }
14431 break;
14432
14433 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014434 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014435 return -EINVAL;
14436 }
14437
14438 if (!cbModeChange)
14439 return 0;
14440
Krunal Sonib4326f22016-03-10 13:05:51 -080014441 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014442 return 0;
14443
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014444 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014445 sme_config.csrConfig.channelBondingMode24GHz);
14446
14447 /* Change SAP ht2040 mode */
14448 status = hdd_set_sap_ht2040_mode(pAdapter,
14449 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014450 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014451 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014452 return -EINVAL;
14453 }
14454
14455 return 0;
14456}
14457
14458/**
14459 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14460 * @wiphy: Pointer to wiphy
14461 * @dev: Pointer to network device
14462 * @chandef: Pointer to channel definition parameter
14463 *
14464 * Return: 0 for success, non-zero for failure
14465 */
14466static int
14467wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14468 struct net_device *dev,
14469 struct cfg80211_chan_def *chandef)
14470{
14471 int ret;
14472
14473 cds_ssr_protect(__func__);
14474 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14475 cds_ssr_unprotect(__func__);
14476
14477 return ret;
14478}
14479#endif
14480
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014481#ifdef CHANNEL_SWITCH_SUPPORTED
14482/**
14483 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14484 * channel in SAP/GO
14485 * @wiphy: wiphy pointer
14486 * @dev: dev pointer.
14487 * @csa_params: Change channel params
14488 *
14489 * This function is called to switch channel in SAP/GO
14490 *
14491 * Return: 0 if success else return non zero
14492 */
14493static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14494 struct net_device *dev,
14495 struct cfg80211_csa_settings *csa_params)
14496{
14497 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14498 hdd_context_t *hdd_ctx;
14499 uint8_t channel;
14500 uint16_t freq;
14501 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014502 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014503
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014504 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014505 csa_params->chandef.chan->center_freq);
14506
14507 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14508 ret = wlan_hdd_validate_context(hdd_ctx);
14509
14510 if (0 != ret)
14511 return ret;
14512
Krunal Sonib4326f22016-03-10 13:05:51 -080014513 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14514 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014515 return -ENOTSUPP;
14516
14517 freq = csa_params->chandef.chan->center_freq;
14518 channel = cds_freq_to_chan(freq);
14519
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014520 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14521
14522 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014523 return ret;
14524}
14525
14526/**
14527 * wlan_hdd_cfg80211_channel_switch()- function to switch
14528 * channel in SAP/GO
14529 * @wiphy: wiphy pointer
14530 * @dev: dev pointer.
14531 * @csa_params: Change channel params
14532 *
14533 * This function is called to switch channel in SAP/GO
14534 *
14535 * Return: 0 if success else return non zero
14536 */
14537static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14538 struct net_device *dev,
14539 struct cfg80211_csa_settings *csa_params)
14540{
14541 int ret;
14542
14543 cds_ssr_protect(__func__);
14544 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14545 cds_ssr_unprotect(__func__);
14546 return ret;
14547}
14548#endif
14549
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014550/**
14551 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14552 * translation from NL to policy manager type
14553 * @type: Generic connection mode type defined in NL
14554 *
14555 *
14556 * This function provides the type translation
14557 *
14558 * Return: cds_con_mode enum
14559 */
14560enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
14561 enum nl80211_iftype type)
14562{
14563 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
14564 switch (type) {
14565 case NL80211_IFTYPE_STATION:
14566 mode = CDS_STA_MODE;
14567 break;
14568 case NL80211_IFTYPE_P2P_CLIENT:
14569 mode = CDS_P2P_CLIENT_MODE;
14570 break;
14571 case NL80211_IFTYPE_P2P_GO:
14572 mode = CDS_P2P_GO_MODE;
14573 break;
14574 case NL80211_IFTYPE_AP:
14575 mode = CDS_SAP_MODE;
14576 break;
14577 case NL80211_IFTYPE_ADHOC:
14578 mode = CDS_IBSS_MODE;
14579 break;
14580 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014581 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014582 type);
14583 }
14584 return mode;
14585}
14586
14587/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014588 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14589 * @wiphy: Handle to struct wiphy to get handle to module context.
14590 * @chandef: Contains information about the capture channel to be set.
14591 *
14592 * This interface is called if and only if monitor mode interface alone is
14593 * active.
14594 *
14595 * Return: 0 success or error code on failure.
14596 */
14597static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14598 struct cfg80211_chan_def *chandef)
14599{
14600 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14601 hdd_adapter_t *adapter;
14602 hdd_station_ctx_t *sta_ctx;
14603 struct hdd_mon_set_ch_info *ch_info;
14604 QDF_STATUS status;
14605 tHalHandle hal_hdl;
14606 struct qdf_mac_addr bssid;
14607 tCsrRoamProfile roam_profile;
14608 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014609 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014610 int ret;
14611 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
14612
14613 ENTER();
14614
14615 ret = wlan_hdd_validate_context(hdd_ctx);
14616 if (ret)
14617 return ret;
14618
14619 hal_hdl = hdd_ctx->hHal;
14620
14621 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
14622 if (!adapter)
14623 return -EIO;
14624
14625 hdd_info("%s: set monitor mode Channel %d and freq %d",
14626 adapter->dev->name, chan_num, chandef->chan->center_freq);
14627
14628 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14629 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014630 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
14631 roam_profile.ChannelInfo.numOfChannels = 1;
14632 roam_profile.phyMode = ch_info->phy_mode;
14633 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014634 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014635
14636 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
14637 QDF_MAC_ADDR_SIZE);
14638
14639 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014640 /*
14641 * CDS api expects secondary channel for calculating
14642 * the channel params
14643 */
14644 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
14645 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
14646 if (chan_num >= 1 && chan_num <= 5)
14647 sec_ch = chan_num + 4;
14648 else if (chan_num >= 6 && chan_num <= 13)
14649 sec_ch = chan_num - 4;
14650 }
14651 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014652 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
14653 &roam_profile);
14654 if (status) {
14655 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
14656 status);
14657 ret = qdf_status_to_os_return(status);
14658 return ret;
14659 }
14660 EXIT();
14661 return 0;
14662}
14663
14664/**
14665 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14666 * @wiphy: Handle to struct wiphy to get handle to module context.
14667 * @chandef: Contains information about the capture channel to be set.
14668 *
14669 * This interface is called if and only if monitor mode interface alone is
14670 * active.
14671 *
14672 * Return: 0 success or error code on failure.
14673 */
14674static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14675 struct cfg80211_chan_def *chandef)
14676{
14677 int ret;
14678
14679 cds_ssr_protect(__func__);
14680 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
14681 cds_ssr_unprotect(__func__);
14682 return ret;
14683}
14684
14685/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014686 * struct cfg80211_ops - cfg80211_ops
14687 *
14688 * @add_virtual_intf: Add virtual interface
14689 * @del_virtual_intf: Delete virtual interface
14690 * @change_virtual_intf: Change virtual interface
14691 * @change_station: Change station
14692 * @add_beacon: Add beacon in sap mode
14693 * @del_beacon: Delete beacon in sap mode
14694 * @set_beacon: Set beacon in sap mode
14695 * @start_ap: Start ap
14696 * @change_beacon: Change beacon
14697 * @stop_ap: Stop ap
14698 * @change_bss: Change bss
14699 * @add_key: Add key
14700 * @get_key: Get key
14701 * @del_key: Delete key
14702 * @set_default_key: Set default key
14703 * @set_channel: Set channel
14704 * @scan: Scan
14705 * @connect: Connect
14706 * @disconnect: Disconnect
14707 * @join_ibss = Join ibss
14708 * @leave_ibss = Leave ibss
14709 * @set_wiphy_params = Set wiphy params
14710 * @set_tx_power = Set tx power
14711 * @get_tx_power = get tx power
14712 * @remain_on_channel = Remain on channel
14713 * @cancel_remain_on_channel = Cancel remain on channel
14714 * @mgmt_tx = Tx management frame
14715 * @mgmt_tx_cancel_wait = Cancel management tx wait
14716 * @set_default_mgmt_key = Set default management key
14717 * @set_txq_params = Set tx queue parameters
14718 * @get_station = Get station
14719 * @set_power_mgmt = Set power management
14720 * @del_station = Delete station
14721 * @add_station = Add station
14722 * @set_pmksa = Set pmksa
14723 * @del_pmksa = Delete pmksa
14724 * @flush_pmksa = Flush pmksa
14725 * @update_ft_ies = Update FT IEs
14726 * @tdls_mgmt = Tdls management
14727 * @tdls_oper = Tdls operation
14728 * @set_rekey_data = Set rekey data
14729 * @sched_scan_start = Scheduled scan start
14730 * @sched_scan_stop = Scheduled scan stop
14731 * @resume = Resume wlan
14732 * @suspend = Suspend wlan
14733 * @set_mac_acl = Set mac acl
14734 * @testmode_cmd = Test mode command
14735 * @set_ap_chanwidth = Set AP channel bandwidth
14736 * @dump_survey = Dump survey
14737 * @key_mgmt_set_pmk = Set pmk key management
14738 */
14739static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
14740 .add_virtual_intf = wlan_hdd_add_virtual_intf,
14741 .del_virtual_intf = wlan_hdd_del_virtual_intf,
14742 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
14743 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014744 .start_ap = wlan_hdd_cfg80211_start_ap,
14745 .change_beacon = wlan_hdd_cfg80211_change_beacon,
14746 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014747 .change_bss = wlan_hdd_cfg80211_change_bss,
14748 .add_key = wlan_hdd_cfg80211_add_key,
14749 .get_key = wlan_hdd_cfg80211_get_key,
14750 .del_key = wlan_hdd_cfg80211_del_key,
14751 .set_default_key = wlan_hdd_cfg80211_set_default_key,
14752 .scan = wlan_hdd_cfg80211_scan,
14753 .connect = wlan_hdd_cfg80211_connect,
14754 .disconnect = wlan_hdd_cfg80211_disconnect,
14755 .join_ibss = wlan_hdd_cfg80211_join_ibss,
14756 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
14757 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
14758 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
14759 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
14760 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
14761 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
14762 .mgmt_tx = wlan_hdd_mgmt_tx,
14763 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
14764 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
14765 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053014766 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014767 .get_station = wlan_hdd_cfg80211_get_station,
14768 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
14769 .del_station = wlan_hdd_cfg80211_del_station,
14770 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014771 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
14772 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
14773 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014774#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014775 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
14776#endif
14777#ifdef FEATURE_WLAN_TDLS
14778 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
14779 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
14780#endif
14781#ifdef WLAN_FEATURE_GTK_OFFLOAD
14782 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
14783#endif /* WLAN_FEATURE_GTK_OFFLOAD */
14784#ifdef FEATURE_WLAN_SCAN_PNO
14785 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
14786 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
14787#endif /*FEATURE_WLAN_SCAN_PNO */
14788 .resume = wlan_hdd_cfg80211_resume_wlan,
14789 .suspend = wlan_hdd_cfg80211_suspend_wlan,
14790 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
14791#ifdef WLAN_NL80211_TESTMODE
14792 .testmode_cmd = wlan_hdd_cfg80211_testmode,
14793#endif
14794#ifdef QCA_HT_2040_COEX
14795 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
14796#endif
14797 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014798#ifdef CHANNEL_SWITCH_SUPPORTED
14799 .channel_switch = wlan_hdd_cfg80211_channel_switch,
14800#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014801 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053014802#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
14803 defined(CFG80211_ABORT_SCAN)
14804 .abort_scan = wlan_hdd_cfg80211_abort_scan,
14805#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014806};