blob: 115f69680fb631160738c8ad27f6d3b1588ef497 [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
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001803 /* ENTER_DEV() intentionally not used in a frequently invoked API */
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);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301891 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001892nla_put_failure:
1893 kfree_skb(skb);
1894 return -EINVAL;
1895}
1896
1897/**
1898 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1899 * @wiphy: pointer to wireless wiphy structure.
1900 * @wdev: pointer to wireless_dev structure.
1901 * @data: Pointer to the data to be passed via vendor interface
1902 * @data_len:Length of the data to be passed
1903 *
1904 * Return: Return the Success or Failure code.
1905 */
1906static int
1907wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1908 struct wireless_dev *wdev,
1909 const void *data, int data_len)
1910{
1911 int ret = 0;
1912
1913 cds_ssr_protect(__func__);
1914 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1915 data, data_len);
1916 cds_ssr_unprotect(__func__);
1917
1918 return ret;
1919}
1920
1921/**
1922 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1923 * @wiphy: pointer to wireless wiphy structure.
1924 * @wdev: pointer to wireless_dev structure.
1925 * @data: Pointer to the data to be passed via vendor interface
1926 * @data_len:Length of the data to be passed
1927 *
1928 * Set the MAC address that is to be used for scanning.
1929 *
1930 * Return: Return the Success or Failure code.
1931 */
1932static int
1933__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1934 struct wireless_dev *wdev,
1935 const void *data,
1936 int data_len)
1937{
1938 tpSirScanMacOui pReqMsg = NULL;
1939 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1940 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301941 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001942 int ret;
1943
Jeff Johnson1f61b612016-02-12 16:28:33 -08001944 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001945
Anurag Chouhan6d760662016-02-20 16:05:43 +05301946 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001947 hdd_err("Command not allowed in FTM mode");
1948 return -EPERM;
1949 }
1950
1951 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301952 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001953 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954
1955 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001956 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957 return -ENOTSUPP;
1958 }
1959
1960 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1961 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001962 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963 return -EINVAL;
1964 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301965 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001966 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07001967 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 return -ENOMEM;
1969 }
1970 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001971 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 goto fail;
1973 }
1974 nla_memcpy(&pReqMsg->oui[0],
1975 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
1976 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07001977 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 pReqMsg->oui[1], pReqMsg->oui[2]);
1979 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301980 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001981 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001982 goto fail;
1983 }
1984 return 0;
1985fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301986 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987 return -EINVAL;
1988}
1989
1990/**
1991 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1992 * @wiphy: pointer to wireless wiphy structure.
1993 * @wdev: pointer to wireless_dev structure.
1994 * @data: Pointer to the data to be passed via vendor interface
1995 * @data_len:Length of the data to be passed
1996 *
1997 * Set the MAC address that is to be used for scanning. This is an
1998 * SSR-protecting wrapper function.
1999 *
2000 * Return: Return the Success or Failure code.
2001 */
2002static int
2003wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2004 struct wireless_dev *wdev,
2005 const void *data,
2006 int data_len)
2007{
2008 int ret;
2009
2010 cds_ssr_protect(__func__);
2011 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2012 data, data_len);
2013 cds_ssr_unprotect(__func__);
2014
2015 return ret;
2016}
2017
2018/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302019 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2020 * @wiphy: pointer phy adapter
2021 * @wdev: pointer to wireless device structure
2022 * @data: pointer to data buffer
2023 * @data_len: length of data
2024 *
2025 * This routine will give concurrency matrix
2026 *
2027 * Return: int status code
2028 */
2029static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2030 struct wireless_dev *wdev,
2031 const void *data,
2032 int data_len)
2033{
2034 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2035 uint8_t i, feature_sets, max_feature_sets;
2036 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2037 struct sk_buff *reply_skb;
2038 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2039 int ret;
2040
2041 ENTER_DEV(wdev->netdev);
2042
2043 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2044 hdd_err("Command not allowed in FTM mode");
2045 return -EPERM;
2046 }
2047
2048 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302049 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302050 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302051
2052 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2053 data, data_len, NULL)) {
2054 hdd_err("Invalid ATTR");
2055 return -EINVAL;
2056 }
2057
2058 /* Parse and fetch max feature set */
2059 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2060 hdd_err("Attr max feature set size failed");
2061 return -EINVAL;
2062 }
2063 max_feature_sets = nla_get_u32(tb[
2064 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2065 hdd_info("Max feature set size: %d", max_feature_sets);
2066
2067 /* Fill feature combination matrix */
2068 feature_sets = 0;
2069 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002070 WIFI_FEATURE_P2P;
2071 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2072 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302073 /* Add more feature combinations here */
2074
2075 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002076 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302077 hdd_info("Feature set matrix");
2078 for (i = 0; i < feature_sets; i++)
2079 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2080
2081 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2082 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2083 if (!reply_skb) {
2084 hdd_err("Feature set matrix: buffer alloc fail");
2085 return -ENOMEM;
2086 }
2087
2088 if (nla_put_u32(reply_skb,
2089 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2090 feature_sets) ||
2091 nla_put(reply_skb,
2092 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2093 sizeof(u32) * feature_sets,
2094 feature_set_matrix)) {
2095 hdd_err("nla put fail");
2096 kfree_skb(reply_skb);
2097 return -EINVAL;
2098 }
2099 return cfg80211_vendor_cmd_reply(reply_skb);
2100}
2101
2102/**
2103 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2104 * @wiphy: pointer to wireless wiphy structure.
2105 * @wdev: pointer to wireless_dev structure.
2106 * @data: Pointer to the data to be passed via vendor interface
2107 * @data_len:Length of the data to be passed
2108 *
2109 * Retrieves the concurrency feature set matrix
2110 *
2111 * Return: 0 on success, negative errno on failure
2112 */
2113static int
2114wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2115 struct wireless_dev *wdev,
2116 const void *data,
2117 int data_len)
2118{
2119 int ret;
2120
2121 cds_ssr_protect(__func__);
2122 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2123 data, data_len);
2124 cds_ssr_unprotect(__func__);
2125
2126 return ret;
2127}
2128
2129/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002130 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2131 * @feature_flags: pointer to the byte array of features.
2132 * @feature: Feature to be turned ON in the byte array.
2133 *
2134 * Return: None
2135 *
2136 * This is called to turn ON or SET the feature flag for the requested feature.
2137 **/
2138#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002139static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2140 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002141{
2142 uint32_t index;
2143 uint8_t bit_mask;
2144
2145 index = feature / NUM_BITS_IN_BYTE;
2146 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2147 feature_flags[index] |= bit_mask;
2148}
2149
2150/**
2151 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2152 * @wiphy: pointer to wireless wiphy structure.
2153 * @wdev: pointer to wireless_dev structure.
2154 * @data: Pointer to the data to be passed via vendor interface
2155 * @data_len:Length of the data to be passed
2156 *
2157 * This is called when wlan driver needs to send supported feature set to
2158 * supplicant upon a request/query from the supplicant.
2159 *
2160 * Return: Return the Success or Failure code.
2161 **/
2162#define MAX_CONCURRENT_CHAN_ON_24G 2
2163#define MAX_CONCURRENT_CHAN_ON_5G 2
2164static int
2165__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2166 struct wireless_dev *wdev,
2167 const void *data, int data_len)
2168{
2169 struct sk_buff *skb = NULL;
2170 uint32_t dbs_capability = 0;
2171 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302172 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002173 int ret_val;
2174
2175 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2176 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2177
Jeff Johnson1f61b612016-02-12 16:28:33 -08002178 ENTER_DEV(wdev->netdev);
2179
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002180 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2181 if (ret_val)
2182 return ret_val;
2183
Anurag Chouhan6d760662016-02-20 16:05:43 +05302184 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185 hdd_err("Command not allowed in FTM mode");
2186 return -EPERM;
2187 }
2188
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002189 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002190 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002191 wlan_hdd_cfg80211_set_feature(feature_flags,
2192 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2193 }
2194
2195 wlan_hdd_cfg80211_set_feature(feature_flags,
2196 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2197 if (wma_is_scan_simultaneous_capable())
2198 wlan_hdd_cfg80211_set_feature(feature_flags,
2199 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002200
2201 if (wma_is_p2p_lo_capable())
2202 wlan_hdd_cfg80211_set_feature(feature_flags,
2203 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2204
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002205 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2206 NLMSG_HDRLEN);
2207
2208 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002209 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002210 return -ENOMEM;
2211 }
2212
2213 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2214 sizeof(feature_flags), feature_flags))
2215 goto nla_put_failure;
2216
2217 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302218 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219 if (one_by_one_dbs)
2220 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2221
2222 if (two_by_two_dbs)
2223 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2224
2225 if (!one_by_one_dbs && !two_by_two_dbs)
2226 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2227 } else {
2228 hdd_err("wma_get_dbs_hw_mode failed");
2229 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2230 }
2231
2232 hdd_info("dbs_capability is %d", dbs_capability);
2233
2234 if (nla_put_u32(skb,
2235 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2236 MAX_CONCURRENT_CHAN_ON_24G))
2237 goto nla_put_failure;
2238
2239 if (nla_put_u32(skb,
2240 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2241 MAX_CONCURRENT_CHAN_ON_5G))
2242 goto nla_put_failure;
2243
2244 return cfg80211_vendor_cmd_reply(skb);
2245
2246nla_put_failure:
2247 kfree_skb(skb);
2248 return -EINVAL;
2249}
2250
2251/**
2252 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2253 * @wiphy: pointer to wireless wiphy structure.
2254 * @wdev: pointer to wireless_dev structure.
2255 * @data: Pointer to the data to be passed via vendor interface
2256 * @data_len:Length of the data to be passed
2257 *
2258 * This is called when wlan driver needs to send supported feature set to
2259 * supplicant upon a request/query from the supplicant.
2260 *
2261 * Return: Return the Success or Failure code.
2262 */
2263static int
2264wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2265 struct wireless_dev *wdev,
2266 const void *data, int data_len)
2267{
2268 int ret;
2269
2270 cds_ssr_protect(__func__);
2271 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2272 data, data_len);
2273 cds_ssr_unprotect(__func__);
2274
2275 return ret;
2276}
2277
2278
2279/**
2280 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2281 * @wiphy: The wiphy structure
2282 * @wdev: The wireless device
2283 * @data: Data passed by framework
2284 * @data_len: Parameters to be configured passed as data
2285 *
2286 * The roaming related parameters are configured by the framework
2287 * using this interface.
2288 *
2289 * Return: Return either success or failure code.
2290 */
2291static int
2292__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2293 struct wireless_dev *wdev, const void *data, int data_len)
2294{
2295 struct net_device *dev = wdev->netdev;
2296 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2297 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2298 uint8_t session_id;
2299 struct roam_ext_params roam_params;
2300 uint32_t cmd_type, req_id;
2301 struct nlattr *curr_attr;
2302 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2303 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2304 int rem, i;
2305 uint32_t buf_len = 0;
2306 int ret;
2307
Jeff Johnson1f61b612016-02-12 16:28:33 -08002308 ENTER_DEV(dev);
2309
Anurag Chouhan6d760662016-02-20 16:05:43 +05302310 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002311 hdd_err("Command not allowed in FTM mode");
2312 return -EPERM;
2313 }
2314
2315 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302316 if (ret)
2317 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002318
2319 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2320 data, data_len,
2321 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002322 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002323 return -EINVAL;
2324 }
2325 /* Parse and fetch Command Type*/
2326 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002327 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002328 goto fail;
2329 }
2330 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302331 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002332 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2333 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002334 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002335 goto fail;
2336 }
2337 req_id = nla_get_u32(
2338 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002339 hdd_debug("Req Id (%d)", req_id);
2340 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002341 switch (cmd_type) {
2342 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2343 i = 0;
2344 nla_for_each_nested(curr_attr,
2345 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2346 rem) {
2347 if (nla_parse(tb2,
2348 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2349 nla_data(curr_attr), nla_len(curr_attr),
2350 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002351 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002352 goto fail;
2353 }
2354 /* Parse and Fetch allowed SSID list*/
2355 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002356 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002357 goto fail;
2358 }
2359 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2360 /*
2361 * Upper Layers include a null termination character.
2362 * Check for the actual permissible length of SSID and
2363 * also ensure not to copy the NULL termination
2364 * character to the driver buffer.
2365 */
2366 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2367 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2368 nla_memcpy(
2369 roam_params.ssid_allowed_list[i].ssId,
2370 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2371 buf_len - 1);
2372 roam_params.ssid_allowed_list[i].length =
2373 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002374 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002375 roam_params.ssid_allowed_list[i].length,
2376 roam_params.ssid_allowed_list[i].ssId,
2377 roam_params.ssid_allowed_list[i].length);
2378 i++;
2379 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002380 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381 }
2382 }
2383 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002384 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002385 roam_params.num_ssid_allowed_list);
2386 sme_update_roam_params(pHddCtx->hHal, session_id,
2387 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2388 break;
2389 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2390 /* Parse and fetch 5G Boost Threshold */
2391 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002392 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002393 goto fail;
2394 }
2395 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2396 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002397 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002398 roam_params.raise_rssi_thresh_5g);
2399 /* Parse and fetch 5G Penalty Threshold */
2400 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002401 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002402 goto fail;
2403 }
2404 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2405 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002406 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002407 roam_params.drop_rssi_thresh_5g);
2408 /* Parse and fetch 5G Boost Factor */
2409 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002410 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002411 goto fail;
2412 }
2413 roam_params.raise_factor_5g = nla_get_u32(
2414 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002415 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002416 roam_params.raise_factor_5g);
2417 /* Parse and fetch 5G Penalty factor */
2418 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002419 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002420 goto fail;
2421 }
2422 roam_params.drop_factor_5g = nla_get_u32(
2423 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002424 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002425 roam_params.drop_factor_5g);
2426 /* Parse and fetch 5G Max Boost */
2427 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002428 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002429 goto fail;
2430 }
2431 roam_params.max_raise_rssi_5g = nla_get_u32(
2432 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002433 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002434 roam_params.max_raise_rssi_5g);
2435 /* Parse and fetch Rssi Diff */
2436 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002437 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002438 goto fail;
2439 }
2440 roam_params.rssi_diff = nla_get_s32(
2441 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002442 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443 roam_params.rssi_diff);
2444 /* Parse and fetch Alert Rssi Threshold */
2445 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002446 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002447 goto fail;
2448 }
2449 roam_params.alert_rssi_threshold = nla_get_u32(
2450 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002451 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452 roam_params.alert_rssi_threshold);
2453 sme_update_roam_params(pHddCtx->hHal, session_id,
2454 roam_params,
2455 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2456 break;
2457 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2458 /* Parse and fetch Activate Good Rssi Roam */
2459 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002460 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002461 goto fail;
2462 }
2463 roam_params.good_rssi_roam = nla_get_s32(
2464 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002465 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002466 roam_params.good_rssi_roam);
2467 sme_update_roam_params(pHddCtx->hHal, session_id,
2468 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2469 break;
2470 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2471 /* Parse and fetch number of preferred BSSID */
2472 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002473 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002474 goto fail;
2475 }
2476 roam_params.num_bssid_favored = nla_get_u32(
2477 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002478 hdd_debug("Num of Preferred BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 roam_params.num_bssid_favored);
2480 i = 0;
2481 nla_for_each_nested(curr_attr,
2482 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2483 rem) {
2484 if (nla_parse(tb2,
2485 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2486 nla_data(curr_attr), nla_len(curr_attr),
2487 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002488 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489 goto fail;
2490 }
2491 /* Parse and fetch MAC address */
2492 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002493 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002494 goto fail;
2495 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002496 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002497 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302498 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002499 hdd_debug(MAC_ADDRESS_STR,
2500 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002501 /* Parse and fetch preference factor*/
2502 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002503 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002504 goto fail;
2505 }
2506 roam_params.bssid_favored_factor[i] = nla_get_u32(
2507 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002508 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 roam_params.bssid_favored_factor[i]);
2510 i++;
2511 }
2512 sme_update_roam_params(pHddCtx->hHal, session_id,
2513 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2514 break;
2515 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2516 /* Parse and fetch number of blacklist BSSID */
2517 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002518 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002519 goto fail;
2520 }
2521 roam_params.num_bssid_avoid_list = nla_get_u32(
2522 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002523 hdd_debug("Num of blacklist BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 roam_params.num_bssid_avoid_list);
2525 i = 0;
2526 nla_for_each_nested(curr_attr,
2527 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2528 rem) {
2529 if (nla_parse(tb2,
2530 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2531 nla_data(curr_attr), nla_len(curr_attr),
2532 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002533 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002534 goto fail;
2535 }
2536 /* Parse and fetch MAC address */
2537 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002538 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 goto fail;
2540 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002541 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302543 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002544 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002546 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 i++;
2548 }
2549 sme_update_roam_params(pHddCtx->hHal, session_id,
2550 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2551 break;
2552 }
2553 return 0;
2554fail:
2555 return -EINVAL;
2556}
2557
2558/**
2559 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2560 * @wiphy: pointer to wireless wiphy structure.
2561 * @wdev: pointer to wireless_dev structure.
2562 * @data: Pointer to the data to be passed via vendor interface
2563 * @data_len:Length of the data to be passed
2564 *
2565 * Return: Return the Success or Failure code.
2566 */
2567static int
2568wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2569 struct wireless_dev *wdev,
2570 const void *data,
2571 int data_len)
2572{
2573 int ret;
2574
2575 cds_ssr_protect(__func__);
2576 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2577 data, data_len);
2578 cds_ssr_unprotect(__func__);
2579
2580 return ret;
2581}
2582
2583static const struct nla_policy
2584wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2585 +1] = {
2586 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2587};
2588
2589/**
2590 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2591 * @hdd_ctx: HDD context
2592 * @device_mode: device mode
2593 * Return: bool
2594 */
2595static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002596 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002597{
2598 hdd_adapter_t *adapter;
2599 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2600 hdd_ap_ctx_t *ap_ctx;
2601 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302602 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302604 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002605 &adapter_node);
2606
2607 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302608 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609 adapter = adapter_node->pAdapter;
2610
2611 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002612 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002613 ap_ctx =
2614 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2615
2616 /*
2617 * if there is SAP already running on DFS channel,
2618 * do not disable scan on dfs channels. Note that
2619 * with SAP on DFS, there cannot be conurrency on
2620 * single radio. But then we can have multiple
2621 * radios !!
2622 */
2623 if (CHANNEL_STATE_DFS ==
2624 cds_get_channel_state(
2625 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002626 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002627 return true;
2628 }
2629 }
2630
2631 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002632 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002633 sta_ctx =
2634 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2635
2636 /*
2637 * if STA is already connected on DFS channel,
2638 * do not disable scan on dfs channels
2639 */
2640 if (hdd_conn_is_connected(sta_ctx) &&
2641 (CHANNEL_STATE_DFS ==
2642 cds_get_channel_state(
2643 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002644 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002645 return true;
2646 }
2647 }
2648
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302649 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002650 adapter_node,
2651 &next);
2652 adapter_node = next;
2653 }
2654
2655 return false;
2656}
2657
2658/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002659 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2660 * @hdd_ctx: HDD context within host driver
2661 * @adapter: Adapter pointer
2662 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2663 *
2664 * Loops through devices to see who is operating on DFS channels
2665 * and then disables/enables DFS channels by calling SME API.
2666 * Fails the disable request if any device is active on a DFS channel.
2667 *
2668 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002670
2671int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2672 hdd_adapter_t *adapter,
2673 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302676 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678
2679 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2680 if (no_dfs_flag) {
2681 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002682 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002683
2684 if (true == status)
2685 return -EOPNOTSUPP;
2686
2687 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002688 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689
2690 if (true == status)
2691 return -EOPNOTSUPP;
2692 }
2693
2694 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2695
2696 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2697
2698 /*
2699 * call the SME API to tunnel down the new channel list
2700 * to the firmware
2701 */
2702 status = sme_handle_dfs_chan_scan(
2703 h_hal, hdd_ctx->config->enableDFSChnlScan);
2704
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302705 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002706 ret_val = 0;
2707
2708 /*
2709 * Clear the SME scan cache also. Note that the
2710 * clearing of scan results is independent of session;
2711 * so no need to iterate over
2712 * all sessions
2713 */
2714 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302715 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002716 ret_val = -EPERM;
2717 }
2718
2719 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002720 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002721 ret_val = 0;
2722 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002723 return ret_val;
2724}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002725
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002726/**
2727 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2728 * @wiphy: corestack handler
2729 * @wdev: wireless device
2730 * @data: data
2731 * @data_len: data length
2732 * Return: success(0) or reason code for failure
2733 */
2734static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2735 struct wireless_dev *wdev,
2736 const void *data,
2737 int data_len)
2738{
2739 struct net_device *dev = wdev->netdev;
2740 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2741 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2742 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2743 int ret_val;
2744 uint32_t no_dfs_flag = 0;
2745
Jeff Johnson1f61b612016-02-12 16:28:33 -08002746 ENTER_DEV(dev);
2747
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002748 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302749 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002750 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002751
2752 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2753 data, data_len,
2754 wlan_hdd_set_no_dfs_flag_config_policy)) {
2755 hdd_err("invalid attr");
2756 return -EINVAL;
2757 }
2758
2759 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2760 hdd_err("attr dfs flag failed");
2761 return -EINVAL;
2762 }
2763
2764 no_dfs_flag = nla_get_u32(
2765 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2766
Jeff Johnson020db452016-06-29 14:37:26 -07002767 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002768
2769 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002770 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002771 return -EINVAL;
2772 }
2773
2774 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2775 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776 return ret_val;
2777}
2778
2779/**
2780 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2781 *
2782 * @wiphy: wiphy device pointer
2783 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002784 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002785 * @data_len: Buffer length
2786 *
2787 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2788 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2789 *
2790 * Return: EOK or other error codes.
2791 */
2792
2793static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2794 struct wireless_dev *wdev,
2795 const void *data,
2796 int data_len)
2797{
2798 int ret;
2799
2800 cds_ssr_protect(__func__);
2801 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2802 data, data_len);
2803 cds_ssr_unprotect(__func__);
2804
2805 return ret;
2806}
2807
Manikandan Mohan80dea792016-04-28 16:36:48 -07002808static const struct nla_policy
2809wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2810 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2811};
2812
2813/**
2814 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2815 * @wiphy: wiphy device pointer
2816 * @wdev: wireless device pointer
2817 * @data: Vendor command data buffer
2818 * @data_len: Buffer length
2819 *
2820 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2821 * setup WISA Mode features.
2822 *
2823 * Return: Success(0) or reason code for failure
2824 */
2825static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2826 struct wireless_dev *wdev, const void *data, int data_len)
2827{
2828 struct net_device *dev = wdev->netdev;
2829 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2830 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2831 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2832 struct sir_wisa_params wisa;
2833 int ret_val;
2834 QDF_STATUS status;
2835 bool wisa_mode;
2836
2837 ENTER_DEV(dev);
2838 ret_val = wlan_hdd_validate_context(hdd_ctx);
2839 if (ret_val)
2840 goto err;
2841
2842 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2843 hdd_err("Command not allowed in FTM mode");
2844 return -EPERM;
2845 }
2846
2847 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2848 wlan_hdd_wisa_cmd_policy)) {
2849 hdd_err("Invalid WISA cmd attributes");
2850 ret_val = -EINVAL;
2851 goto err;
2852 }
2853 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2854 hdd_err("Invalid WISA mode");
2855 ret_val = -EINVAL;
2856 goto err;
2857 }
2858
2859 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2860 hdd_info("WISA Mode: %d", wisa_mode);
2861 wisa.mode = wisa_mode;
2862 wisa.vdev_id = adapter->sessionId;
2863 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002864 if (!QDF_IS_STATUS_SUCCESS(status)) {
2865 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002866 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002867 }
2868 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
2869 ol_txrx_set_wisa_mode(ol_txrx_get_vdev_from_vdev_id(
2870 adapter->sessionId), wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002871err:
2872 EXIT();
2873 return ret_val;
2874}
2875
2876/**
2877 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2878 * @wiphy: corestack handler
2879 * @wdev: wireless device
2880 * @data: data
2881 * @data_len: data length
2882 *
2883 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2884 * setup WISA mode features.
2885 *
2886 * Return: Success(0) or reason code for failure
2887 */
2888static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2889 struct wireless_dev *wdev,
2890 const void *data,
2891 int data_len)
2892{
2893 int ret;
2894
2895 cds_ssr_protect(__func__);
2896 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2897 cds_ssr_unprotect(__func__);
2898
2899 return ret;
2900}
2901
Anurag Chouhan96919482016-07-13 16:36:57 +05302902/*
2903 * define short names for the global vendor params
2904 * used by __wlan_hdd_cfg80211_get_station_cmd()
2905 */
2906#define STATION_INVALID \
2907 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2908#define STATION_INFO \
2909 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2910#define STATION_ASSOC_FAIL_REASON \
2911 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2912#define STATION_MAX \
2913 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2914
2915static const struct nla_policy
2916hdd_get_station_policy[STATION_MAX + 1] = {
2917 [STATION_INFO] = {.type = NLA_FLAG},
2918 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2919};
2920
2921/**
2922 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2923 * @hdd_ctx: HDD context within host driver
2924 * @wdev: wireless device
2925 *
2926 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
2927 * Validate cmd attributes and send the station info to upper layers.
2928 *
2929 * Return: Success(0) or reason code for failure
2930 */
2931static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
2932 hdd_adapter_t *adapter)
2933{
2934 struct sk_buff *skb = NULL;
2935 uint32_t nl_buf_len;
2936 hdd_station_ctx_t *hdd_sta_ctx;
2937
2938 nl_buf_len = NLMSG_HDRLEN;
2939 nl_buf_len += sizeof(uint32_t);
2940 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
2941
2942 if (!skb) {
2943 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
2944 return -ENOMEM;
2945 }
2946
2947 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2948
2949 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
2950 hdd_sta_ctx->conn_info.assoc_status_code)) {
2951 hdd_err("put fail");
2952 goto fail;
2953 }
2954 return cfg80211_vendor_cmd_reply(skb);
2955fail:
2956 if (skb)
2957 kfree_skb(skb);
2958 return -EINVAL;
2959}
2960
2961/**
2962 * hdd_map_auth_type() - transform auth type specific to
2963 * vendor command
2964 * @auth_type: csr auth type
2965 *
2966 * Return: Success(0) or reason code for failure
2967 */
2968static int hdd_convert_auth_type(uint32_t auth_type)
2969{
2970 uint32_t ret_val;
2971
2972 switch (auth_type) {
2973 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
2974 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
2975 break;
2976 case eCSR_AUTH_TYPE_SHARED_KEY:
2977 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
2978 break;
2979 case eCSR_AUTH_TYPE_WPA:
2980 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
2981 break;
2982 case eCSR_AUTH_TYPE_WPA_PSK:
2983 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
2984 break;
2985 case eCSR_AUTH_TYPE_AUTOSWITCH:
2986 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
2987 break;
2988 case eCSR_AUTH_TYPE_WPA_NONE:
2989 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
2990 break;
2991 case eCSR_AUTH_TYPE_RSN:
2992 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
2993 break;
2994 case eCSR_AUTH_TYPE_RSN_PSK:
2995 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
2996 break;
2997 case eCSR_AUTH_TYPE_FT_RSN:
2998 ret_val = QCA_WLAN_AUTH_TYPE_FT;
2999 break;
3000 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3001 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3002 break;
3003 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3004 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3005 break;
3006 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3007 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3008 break;
3009 case eCSR_AUTH_TYPE_CCKM_WPA:
3010 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3011 break;
3012 case eCSR_AUTH_TYPE_CCKM_RSN:
3013 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3014 break;
3015 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3016 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3017 break;
3018 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3019 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3020 break;
3021 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3022 case eCSR_AUTH_TYPE_FAILED:
3023 case eCSR_AUTH_TYPE_NONE:
3024 default:
3025 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3026 break;
3027 }
3028 return ret_val;
3029}
3030
3031/**
3032 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3033 * vendor command
3034 * @dot11mode: dot11mode
3035 *
3036 * Return: Success(0) or reason code for failure
3037 */
3038static int hdd_convert_dot11mode(uint32_t dot11mode)
3039{
3040 uint32_t ret_val;
3041
3042 switch (dot11mode) {
3043 case eCSR_CFG_DOT11_MODE_11A:
3044 ret_val = QCA_WLAN_802_11_MODE_11A;
3045 break;
3046 case eCSR_CFG_DOT11_MODE_11B:
3047 ret_val = QCA_WLAN_802_11_MODE_11B;
3048 break;
3049 case eCSR_CFG_DOT11_MODE_11G:
3050 ret_val = QCA_WLAN_802_11_MODE_11G;
3051 break;
3052 case eCSR_CFG_DOT11_MODE_11N:
3053 ret_val = QCA_WLAN_802_11_MODE_11N;
3054 break;
3055 case eCSR_CFG_DOT11_MODE_11AC:
3056 ret_val = QCA_WLAN_802_11_MODE_11AC;
3057 break;
3058 case eCSR_CFG_DOT11_MODE_AUTO:
3059 case eCSR_CFG_DOT11_MODE_ABG:
3060 default:
3061 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3062 }
3063 return ret_val;
3064}
3065
3066/**
3067 * hdd_add_tx_bitrate() - add tx bitrate attribute
3068 * @skb: pointer to sk buff
3069 * @hdd_sta_ctx: pointer to hdd station context
3070 * @idx: attribute index
3071 *
3072 * Return: Success(0) or reason code for failure
3073 */
3074static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3075 hdd_station_ctx_t *hdd_sta_ctx,
3076 int idx)
3077{
3078 struct nlattr *nla_attr;
3079 uint32_t bitrate, bitrate_compat;
3080
3081 nla_attr = nla_nest_start(skb, idx);
3082 if (!nla_attr)
3083 goto fail;
3084 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3085 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3086
3087 /* report 16-bit bitrate only if we can */
3088 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3089 if (bitrate > 0 &&
3090 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3091 hdd_err("put fail");
3092 goto fail;
3093 }
3094 if (bitrate_compat > 0 &&
3095 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3096 hdd_err("put fail");
3097 goto fail;
3098 }
3099 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3100 hdd_sta_ctx->conn_info.txrate.nss)) {
3101 hdd_err("put fail");
3102 goto fail;
3103 }
3104 nla_nest_end(skb, nla_attr);
3105 return 0;
3106fail:
3107 return -EINVAL;
3108}
3109
3110/**
3111 * hdd_add_sta_info() - add station info attribute
3112 * @skb: pointer to sk buff
3113 * @hdd_sta_ctx: pointer to hdd station context
3114 * @idx: attribute index
3115 *
3116 * Return: Success(0) or reason code for failure
3117 */
3118static int32_t hdd_add_sta_info(struct sk_buff *skb,
3119 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3120{
3121 struct nlattr *nla_attr;
3122
3123 nla_attr = nla_nest_start(skb, idx);
3124 if (!nla_attr)
3125 goto fail;
3126 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3127 (hdd_sta_ctx->conn_info.signal + 100))) {
3128 hdd_err("put fail");
3129 goto fail;
3130 }
3131 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3132 goto fail;
3133 nla_nest_end(skb, nla_attr);
3134 return 0;
3135fail:
3136 return -EINVAL;
3137}
3138
3139/**
3140 * hdd_add_survey_info() - add survey info attribute
3141 * @skb: pointer to sk buff
3142 * @hdd_sta_ctx: pointer to hdd station context
3143 * @idx: attribute index
3144 *
3145 * Return: Success(0) or reason code for failure
3146 */
3147static int32_t hdd_add_survey_info(struct sk_buff *skb,
3148 hdd_station_ctx_t *hdd_sta_ctx,
3149 int idx)
3150{
3151 struct nlattr *nla_attr;
3152
3153 nla_attr = nla_nest_start(skb, idx);
3154 if (!nla_attr)
3155 goto fail;
3156 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3157 hdd_sta_ctx->conn_info.freq) ||
3158 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3159 (hdd_sta_ctx->conn_info.noise + 100))) {
3160 hdd_err("put fail");
3161 goto fail;
3162 }
3163 nla_nest_end(skb, nla_attr);
3164 return 0;
3165fail:
3166 return -EINVAL;
3167}
3168
3169/**
3170 * hdd_add_link_standard_info() - add link info attribute
3171 * @skb: pointer to sk buff
3172 * @hdd_sta_ctx: pointer to hdd station context
3173 * @idx: attribute index
3174 *
3175 * Return: Success(0) or reason code for failure
3176 */
3177static int32_t
3178hdd_add_link_standard_info(struct sk_buff *skb,
3179 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3180{
3181 struct nlattr *nla_attr;
3182
3183 nla_attr = nla_nest_start(skb, idx);
3184 if (!nla_attr)
3185 goto fail;
3186 if (nla_put(skb,
3187 NL80211_ATTR_SSID,
3188 hdd_sta_ctx->conn_info.SSID.SSID.length,
3189 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3190 hdd_err("put fail");
3191 goto fail;
3192 }
3193 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3194 goto fail;
3195 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3196 goto fail;
3197 nla_nest_end(skb, nla_attr);
3198 return 0;
3199fail:
3200 return -EINVAL;
3201}
3202
3203/**
3204 * hdd_add_ap_standard_info() - add ap info attribute
3205 * @skb: pointer to sk buff
3206 * @hdd_sta_ctx: pointer to hdd station context
3207 * @idx: attribute index
3208 *
3209 * Return: Success(0) or reason code for failure
3210 */
3211static int32_t
3212hdd_add_ap_standard_info(struct sk_buff *skb,
3213 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3214{
3215 struct nlattr *nla_attr;
3216
3217 nla_attr = nla_nest_start(skb, idx);
3218 if (!nla_attr)
3219 goto fail;
3220 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3221 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3222 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3223 &hdd_sta_ctx->conn_info.vht_caps)) {
3224 hdd_err("put fail");
3225 goto fail;
3226 }
3227 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3228 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3229 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3230 &hdd_sta_ctx->conn_info.ht_caps)) {
3231 hdd_err("put fail");
3232 goto fail;
3233 }
3234 nla_nest_end(skb, nla_attr);
3235 return 0;
3236fail:
3237 return -EINVAL;
3238}
3239
3240/**
3241 * hdd_get_station_info() - send BSS information to supplicant
3242 * @hdd_ctx: pointer to hdd context
3243 * @adapter: pointer to adapter
3244 *
3245 * Return: 0 if success else error status
3246 */
3247static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3248 hdd_adapter_t *adapter)
3249{
3250 struct sk_buff *skb = NULL;
3251 uint8_t *tmp_hs20 = NULL;
3252 uint32_t nl_buf_len;
3253 hdd_station_ctx_t *hdd_sta_ctx;
3254
3255 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3256
3257 nl_buf_len = NLMSG_HDRLEN;
3258 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3259 sizeof(hdd_sta_ctx->conn_info.freq) +
3260 sizeof(hdd_sta_ctx->conn_info.noise) +
3261 sizeof(hdd_sta_ctx->conn_info.signal) +
3262 (sizeof(uint32_t) * 2) +
3263 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3264 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3265 sizeof(hdd_sta_ctx->conn_info.authType) +
3266 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3267 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3268 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3269 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3270 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3271 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3272 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3273 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3274 1);
3275 }
3276 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3277 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3278 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3279 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3280
3281
3282 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3283 if (!skb) {
3284 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3285 return -ENOMEM;
3286 }
3287
3288 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3289 LINK_INFO_STANDARD_NL80211_ATTR)) {
3290 hdd_err("put fail");
3291 goto fail;
3292 }
3293 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3294 AP_INFO_STANDARD_NL80211_ATTR)) {
3295 hdd_err("put fail");
3296 goto fail;
3297 }
3298 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3299 hdd_sta_ctx->conn_info.roam_count) ||
3300 nla_put_u32(skb, INFO_AKM,
3301 hdd_convert_auth_type(
3302 hdd_sta_ctx->conn_info.authType)) ||
3303 nla_put_u32(skb, WLAN802_11_MODE,
3304 hdd_convert_dot11mode(
3305 hdd_sta_ctx->conn_info.dot11Mode))) {
3306 hdd_err("put fail");
3307 goto fail;
3308 }
3309 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3310 if (nla_put(skb, HT_OPERATION,
3311 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3312 &hdd_sta_ctx->conn_info.ht_operation)) {
3313 hdd_err("put fail");
3314 goto fail;
3315 }
3316 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3317 if (nla_put(skb, VHT_OPERATION,
3318 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3319 &hdd_sta_ctx->conn_info.vht_operation)) {
3320 hdd_err("put fail");
3321 goto fail;
3322 }
3323 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3324 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3325 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3326 tmp_hs20 + 1)) {
3327 hdd_err("put fail");
3328 goto fail;
3329 }
3330
3331 return cfg80211_vendor_cmd_reply(skb);
3332fail:
3333 if (skb)
3334 kfree_skb(skb);
3335 return -EINVAL;
3336}
3337
3338/**
3339 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3340 * @wiphy: corestack handler
3341 * @wdev: wireless device
3342 * @data: data
3343 * @data_len: data length
3344 *
3345 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3346 * Validate cmd attributes and send the station info to upper layers.
3347 *
3348 * Return: Success(0) or reason code for failure
3349 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303350static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303351__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3352 struct wireless_dev *wdev,
3353 const void *data,
3354 int data_len)
3355{
3356 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3357 struct net_device *dev = wdev->netdev;
3358 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3359 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3360 int32_t status;
3361
3362 ENTER_DEV(dev);
3363 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3364 hdd_err("Command not allowed in FTM mode");
3365 status = -EPERM;
3366 goto out;
3367 }
3368
3369 status = wlan_hdd_validate_context(hdd_ctx);
3370 if (0 != status)
3371 goto out;
3372
3373
3374 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3375 data, data_len, NULL);
3376 if (status) {
3377 hdd_err("Invalid ATTR");
3378 goto out;
3379 }
3380
3381 /* Parse and fetch Command Type*/
3382 if (tb[STATION_INFO]) {
3383 status = hdd_get_station_info(hdd_ctx, adapter);
3384 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3385 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3386 } else {
3387 hdd_err("get station info cmd type failed");
3388 status = -EINVAL;
3389 goto out;
3390 }
3391 EXIT();
3392out:
3393 return status;
3394}
3395
3396/**
3397 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3398 * @wiphy: corestack handler
3399 * @wdev: wireless device
3400 * @data: data
3401 * @data_len: data length
3402 *
3403 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3404 * Validate cmd attributes and send the station info to upper layers.
3405 *
3406 * Return: Success(0) or reason code for failure
3407 */
3408static int32_t
3409hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3410 struct wireless_dev *wdev,
3411 const void *data,
3412 int data_len)
3413{
3414 int ret;
3415
3416 cds_ssr_protect(__func__);
3417 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3418 cds_ssr_unprotect(__func__);
3419
3420 return ret;
3421}
3422
3423/*
3424 * undef short names defined for get station command
3425 * used by __wlan_hdd_cfg80211_get_station_cmd()
3426 */
3427#undef STATION_INVALID
3428#undef STATION_INFO
3429#undef STATION_ASSOC_FAIL_REASON
3430#undef STATION_MAX
3431
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003432#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3433/**
3434 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3435 * @wiphy: pointer to wireless wiphy structure.
3436 * @wdev: pointer to wireless_dev structure.
3437 * @data: Pointer to the Key data
3438 * @data_len:Length of the data passed
3439 *
3440 * This is called when wlan driver needs to save the keys received via
3441 * vendor specific command.
3442 *
3443 * Return: Return the Success or Failure code.
3444 */
3445static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3446 struct wireless_dev *wdev,
3447 const void *data, int data_len)
3448{
3449 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3450 struct net_device *dev = wdev->netdev;
3451 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3452 hdd_context_t *hdd_ctx_ptr;
3453 int status;
3454
Jeff Johnson1f61b612016-02-12 16:28:33 -08003455 ENTER_DEV(dev);
3456
Anurag Chouhan6d760662016-02-20 16:05:43 +05303457 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003458 hdd_err("Command not allowed in FTM mode");
3459 return -EPERM;
3460 }
3461
3462 if ((data == NULL) || (data_len == 0) ||
3463 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003464 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003465 return -EINVAL;
3466 }
3467
3468 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3469 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003470 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003471 return -EINVAL;
3472 }
3473
3474 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303475 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003477 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3478 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003479 true,
3480 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303481 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3482 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003483 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3484 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3485 return 0;
3486}
3487
3488/**
3489 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3490 * @wiphy: pointer to wireless wiphy structure.
3491 * @wdev: pointer to wireless_dev structure.
3492 * @data: Pointer to the Key data
3493 * @data_len:Length of the data passed
3494 *
3495 * This is called when wlan driver needs to save the keys received via
3496 * vendor specific command.
3497 *
3498 * Return: Return the Success or Failure code.
3499 */
3500static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3501 struct wireless_dev *wdev,
3502 const void *data, int data_len)
3503{
3504 int ret;
3505
3506 cds_ssr_protect(__func__);
3507 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3508 cds_ssr_unprotect(__func__);
3509
3510 return ret;
3511}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003512#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003513
3514static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3515 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3516 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3517 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003518 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003519};
3520
3521/**
3522 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3523 * @wiphy: pointer to wireless wiphy structure.
3524 * @wdev: pointer to wireless_dev structure.
3525 * @data: Pointer to the data to be passed via vendor interface
3526 * @data_len:Length of the data to be passed
3527 *
3528 * This is called when wlan driver needs to send wifi driver related info
3529 * (driver/fw version) to the user space application upon request.
3530 *
3531 * Return: Return the Success or Failure code.
3532 */
3533static int
3534__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3535 struct wireless_dev *wdev,
3536 const void *data, int data_len)
3537{
3538 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3539 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003540 tSirVersionString driver_version;
3541 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003542 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003543 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003544 struct sk_buff *reply_skb;
3545 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003546
Jeff Johnson1f61b612016-02-12 16:28:33 -08003547 ENTER_DEV(wdev->netdev);
3548
Anurag Chouhan6d760662016-02-20 16:05:43 +05303549 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003550 hdd_err("Command not allowed in FTM mode");
3551 return -EPERM;
3552 }
3553
3554 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303555 if (status)
3556 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003557
3558 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3559 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003560 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561 return -EINVAL;
3562 }
3563
3564 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003565 hdd_err("Rcvd req for Driver version");
3566 strlcpy(driver_version, QWLAN_VERSIONSTR,
3567 sizeof(driver_version));
3568 skb_len += strlen(driver_version) + 1;
3569 count++;
3570 }
3571
3572 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3573 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003574 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3575 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003576 snprintf(firmware_version, sizeof(firmware_version),
3577 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3578 skb_len += strlen(firmware_version) + 1;
3579 count++;
3580 }
3581
3582 if (count == 0) {
3583 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003584 return -EINVAL;
3585 }
3586
Ryan Hsu7ac88852016-04-28 10:20:34 -07003587 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3588 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3589
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003590 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003591 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003592 return -ENOMEM;
3593 }
3594
Ryan Hsu7ac88852016-04-28 10:20:34 -07003595 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3596 if (nla_put_string(reply_skb,
3597 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3598 driver_version))
3599 goto error_nla_fail;
3600 }
3601
3602 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3603 if (nla_put_string(reply_skb,
3604 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3605 firmware_version))
3606 goto error_nla_fail;
3607 }
3608
3609 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3610 if (nla_put_u32(reply_skb,
3611 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3612 hdd_ctx->radio_index))
3613 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003614 }
3615
3616 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003617
3618error_nla_fail:
3619 hdd_err("nla put fail");
3620 kfree_skb(reply_skb);
3621 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003622}
3623
3624/**
3625 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3626 * @wiphy: pointer to wireless wiphy structure.
3627 * @wdev: pointer to wireless_dev structure.
3628 * @data: Pointer to the data to be passed via vendor interface
3629 * @data_len:Length of the data to be passed
3630 *
3631 * This is called when wlan driver needs to send wifi driver related info
3632 * (driver/fw version) to the user space application upon request.
3633 *
3634 * Return: Return the Success or Failure code.
3635 */
3636static int
3637wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3638 struct wireless_dev *wdev,
3639 const void *data, int data_len)
3640{
3641 int ret;
3642
3643 cds_ssr_protect(__func__);
3644 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3645 cds_ssr_unprotect(__func__);
3646
3647 return ret;
3648}
3649
3650/**
3651 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3652 * @wiphy: pointer to wireless wiphy structure.
3653 * @wdev: pointer to wireless_dev structure.
3654 * @data: Pointer to the data to be passed via vendor interface
3655 * @data_len:Length of the data to be passed
3656 *
3657 * This is called by userspace to know the supported logger features
3658 *
3659 * Return: Return the Success or Failure code.
3660 */
3661static int
3662__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3663 struct wireless_dev *wdev,
3664 const void *data, int data_len)
3665{
3666 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3667 int status;
3668 uint32_t features;
3669 struct sk_buff *reply_skb = NULL;
3670
Jeff Johnson1f61b612016-02-12 16:28:33 -08003671 ENTER_DEV(wdev->netdev);
3672
Anurag Chouhan6d760662016-02-20 16:05:43 +05303673 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003674 hdd_err("Command not allowed in FTM mode");
3675 return -EPERM;
3676 }
3677
3678 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303679 if (status)
3680 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003681
3682 features = 0;
3683
3684 if (hdd_is_memdump_supported())
3685 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3686 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3687 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3688 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3689
3690 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3691 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3692 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003693 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003694 return -ENOMEM;
3695 }
3696
Jeff Johnson020db452016-06-29 14:37:26 -07003697 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3699 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003700 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003701 kfree_skb(reply_skb);
3702 return -EINVAL;
3703 }
3704
3705 return cfg80211_vendor_cmd_reply(reply_skb);
3706}
3707
3708/**
3709 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3710 * @wiphy: pointer to wireless wiphy structure.
3711 * @wdev: pointer to wireless_dev structure.
3712 * @data: Pointer to the data to be passed via vendor interface
3713 * @data_len:Length of the data to be passed
3714 *
3715 * This is called by userspace to know the supported logger features
3716 *
3717 * Return: Return the Success or Failure code.
3718 */
3719static int
3720wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3721 struct wireless_dev *wdev,
3722 const void *data, int data_len)
3723{
3724 int ret;
3725
3726 cds_ssr_protect(__func__);
3727 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3728 data, data_len);
3729 cds_ssr_unprotect(__func__);
3730
3731 return ret;
3732}
3733
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003734#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003735/**
3736 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3737 * @hdd_ctx_ptr: pointer to HDD Context.
3738 * @bssid: pointer to bssid of roamed AP.
3739 * @req_rsn_ie: Pointer to request RSN IE
3740 * @req_rsn_len: Length of the request RSN IE
3741 * @rsp_rsn_ie: Pointer to response RSN IE
3742 * @rsp_rsn_len: Length of the response RSN IE
3743 * @roam_info_ptr: Pointer to the roaming related information
3744 *
3745 * This is called when wlan driver needs to send the roaming and
3746 * authorization information after roaming.
3747 *
3748 * The information that would be sent is the request RSN IE, response
3749 * RSN IE and BSSID of the newly roamed AP.
3750 *
3751 * If the Authorized status is authenticated, then additional parameters
3752 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3753 * supplicant.
3754 *
3755 * The supplicant upon receiving this event would ignore the legacy
3756 * cfg80211_roamed call and use the entire information from this event.
3757 * The cfg80211_roamed should still co-exist since the kernel will
3758 * make use of the parameters even if the supplicant ignores it.
3759 *
3760 * Return: Return the Success or Failure code.
3761 */
3762int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3763 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3764 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3765{
3766 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003767 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003768 ENTER();
3769
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303770 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003771 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003772
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003773 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003774 !roam_info_ptr->roamSynchInProgress)
3775 return 0;
3776
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003777 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3778 NULL,
3779 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3780 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3781 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003782 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3784 GFP_KERNEL);
3785
3786 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003787 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003788 return -EINVAL;
3789 }
3790
3791 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3792 ETH_ALEN, bssid) ||
3793 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3794 req_rsn_len, req_rsn_ie) ||
3795 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3796 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003797 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003798 goto nla_put_failure;
3799 }
Jeff Johnson020db452016-06-29 14:37:26 -07003800 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003801 if (roam_info_ptr->synchAuthStatus ==
3802 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003803 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003804 if (nla_put_u8(skb,
3805 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3806 hdd_err("nla put fail");
3807 goto nla_put_failure;
3808 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003809 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3810 /* if FT or CCKM connection: dont send replay counter */
3811 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3812 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3813 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3814 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3815 nla_put(skb,
3816 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3817 SIR_REPLAY_CTR_LEN,
3818 roam_info_ptr->replay_ctr)) {
3819 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003820 hdd_err("failed to send replay counter.");
3821 goto nla_put_failure;
3822 }
3823 if (nla_put(skb,
3824 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3825 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3826 nla_put(skb,
3827 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3828 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3829 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003830 goto nla_put_failure;
3831 }
3832 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003833 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003834 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3835 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003836 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003837 goto nla_put_failure;
3838 }
3839 }
3840
Jeff Johnson020db452016-06-29 14:37:26 -07003841 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003842 roam_info_ptr->subnet_change_status);
3843
3844 /*
3845 * Add subnet change status if subnet has changed
3846 * 0 = unchanged
3847 * 1 = changed
3848 * 2 = unknown
3849 */
3850 if (roam_info_ptr->subnet_change_status) {
3851 if (nla_put_u8(skb,
3852 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3853 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003854 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003855 goto nla_put_failure;
3856 }
3857 }
3858
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003859 cfg80211_vendor_event(skb, GFP_KERNEL);
3860 return 0;
3861
3862nla_put_failure:
3863 kfree_skb(skb);
3864 return -EINVAL;
3865}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003866#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003867
3868static const struct nla_policy
3869wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3870
3871 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3872 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3873 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303874 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303875 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3876 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003877};
3878
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003879/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303880 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3881 *
3882 * @adapter: Pointer to HDD adapter
3883 * @ie_data: Pointer to Scan IEs buffer
3884 * @ie_len: Length of Scan IEs
3885 *
3886 * Return: 0 on success; error number otherwise
3887 */
3888static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3889 uint8_t *ie_data, uint8_t ie_len)
3890{
3891 hdd_scaninfo_t *scan_info = NULL;
3892 scan_info = &adapter->scan_info;
3893
3894 if (scan_info->default_scan_ies) {
3895 qdf_mem_free(scan_info->default_scan_ies);
3896 scan_info->default_scan_ies = NULL;
3897 }
3898
3899 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3900 if (!scan_info->default_scan_ies)
3901 return -ENOMEM;
3902
3903 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3904 scan_info->default_scan_ies_len = ie_len;
3905 return 0;
3906}
3907
3908/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3910 * vendor command
3911 *
3912 * @wiphy: wiphy device pointer
3913 * @wdev: wireless device pointer
3914 * @data: Vendor command data buffer
3915 * @data_len: Buffer length
3916 *
3917 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3918 *
3919 * Return: Error code.
3920 */
3921static int
3922__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3923 struct wireless_dev *wdev,
3924 const void *data,
3925 int data_len)
3926{
3927 struct net_device *dev = wdev->netdev;
3928 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3929 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3930 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3931 int ret_val = 0;
3932 u32 modulated_dtim;
3933 u16 stats_avg_factor;
3934 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303935 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003936 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07003937 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303938 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303939 int attr_len;
3940 int access_policy = 0;
3941 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3942 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303943 uint16_t scan_ie_len = 0;
3944 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303945 struct sir_set_tx_rx_aggregation_size request;
3946 QDF_STATUS qdf_status;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303947
Jeff Johnson1f61b612016-02-12 16:28:33 -08003948 ENTER_DEV(dev);
3949
Anurag Chouhan6d760662016-02-20 16:05:43 +05303950 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003951 hdd_err("Command not allowed in FTM mode");
3952 return -EPERM;
3953 }
3954
3955 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303956 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003957 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003958
3959 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3960 data, data_len,
3961 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07003962 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003963 return -EINVAL;
3964 }
3965
Krunal Sonie3531942016-04-12 17:43:53 -07003966 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
3967 ftm_capab = nla_get_u32(tb[
3968 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
3969 hdd_ctx->config->fine_time_meas_cap =
3970 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
3971 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05303972 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07003973 hdd_ctx->config->fine_time_meas_cap);
3974 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
3975 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
3976 hdd_ctx->config->fine_time_meas_cap);
3977 }
3978
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003979 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
3980 modulated_dtim = nla_get_u32(
3981 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
3982
3983 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
3984 adapter->sessionId,
3985 modulated_dtim);
3986
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303987 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003988 ret_val = -EPERM;
3989 }
3990
Kapil Gupta6213c012016-09-02 19:39:09 +05303991 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
3992 qpower = nla_get_u8(
3993 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
3994 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
3995 ret_val = -EINVAL;
3996 }
3997
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003998 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
3999 stats_avg_factor = nla_get_u16(
4000 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4001 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4002 adapter->sessionId,
4003 stats_avg_factor);
4004
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304005 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004006 ret_val = -EPERM;
4007 }
4008
4009
4010 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4011 guard_time = nla_get_u32(
4012 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4013 status = sme_configure_guard_time(hdd_ctx->hHal,
4014 adapter->sessionId,
4015 guard_time);
4016
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304017 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004018 ret_val = -EPERM;
4019 }
4020
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304021 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4022 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4023 attr_len = nla_len(
4024 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4025 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4026 hdd_info("Invalid value. attr_len %d",
4027 attr_len);
4028 return -EINVAL;
4029 }
4030
4031 nla_memcpy(&vendor_ie,
4032 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4033 attr_len);
4034 vendor_ie_present = true;
4035 hdd_info("Access policy vendor ie present.attr_len %d",
4036 attr_len);
4037 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4038 &vendor_ie[0], attr_len);
4039 }
4040
4041 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4042 access_policy = (int) nla_get_u32(
4043 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4044 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4045 (access_policy >
4046 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4047 hdd_info("Invalid value. access_policy %d",
4048 access_policy);
4049 return -EINVAL;
4050 }
4051 access_policy_present = true;
4052 hdd_info("Access policy present. access_policy %d",
4053 access_policy);
4054 }
4055
4056 if (vendor_ie_present && access_policy_present) {
4057 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4058 access_policy =
4059 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304060 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304061 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304062 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304063
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304064 hdd_info("calling sme_update_access_policy_vendor_ie");
4065 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4066 adapter->sessionId, &vendor_ie[0],
4067 access_policy);
4068 if (QDF_STATUS_SUCCESS != status) {
4069 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304070 return -EINVAL;
4071 }
4072 }
4073
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304074 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4075 set_value = nla_get_u8(
4076 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4077 hdd_info("set_value: %d", set_value);
4078 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4079 }
4080
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304081 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4082 scan_ie_len = nla_len(
4083 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4084 hdd_info("Received default scan IE of len %d session %d device mode %d",
4085 scan_ie_len, adapter->sessionId,
4086 adapter->device_mode);
4087 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4088 scan_ie = (uint8_t *) nla_data(tb
4089 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304090
4091 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4092 scan_ie_len))
4093 hdd_err("Failed to save default scan IEs");
4094
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304095 if (adapter->device_mode == QDF_STA_MODE) {
4096 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4097 adapter->sessionId, scan_ie,
4098 scan_ie_len);
4099 if (QDF_STATUS_SUCCESS != status)
4100 ret_val = -EPERM;
4101 }
4102 } else
4103 ret_val = -EPERM;
4104 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304105
4106 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4107 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4108 /* if one is specified, both must be specified */
4109 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4110 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4111 hdd_err("Both TX and RX MPDU Aggregation required");
4112 return -EINVAL;
4113 }
4114
4115 request.tx_aggregation_size = nla_get_u8(
4116 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4117 request.rx_aggregation_size = nla_get_u8(
4118 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4119 request.vdev_id = adapter->sessionId;
4120
4121 if (request.tx_aggregation_size >=
4122 CFG_TX_AGGREGATION_SIZE_MIN &&
4123 request.tx_aggregation_size <=
4124 CFG_TX_AGGREGATION_SIZE_MAX &&
4125 request.rx_aggregation_size >=
4126 CFG_RX_AGGREGATION_SIZE_MIN &&
4127 request.rx_aggregation_size <=
4128 CFG_RX_AGGREGATION_SIZE_MAX) {
4129 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4130 if (qdf_status != QDF_STATUS_SUCCESS) {
4131 hdd_err("failed to set aggr sizes err %d",
4132 qdf_status);
4133 ret_val = -EPERM;
4134 }
4135 } else {
4136 hdd_err("TX %d RX %d MPDU aggr size not in range",
4137 request.tx_aggregation_size,
4138 request.rx_aggregation_size);
4139 ret_val = -EINVAL;
4140 }
4141 }
4142
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304143 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4144 uint8_t ignore_assoc_disallowed;
4145
4146 ignore_assoc_disallowed
4147 = nla_get_u8(tb[
4148 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4149 hdd_info("Set ignore_assoc_disallowed value - %d",
4150 ignore_assoc_disallowed);
4151 if ((ignore_assoc_disallowed <
4152 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4153 (ignore_assoc_disallowed >
4154 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4155 return -EPERM;
4156
4157 sme_update_session_param(hdd_ctx->hHal,
4158 adapter->sessionId,
4159 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4160 ignore_assoc_disallowed);
4161 }
4162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004163 return ret_val;
4164}
4165
4166/**
4167 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4168 * vendor command
4169 *
4170 * @wiphy: wiphy device pointer
4171 * @wdev: wireless device pointer
4172 * @data: Vendor command data buffer
4173 * @data_len: Buffer length
4174 *
4175 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4176 *
4177 * Return: EOK or other error codes.
4178 */
4179static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4180 struct wireless_dev *wdev,
4181 const void *data,
4182 int data_len)
4183{
4184 int ret;
4185
4186 cds_ssr_protect(__func__);
4187 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4188 data, data_len);
4189 cds_ssr_unprotect(__func__);
4190
4191 return ret;
4192}
4193
4194static const struct
4195nla_policy
4196qca_wlan_vendor_wifi_logger_start_policy
4197[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4198 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4199 = {.type = NLA_U32 },
4200 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4201 = {.type = NLA_U32 },
4202 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4203 = {.type = NLA_U32 },
4204};
4205
4206/**
4207 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4208 * or disable the collection of packet statistics from the firmware
4209 * @wiphy: WIPHY structure pointer
4210 * @wdev: Wireless device structure pointer
4211 * @data: Pointer to the data received
4212 * @data_len: Length of the data received
4213 *
4214 * This function enables or disables the collection of packet statistics from
4215 * the firmware
4216 *
4217 * Return: 0 on success and errno on failure
4218 */
4219static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4220 struct wireless_dev *wdev,
4221 const void *data,
4222 int data_len)
4223{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304224 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004225 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4226 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4227 struct sir_wifi_start_log start_log;
4228
Jeff Johnson1f61b612016-02-12 16:28:33 -08004229 ENTER_DEV(wdev->netdev);
4230
Anurag Chouhan6d760662016-02-20 16:05:43 +05304231 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004232 hdd_err("Command not allowed in FTM mode");
4233 return -EPERM;
4234 }
4235
4236 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304237 if (status)
4238 return status;
4239
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004240
4241 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4242 data, data_len,
4243 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004244 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004245 return -EINVAL;
4246 }
4247
4248 /* Parse and fetch ring id */
4249 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004250 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004251 return -EINVAL;
4252 }
4253 start_log.ring_id = nla_get_u32(
4254 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004255 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004256
4257 /* Parse and fetch verbose level */
4258 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004259 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004260 return -EINVAL;
4261 }
4262 start_log.verbose_level = nla_get_u32(
4263 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004264 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004265
4266 /* Parse and fetch flag */
4267 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004268 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004269 return -EINVAL;
4270 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304271 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004272 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304273 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004274
4275 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4276
4277 if (start_log.ring_id == RING_ID_WAKELOCK) {
4278 /* Start/stop wakelock events */
4279 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4280 cds_set_wakelock_logging(true);
4281 else
4282 cds_set_wakelock_logging(false);
4283 return 0;
4284 }
4285
4286 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304287 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004288 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004289 status);
4290 return -EINVAL;
4291 }
4292 return 0;
4293}
4294
4295/**
4296 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4297 * or disable the collection of packet statistics from the firmware
4298 * @wiphy: WIPHY structure pointer
4299 * @wdev: Wireless device structure pointer
4300 * @data: Pointer to the data received
4301 * @data_len: Length of the data received
4302 *
4303 * This function is used to enable or disable the collection of packet
4304 * statistics from the firmware
4305 *
4306 * Return: 0 on success and errno on failure
4307 */
4308static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4309 struct wireless_dev *wdev,
4310 const void *data,
4311 int data_len)
4312{
4313 int ret = 0;
4314
4315 cds_ssr_protect(__func__);
4316 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4317 wdev, data, data_len);
4318 cds_ssr_unprotect(__func__);
4319
4320 return ret;
4321}
4322
4323static const struct
4324nla_policy
4325qca_wlan_vendor_wifi_logger_get_ring_data_policy
4326[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4327 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4328 = {.type = NLA_U32 },
4329};
4330
4331/**
4332 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4333 * @wiphy: WIPHY structure pointer
4334 * @wdev: Wireless device structure pointer
4335 * @data: Pointer to the data received
4336 * @data_len: Length of the data received
4337 *
4338 * This function is used to flush or retrieve the per packet statistics from
4339 * the driver
4340 *
4341 * Return: 0 on success and errno on failure
4342 */
4343static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4344 struct wireless_dev *wdev,
4345 const void *data,
4346 int data_len)
4347{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304348 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004349 uint32_t ring_id;
4350 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4351 struct nlattr *tb
4352 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4353
Jeff Johnson1f61b612016-02-12 16:28:33 -08004354 ENTER_DEV(wdev->netdev);
4355
Anurag Chouhan6d760662016-02-20 16:05:43 +05304356 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004357 hdd_err("Command not allowed in FTM mode");
4358 return -EPERM;
4359 }
4360
4361 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304362 if (status)
4363 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004364
4365 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4366 data, data_len,
4367 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004368 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004369 return -EINVAL;
4370 }
4371
4372 /* Parse and fetch ring id */
4373 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004374 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375 return -EINVAL;
4376 }
4377
4378 ring_id = nla_get_u32(
4379 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4380
4381 if (ring_id == RING_ID_PER_PACKET_STATS) {
4382 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004383 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304384 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4385 /*
4386 * As part of DRIVER ring ID, flush both driver and fw logs.
4387 * For other Ring ID's driver doesn't have any rings to flush
4388 */
4389 hdd_notice("Bug report triggered by framework");
4390
4391 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4392 WLAN_LOG_INDICATOR_FRAMEWORK,
4393 WLAN_LOG_REASON_CODE_UNUSED,
4394 true, false);
4395 if (QDF_STATUS_SUCCESS != status) {
4396 hdd_err("Failed to trigger bug report");
4397 return -EINVAL;
4398 }
4399 } else {
4400 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4401 WLAN_LOG_INDICATOR_FRAMEWORK,
4402 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004403 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004404 return 0;
4405}
4406
4407/**
4408 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4409 * @wiphy: WIPHY structure pointer
4410 * @wdev: Wireless device structure pointer
4411 * @data: Pointer to the data received
4412 * @data_len: Length of the data received
4413 *
4414 * This function is used to flush or retrieve the per packet statistics from
4415 * the driver
4416 *
4417 * Return: 0 on success and errno on failure
4418 */
4419static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4420 struct wireless_dev *wdev,
4421 const void *data,
4422 int data_len)
4423{
4424 int ret = 0;
4425
4426 cds_ssr_protect(__func__);
4427 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4428 wdev, data, data_len);
4429 cds_ssr_unprotect(__func__);
4430
4431 return ret;
4432}
4433
4434#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4435/**
4436 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4437 * @hdd_ctx: HDD context
4438 * @request_id: [input] request id
4439 * @pattern_id: [output] pattern id
4440 *
4441 * This function loops through request id to pattern id array
4442 * if the slot is available, store the request id and return pattern id
4443 * if entry exists, return the pattern id
4444 *
4445 * Return: 0 on success and errno on failure
4446 */
4447static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4448 uint32_t request_id,
4449 uint8_t *pattern_id)
4450{
4451 uint32_t i;
4452
4453 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4454 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4455 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4456 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4457 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4458 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4459 return 0;
4460 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4461 request_id) {
4462 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4463 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4464 return 0;
4465 }
4466 }
4467 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4468 return -EINVAL;
4469}
4470
4471/**
4472 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4473 * @hdd_ctx: HDD context
4474 * @request_id: [input] request id
4475 * @pattern_id: [output] pattern id
4476 *
4477 * This function loops through request id to pattern id array
4478 * reset request id to 0 (slot available again) and
4479 * return pattern id
4480 *
4481 * Return: 0 on success and errno on failure
4482 */
4483static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4484 uint32_t request_id,
4485 uint8_t *pattern_id)
4486{
4487 uint32_t i;
4488
4489 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4490 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4491 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4492 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4493 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4494 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4495 return 0;
4496 }
4497 }
4498 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4499 return -EINVAL;
4500}
4501
4502
4503/*
4504 * define short names for the global vendor params
4505 * used by __wlan_hdd_cfg80211_offloaded_packets()
4506 */
4507#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4508#define PARAM_REQUEST_ID \
4509 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4510#define PARAM_CONTROL \
4511 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4512#define PARAM_IP_PACKET \
4513 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4514#define PARAM_SRC_MAC_ADDR \
4515 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4516#define PARAM_DST_MAC_ADDR \
4517 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4518#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4519
4520/**
4521 * wlan_hdd_add_tx_ptrn() - add tx pattern
4522 * @adapter: adapter pointer
4523 * @hdd_ctx: hdd context
4524 * @tb: nl attributes
4525 *
4526 * This function reads the NL attributes and forms a AddTxPtrn message
4527 * posts it to SME.
4528 *
4529 */
4530static int
4531wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4532 struct nlattr **tb)
4533{
4534 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304535 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004536 uint32_t request_id, ret, len;
4537 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304538 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004539 uint16_t eth_type = htons(ETH_P_IP);
4540
4541 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004542 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004543 return -ENOTSUPP;
4544 }
4545
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304546 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004547 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004548 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004549 return -ENOMEM;
4550 }
4551
4552 /* Parse and fetch request Id */
4553 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004554 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004555 goto fail;
4556 }
4557
4558 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4559 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004560 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004561 return -EINVAL;
4562 }
Jeff Johnson77848112016-06-29 14:52:06 -07004563 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004564
4565 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004566 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004567 goto fail;
4568 }
4569 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004570 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004571 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004572 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004573 goto fail;
4574 }
4575
4576 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004577 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004578 goto fail;
4579 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004580 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304581 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004582 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004583 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004584
Anurag Chouhanc5548422016-02-24 18:33:27 +05304585 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004586 &adapter->macAddressCurrent)) {
4587 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004588 goto fail;
4589 }
4590
4591 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004592 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004593 goto fail;
4594 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304595 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004596 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004597 MAC_ADDR_ARRAY(dst_addr.bytes));
4598
4599 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004600 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004601 goto fail;
4602 }
4603 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004604 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004605
4606 if (add_req->ucPtrnSize < 0 ||
4607 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4608 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004609 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004610 add_req->ucPtrnSize);
4611 goto fail;
4612 }
4613
4614 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304615 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304616 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304617 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304618 QDF_MAC_ADDR_SIZE);
4619 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304620 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004621 len += 2;
4622
4623 /*
4624 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4625 * ------------------------------------------------------------
4626 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4627 * ------------------------------------------------------------
4628 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304629 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004630 nla_data(tb[PARAM_IP_PACKET]),
4631 add_req->ucPtrnSize);
4632 add_req->ucPtrnSize += len;
4633
4634 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4635 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004636 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004637 goto fail;
4638 }
4639 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004640 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004641
4642 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304643 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004644 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004645 goto fail;
4646 }
4647
4648 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304649 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004650 return 0;
4651
4652fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304653 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004654 return -EINVAL;
4655}
4656
4657/**
4658 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4659 * @adapter: adapter pointer
4660 * @hdd_ctx: hdd context
4661 * @tb: nl attributes
4662 *
4663 * This function reads the NL attributes and forms a DelTxPtrn message
4664 * posts it to SME.
4665 *
4666 */
4667static int
4668wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4669 struct nlattr **tb)
4670{
4671 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304672 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004673 uint32_t request_id, ret;
4674 uint8_t pattern_id = 0;
4675
4676 /* Parse and fetch request Id */
4677 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004678 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004679 return -EINVAL;
4680 }
4681 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4682 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004683 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004684 return -EINVAL;
4685 }
4686
4687 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4688 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004689 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690 return -EINVAL;
4691 }
4692
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304693 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004694 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004695 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004696 return -ENOMEM;
4697 }
4698
Anurag Chouhanc5548422016-02-24 18:33:27 +05304699 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004700 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004702 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004703 request_id, del_req->ucPtrnId);
4704
4705 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304706 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004707 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004708 goto fail;
4709 }
4710
4711 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304712 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004713 return 0;
4714
4715fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304716 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004717 return -EINVAL;
4718}
4719
4720
4721/**
4722 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4723 * @wiphy: Pointer to wireless phy
4724 * @wdev: Pointer to wireless device
4725 * @data: Pointer to data
4726 * @data_len: Data length
4727 *
4728 * Return: 0 on success, negative errno on failure
4729 */
4730static int
4731__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4732 struct wireless_dev *wdev,
4733 const void *data,
4734 int data_len)
4735{
4736 struct net_device *dev = wdev->netdev;
4737 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4738 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4739 struct nlattr *tb[PARAM_MAX + 1];
4740 uint8_t control;
4741 int ret;
4742 static const struct nla_policy policy[PARAM_MAX + 1] = {
4743 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4744 [PARAM_CONTROL] = { .type = NLA_U32 },
4745 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304746 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004747 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304748 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004749 [PARAM_PERIOD] = { .type = NLA_U32 },
4750 };
4751
Jeff Johnson1f61b612016-02-12 16:28:33 -08004752 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004753
Anurag Chouhan6d760662016-02-20 16:05:43 +05304754 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004755 hdd_err("Command not allowed in FTM mode");
4756 return -EPERM;
4757 }
4758
4759 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304760 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004761 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762
4763 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004764 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004765 return -ENOTSUPP;
4766 }
4767
4768 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004769 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004770 return -EINVAL;
4771 }
4772
4773 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004774 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004775 return -EINVAL;
4776 }
4777 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004778 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004779
4780 if (control == WLAN_START_OFFLOADED_PACKETS)
4781 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4782 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4783 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4784 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004785 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004786 return -EINVAL;
4787 }
4788}
4789
4790/*
4791 * done with short names for the global vendor params
4792 * used by __wlan_hdd_cfg80211_offloaded_packets()
4793 */
4794#undef PARAM_MAX
4795#undef PARAM_REQUEST_ID
4796#undef PARAM_CONTROL
4797#undef PARAM_IP_PACKET
4798#undef PARAM_SRC_MAC_ADDR
4799#undef PARAM_DST_MAC_ADDR
4800#undef PARAM_PERIOD
4801
4802/**
4803 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4804 * @wiphy: wiphy structure pointer
4805 * @wdev: Wireless device structure pointer
4806 * @data: Pointer to the data received
4807 * @data_len: Length of @data
4808 *
4809 * Return: 0 on success; errno on failure
4810 */
4811static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4812 struct wireless_dev *wdev,
4813 const void *data,
4814 int data_len)
4815{
4816 int ret = 0;
4817
4818 cds_ssr_protect(__func__);
4819 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4820 wdev, data, data_len);
4821 cds_ssr_unprotect(__func__);
4822
4823 return ret;
4824}
4825#endif
4826
4827/*
4828 * define short names for the global vendor params
4829 * used by __wlan_hdd_cfg80211_monitor_rssi()
4830 */
4831#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4832#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4833#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4834#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4835#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4836
4837/**
4838 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4839 * @wiphy: Pointer to wireless phy
4840 * @wdev: Pointer to wireless device
4841 * @data: Pointer to data
4842 * @data_len: Data length
4843 *
4844 * Return: 0 on success, negative errno on failure
4845 */
4846static int
4847__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4848 struct wireless_dev *wdev,
4849 const void *data,
4850 int data_len)
4851{
4852 struct net_device *dev = wdev->netdev;
4853 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4854 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4855 struct nlattr *tb[PARAM_MAX + 1];
4856 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304857 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004858 int ret;
4859 uint32_t control;
4860 static const struct nla_policy policy[PARAM_MAX + 1] = {
4861 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4862 [PARAM_CONTROL] = { .type = NLA_U32 },
4863 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4864 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4865 };
4866
Jeff Johnson1f61b612016-02-12 16:28:33 -08004867 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004868
4869 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304870 if (ret)
4871 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004872
4873 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004874 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004875 return -ENOTSUPP;
4876 }
4877
4878 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004879 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004880 return -EINVAL;
4881 }
4882
4883 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004884 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004885 return -EINVAL;
4886 }
4887
4888 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004889 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004890 return -EINVAL;
4891 }
4892
4893 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4894 req.session_id = adapter->sessionId;
4895 control = nla_get_u32(tb[PARAM_CONTROL]);
4896
4897 if (control == QCA_WLAN_RSSI_MONITORING_START) {
4898 req.control = true;
4899 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004900 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004901 return -EINVAL;
4902 }
4903
4904 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004905 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004906 return -EINVAL;
4907 }
4908
4909 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
4910 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
4911
4912 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004913 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914 req.min_rssi, req.max_rssi);
4915 return -EINVAL;
4916 }
Jeff Johnson77848112016-06-29 14:52:06 -07004917 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004918 req.min_rssi, req.max_rssi);
4919
4920 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
4921 req.control = false;
4922 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004923 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004924 return -EINVAL;
4925 }
Jeff Johnson77848112016-06-29 14:52:06 -07004926 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004927 req.request_id, req.session_id, req.control);
4928
4929 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304930 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004931 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004932 return -EINVAL;
4933 }
4934
4935 return 0;
4936}
4937
4938/*
4939 * done with short names for the global vendor params
4940 * used by __wlan_hdd_cfg80211_monitor_rssi()
4941 */
4942#undef PARAM_MAX
4943#undef PARAM_CONTROL
4944#undef PARAM_REQUEST_ID
4945#undef PARAM_MAX_RSSI
4946#undef PARAM_MIN_RSSI
4947
4948/**
4949 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
4950 * @wiphy: wiphy structure pointer
4951 * @wdev: Wireless device structure pointer
4952 * @data: Pointer to the data received
4953 * @data_len: Length of @data
4954 *
4955 * Return: 0 on success; errno on failure
4956 */
4957static int
4958wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
4959 const void *data, int data_len)
4960{
4961 int ret;
4962
4963 cds_ssr_protect(__func__);
4964 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
4965 cds_ssr_unprotect(__func__);
4966
4967 return ret;
4968}
4969
4970/**
4971 * hdd_rssi_threshold_breached() - rssi breached NL event
4972 * @hddctx: HDD context
4973 * @data: rssi breached event data
4974 *
4975 * This function reads the rssi breached event %data and fill in the skb with
4976 * NL attributes and send up the NL event.
4977 *
4978 * Return: none
4979 */
4980void hdd_rssi_threshold_breached(void *hddctx,
4981 struct rssi_breach_event *data)
4982{
4983 hdd_context_t *hdd_ctx = hddctx;
4984 struct sk_buff *skb;
4985
4986 ENTER();
4987
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304988 if (wlan_hdd_validate_context(hdd_ctx))
4989 return;
4990 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07004991 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004992 return;
4993 }
4994
4995 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4996 NULL,
4997 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
4998 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
4999 GFP_KERNEL);
5000
5001 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005002 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005003 return;
5004 }
5005
Jeff Johnson77848112016-06-29 14:52:06 -07005006 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005007 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005008 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005009 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5010
5011 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5012 data->request_id) ||
5013 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5014 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5015 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5016 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005017 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005018 goto fail;
5019 }
5020
5021 cfg80211_vendor_event(skb, GFP_KERNEL);
5022 return;
5023
5024fail:
5025 kfree_skb(skb);
5026 return;
5027}
5028
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305029static const struct nla_policy
5030ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5031 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5032};
5033
5034/**
5035 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5036 * @wiphy: Pointer to wireless phy
5037 * @wdev: Pointer to wireless device
5038 * @data: Pointer to data
5039 * @data_len: Length of @data
5040 *
5041 * Return: 0 on success, negative errno on failure
5042 */
5043static int
5044__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5045 struct wireless_dev *wdev,
5046 const void *data, int data_len)
5047{
5048 int status;
5049 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5050 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005051 struct net_device *dev = wdev->netdev;
5052 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305053
5054 ENTER_DEV(wdev->netdev);
5055
5056 status = wlan_hdd_validate_context(pHddCtx);
5057 if (0 != status)
5058 return status;
5059 if (!pHddCtx->config->fhostNSOffload) {
5060 hdd_err("ND Offload not supported");
5061 return -EINVAL;
5062 }
5063
5064 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5065 (struct nlattr *)data,
5066 data_len, ns_offload_set_policy)) {
5067 hdd_err("nla_parse failed");
5068 return -EINVAL;
5069 }
5070
5071 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5072 hdd_err("ND Offload flag attribute not present");
5073 return -EINVAL;
5074 }
5075
5076 pHddCtx->ns_offload_enable =
5077 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5078
Dustin Brownd8279d22016-09-07 14:52:57 -07005079 /* update ns offload in case it is already enabled/disabled */
5080 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5081
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305082 return 0;
5083}
5084
5085/**
5086 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5087 * @wiphy: pointer to wireless wiphy structure.
5088 * @wdev: pointer to wireless_dev structure.
5089 * @data: Pointer to the data to be passed via vendor interface
5090 * @data_len:Length of the data to be passed
5091 *
5092 * Return: Return the Success or Failure code.
5093 */
5094static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5095 struct wireless_dev *wdev,
5096 const void *data, int data_len)
5097{
5098 int ret;
5099
5100 cds_ssr_protect(__func__);
5101 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5102 cds_ssr_unprotect(__func__);
5103
5104 return ret;
5105}
5106
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005107/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5108 * @wiphy: Pointer to wireless phy
5109 * @wdev: Pointer to wireless device
5110 * @data: Pointer to data
5111 * @data_len: Data length
5112 *
5113 * This function return the preferred frequency list generated by the policy
5114 * manager.
5115 *
5116 * Return: success or failure code
5117 */
5118static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5119 struct wireless_dev
5120 *wdev, const void *data,
5121 int data_len)
5122{
5123 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5124 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305125 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305126 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005127 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305128 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005129 enum cds_con_mode intf_mode;
5130 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5131 struct sk_buff *reply_skb;
5132
Jeff Johnson1f61b612016-02-12 16:28:33 -08005133 ENTER_DEV(wdev->netdev);
5134
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005135 ret = wlan_hdd_validate_context(hdd_ctx);
5136 if (ret)
5137 return -EINVAL;
5138
5139 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5140 data, data_len, NULL)) {
5141 hdd_err("Invalid ATTR");
5142 return -EINVAL;
5143 }
5144
5145 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5146 hdd_err("attr interface type failed");
5147 return -EINVAL;
5148 }
5149
5150 intf_mode = nla_get_u32(tb
5151 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5152
5153 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5154 hdd_err("Invalid interface type");
5155 return -EINVAL;
5156 }
5157
5158 hdd_debug("Userspace requested pref freq list");
5159
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305160 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5161 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305162 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005163 hdd_err("Get pcl failed");
5164 return -EINVAL;
5165 }
5166
5167 /* convert channel number to frequency */
5168 for (i = 0; i < pcl_len; i++) {
5169 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5170 freq_list[i] =
5171 ieee80211_channel_to_frequency(pcl[i],
5172 IEEE80211_BAND_2GHZ);
5173 else
5174 freq_list[i] =
5175 ieee80211_channel_to_frequency(pcl[i],
5176 IEEE80211_BAND_5GHZ);
5177 }
5178
5179 /* send the freq_list back to supplicant */
5180 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5181 sizeof(u32) *
5182 pcl_len +
5183 NLMSG_HDRLEN);
5184
5185 if (!reply_skb) {
5186 hdd_err("Allocate reply_skb failed");
5187 return -EINVAL;
5188 }
5189
5190 if (nla_put_u32(reply_skb,
5191 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5192 intf_mode) ||
5193 nla_put(reply_skb,
5194 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5195 sizeof(uint32_t) * pcl_len,
5196 freq_list)) {
5197 hdd_err("nla put fail");
5198 kfree_skb(reply_skb);
5199 return -EINVAL;
5200 }
5201
5202 return cfg80211_vendor_cmd_reply(reply_skb);
5203}
5204
5205/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5206 * @wiphy: Pointer to wireless phy
5207 * @wdev: Pointer to wireless device
5208 * @data: Pointer to data
5209 * @data_len: Data length
5210 *
5211 * This function return the preferred frequency list generated by the policy
5212 * manager.
5213 *
5214 * Return: success or failure code
5215 */
5216static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5217 struct wireless_dev
5218 *wdev, const void *data,
5219 int data_len)
5220{
5221 int ret = 0;
5222
5223 cds_ssr_protect(__func__);
5224 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5225 data, data_len);
5226 cds_ssr_unprotect(__func__);
5227
5228 return ret;
5229}
5230
5231/**
5232 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5233 * @wiphy: Pointer to wireless phy
5234 * @wdev: Pointer to wireless device
5235 * @data: Pointer to data
5236 * @data_len: Data length
5237 *
5238 * Return: 0 on success, negative errno on failure
5239 */
5240static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5241 struct wireless_dev *wdev,
5242 const void *data,
5243 int data_len)
5244{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305245 struct net_device *ndev = wdev->netdev;
5246 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5248 int ret = 0;
5249 enum cds_con_mode intf_mode;
5250 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5251 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005252
Jeff Johnson1f61b612016-02-12 16:28:33 -08005253 ENTER_DEV(ndev);
5254
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005255 ret = wlan_hdd_validate_context(hdd_ctx);
5256 if (ret)
5257 return ret;
5258
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005259 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5260 data, data_len, NULL)) {
5261 hdd_err("Invalid ATTR");
5262 return -EINVAL;
5263 }
5264
5265 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5266 hdd_err("attr interface type failed");
5267 return -EINVAL;
5268 }
5269
5270 intf_mode = nla_get_u32(tb
5271 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5272
5273 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5274 hdd_err("Invalid interface type");
5275 return -EINVAL;
5276 }
5277
5278 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5279 hdd_err("attr probable freq failed");
5280 return -EINVAL;
5281 }
5282
5283 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5284 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5285
5286 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005287 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005288 channel_hint, HW_MODE_20_MHZ)) {
5289 hdd_err("Set channel hint failed due to concurrency check");
5290 return -EINVAL;
5291 }
5292
Krunal Soni09e55032016-06-07 10:06:55 -07005293 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5294 hdd_warn("Remain On Channel Pending");
5295
Krunal Soni3091bcc2016-06-23 12:28:21 -07005296 ret = qdf_reset_connection_update();
5297 if (!QDF_IS_STATUS_SUCCESS(ret))
5298 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005299
Krunal Soni3091bcc2016-06-23 12:28:21 -07005300 ret = cds_current_connections_update(adapter->sessionId,
5301 channel_hint,
5302 SIR_UPDATE_REASON_SET_OPER_CHAN);
5303 if (QDF_STATUS_E_FAILURE == ret) {
5304 /* return in the failure case */
5305 hdd_err("ERROR: connections update failed!!");
5306 return -EINVAL;
5307 }
5308
5309 if (QDF_STATUS_SUCCESS == ret) {
5310 /*
5311 * Success is the only case for which we expect hw mode
5312 * change to take place, hence we need to wait.
5313 * For any other return value it should be a pass
5314 * through
5315 */
5316 ret = qdf_wait_for_connection_update();
5317 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5318 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005319 return -EINVAL;
5320 }
5321
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005322 }
5323
5324 return 0;
5325}
5326
5327/**
5328 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5329 * @wiphy: Pointer to wireless phy
5330 * @wdev: Pointer to wireless device
5331 * @data: Pointer to data
5332 * @data_len: Data length
5333 *
5334 * Return: 0 on success, negative errno on failure
5335 */
5336static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5337 struct wireless_dev *wdev,
5338 const void *data,
5339 int data_len)
5340{
5341 int ret = 0;
5342
5343 cds_ssr_protect(__func__);
5344 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5345 data, data_len);
5346 cds_ssr_unprotect(__func__);
5347
5348 return ret;
5349}
5350
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305351static const struct
5352nla_policy
5353qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5354 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5355};
5356
5357/**
5358 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5359 * @wiphy: WIPHY structure pointer
5360 * @wdev: Wireless device structure pointer
5361 * @data: Pointer to the data received
5362 * @data_len: Length of the data received
5363 *
5364 * This function is used to get link properties like nss, rate flags and
5365 * operating frequency for the active connection with the given peer.
5366 *
5367 * Return: 0 on success and errno on failure
5368 */
5369static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5370 struct wireless_dev *wdev,
5371 const void *data,
5372 int data_len)
5373{
5374 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5375 struct net_device *dev = wdev->netdev;
5376 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5377 hdd_station_ctx_t *hdd_sta_ctx;
5378 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305379 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305380 uint32_t sta_id;
5381 struct sk_buff *reply_skb;
5382 uint32_t rate_flags = 0;
5383 uint8_t nss;
5384 uint8_t final_rate_flags = 0;
5385 uint32_t freq;
5386
Jeff Johnson1f61b612016-02-12 16:28:33 -08005387 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305388
Anurag Chouhan6d760662016-02-20 16:05:43 +05305389 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305390 hdd_err("Command not allowed in FTM mode");
5391 return -EPERM;
5392 }
5393
5394 if (0 != wlan_hdd_validate_context(hdd_ctx))
5395 return -EINVAL;
5396
5397 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5398 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005399 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305400 return -EINVAL;
5401 }
5402
5403 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005404 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305405 adapter->device_mode);
5406 return -EINVAL;
5407 }
5408
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305409 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305410 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005411 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305412 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5413
Krunal Sonib4326f22016-03-10 13:05:51 -08005414 if (adapter->device_mode == QDF_STA_MODE ||
5415 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305416 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5417 if ((hdd_sta_ctx->conn_info.connState !=
5418 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305419 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305420 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005421 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305422 MAC_ADDR_ARRAY(peer_mac));
5423 return -EINVAL;
5424 }
5425
5426 nss = hdd_sta_ctx->conn_info.nss;
5427 freq = cds_chan_to_freq(
5428 hdd_sta_ctx->conn_info.operationChannel);
5429 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005430 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5431 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305432
5433 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5434 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305435 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305436 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305437 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305438 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305439 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305440 break;
5441 }
5442
5443 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005444 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305445 MAC_ADDR_ARRAY(peer_mac));
5446 return -EINVAL;
5447 }
5448
5449 nss = adapter->aStaInfo[sta_id].nss;
5450 freq = cds_chan_to_freq(
5451 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5452 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5453 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005454 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305455 MAC_ADDR_ARRAY(peer_mac));
5456 return -EINVAL;
5457 }
5458
5459 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5460 if (rate_flags & eHAL_TX_RATE_VHT80) {
5461 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005462#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305463 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005464#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305465 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5466 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005467#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305468 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005469#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305470 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5471 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5472 } else if (rate_flags &
5473 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5474 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005475#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305476 if (rate_flags & eHAL_TX_RATE_HT40)
5477 final_rate_flags |=
5478 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005479#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305480 }
5481
5482 if (rate_flags & eHAL_TX_RATE_SGI) {
5483 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5484 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5485 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5486 }
5487 }
5488
5489 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5490 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5491
5492 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005493 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305494 return -EINVAL;
5495 }
5496
5497 if (nla_put_u8(reply_skb,
5498 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5499 nss) ||
5500 nla_put_u8(reply_skb,
5501 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5502 final_rate_flags) ||
5503 nla_put_u32(reply_skb,
5504 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5505 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005506 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305507 kfree_skb(reply_skb);
5508 return -EINVAL;
5509 }
5510
5511 return cfg80211_vendor_cmd_reply(reply_skb);
5512}
5513
5514/**
5515 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5516 * properties.
5517 * @wiphy: WIPHY structure pointer
5518 * @wdev: Wireless device structure pointer
5519 * @data: Pointer to the data received
5520 * @data_len: Length of the data received
5521 *
5522 * This function is used to get link properties like nss, rate flags and
5523 * operating frequency for the active connection with the given peer.
5524 *
5525 * Return: 0 on success and errno on failure
5526 */
5527static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5528 struct wireless_dev *wdev,
5529 const void *data,
5530 int data_len)
5531{
5532 int ret = 0;
5533
5534 cds_ssr_protect(__func__);
5535 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5536 wdev, data, data_len);
5537 cds_ssr_unprotect(__func__);
5538
5539 return ret;
5540}
5541
Peng Xu278d0122015-09-24 16:34:17 -07005542static const struct
5543nla_policy
5544qca_wlan_vendor_ota_test_policy
5545[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5546 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5547};
5548
5549/**
5550 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5551 * @wiphy: Pointer to wireless phy
5552 * @wdev: Pointer to wireless device
5553 * @data: Pointer to data
5554 * @data_len: Data length
5555 *
5556 * Return: 0 on success, negative errno on failure
5557 */
5558static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5559 struct wireless_dev *wdev,
5560 const void *data,
5561 int data_len)
5562{
5563 struct net_device *dev = wdev->netdev;
5564 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5565 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5566 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5567 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5568 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305569 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005570 uint32_t current_roam_state;
5571
Jeff Johnson1f61b612016-02-12 16:28:33 -08005572 ENTER_DEV(dev);
5573
Anurag Chouhan6d760662016-02-20 16:05:43 +05305574 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005575 hdd_err("Command not allowed in FTM mode");
5576 return -EPERM;
5577 }
5578
5579 if (0 != wlan_hdd_validate_context(hdd_ctx))
5580 return -EINVAL;
5581
5582 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5583 data, data_len,
5584 qca_wlan_vendor_ota_test_policy)) {
5585 hdd_err("invalid attr");
5586 return -EINVAL;
5587 }
5588
5589 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5590 hdd_err("attr ota test failed");
5591 return -EINVAL;
5592 }
5593
5594 ota_enable = nla_get_u8(
5595 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5596
5597 hdd_info(" OTA test enable = %d", ota_enable);
5598 if (ota_enable != 1) {
5599 hdd_err("Invalid value, only enable test mode is supported!");
5600 return -EINVAL;
5601 }
5602
5603 current_roam_state =
5604 sme_get_current_roam_state(hal, adapter->sessionId);
5605 status = sme_stop_roaming(hal, adapter->sessionId,
5606 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305607 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005608 hdd_err("Enable/Disable roaming failed");
5609 return -EINVAL;
5610 }
5611
5612 status = sme_ps_enable_disable(hal, adapter->sessionId,
5613 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305614 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005615 hdd_err("Enable/Disable power save failed");
5616 /* restore previous roaming setting */
5617 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5618 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5619 status = sme_start_roaming(hal, adapter->sessionId,
5620 eCsrHddIssued);
5621 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5622 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5623 status = sme_stop_roaming(hal, adapter->sessionId,
5624 eCsrHddIssued);
5625
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305626 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005627 hdd_err("Restoring roaming state failed");
5628
5629 return -EINVAL;
5630 }
5631
5632
5633 return 0;
5634}
5635
5636/**
5637 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5638 * @wiphy: Pointer to wireless phy
5639 * @wdev: Pointer to wireless device
5640 * @data: Pointer to data
5641 * @data_len: Data length
5642 *
5643 * Return: 0 on success, negative errno on failure
5644 */
5645static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5646 struct wireless_dev *wdev,
5647 const void *data,
5648 int data_len)
5649{
5650 int ret = 0;
5651
5652 cds_ssr_protect(__func__);
5653 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5654 cds_ssr_unprotect(__func__);
5655
5656 return ret;
5657}
5658
Peng Xu4d67c8f2015-10-16 16:02:26 -07005659/**
5660 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5661 * @wiphy: Pointer to wireless phy
5662 * @wdev: Pointer to wireless device
5663 * @data: Pointer to data
5664 * @data_len: Data length
5665 *
5666 * Return: 0 on success, negative errno on failure
5667 */
5668static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5669 struct wireless_dev *wdev,
5670 const void *data,
5671 int data_len)
5672{
5673 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5674 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005675 hdd_adapter_t *adapter;
5676 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005677 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5678 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005679 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005680
Jeff Johnson1f61b612016-02-12 16:28:33 -08005681 ENTER_DEV(dev);
5682
Peng Xu4d67c8f2015-10-16 16:02:26 -07005683 ret = wlan_hdd_validate_context(hdd_ctx);
5684 if (ret)
5685 return ret;
5686
5687 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5688
5689 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5690 data, data_len, NULL)) {
5691 hdd_err("Invalid ATTR");
5692 return -EINVAL;
5693 }
5694
5695 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5696 hdd_err("attr tx power scale failed");
5697 return -EINVAL;
5698 }
5699
5700 scale_value = nla_get_u8(tb
5701 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5702
5703 if (scale_value > MAX_TXPOWER_SCALE) {
5704 hdd_err("Invalid tx power scale level");
5705 return -EINVAL;
5706 }
5707
Peng Xu62c8c432016-05-09 15:23:02 -07005708 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005709
Peng Xu62c8c432016-05-09 15:23:02 -07005710 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005711 hdd_err("Set tx power scale failed");
5712 return -EINVAL;
5713 }
5714
5715 return 0;
5716}
5717
5718/**
5719 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5720 * @wiphy: Pointer to wireless phy
5721 * @wdev: Pointer to wireless device
5722 * @data: Pointer to data
5723 * @data_len: Data length
5724 *
5725 * Return: 0 on success, negative errno on failure
5726 */
5727static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5728 struct wireless_dev *wdev,
5729 const void *data,
5730 int data_len)
5731{
Peng Xu62c8c432016-05-09 15:23:02 -07005732 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005733
5734 cds_ssr_protect(__func__);
5735 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5736 data, data_len);
5737 cds_ssr_unprotect(__func__);
5738
5739 return ret;
5740}
5741
5742/**
5743 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5744 * @wiphy: Pointer to wireless phy
5745 * @wdev: Pointer to wireless device
5746 * @data: Pointer to data
5747 * @data_len: Data length
5748 *
5749 * Return: 0 on success, negative errno on failure
5750 */
5751static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5752 struct wireless_dev *wdev,
5753 const void *data,
5754 int data_len)
5755{
5756 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5757 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005758 hdd_adapter_t *adapter;
5759 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005760 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5761 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005762 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005763
Jeff Johnson1f61b612016-02-12 16:28:33 -08005764 ENTER_DEV(dev);
5765
Peng Xu4d67c8f2015-10-16 16:02:26 -07005766 ret = wlan_hdd_validate_context(hdd_ctx);
5767 if (ret)
5768 return ret;
5769
5770 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5771
5772 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5773 data, data_len, NULL)) {
5774 hdd_err("Invalid ATTR");
5775 return -EINVAL;
5776 }
5777
5778 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5779 hdd_err("attr tx power decrease db value failed");
5780 return -EINVAL;
5781 }
5782
5783 scale_value = nla_get_u8(tb
5784 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5785
Peng Xu62c8c432016-05-09 15:23:02 -07005786 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5787 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005788
Peng Xu62c8c432016-05-09 15:23:02 -07005789 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005790 hdd_err("Set tx power decrease db failed");
5791 return -EINVAL;
5792 }
5793
5794 return 0;
5795}
5796
5797/**
5798 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5799 * @wiphy: Pointer to wireless phy
5800 * @wdev: Pointer to wireless device
5801 * @data: Pointer to data
5802 * @data_len: Data length
5803 *
5804 * Return: 0 on success, negative errno on failure
5805 */
5806static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5807 struct wireless_dev *wdev,
5808 const void *data,
5809 int data_len)
5810{
Peng Xu62c8c432016-05-09 15:23:02 -07005811 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005812
5813 cds_ssr_protect(__func__);
5814 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5815 data, data_len);
5816 cds_ssr_unprotect(__func__);
5817
5818 return ret;
5819}
Peng Xu8fdaa492016-06-22 10:20:47 -07005820
5821/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305822 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5823 * @wiphy: Pointer to wireless phy
5824 * @wdev: Pointer to wireless device
5825 * @data: Pointer to data
5826 * @data_len: Data length
5827 *
5828 * Processes the conditional channel switch request and invokes the helper
5829 * APIs to process the channel switch request.
5830 *
5831 * Return: 0 on success, negative errno on failure
5832 */
5833static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5834 struct wireless_dev *wdev,
5835 const void *data,
5836 int data_len)
5837{
5838 int ret;
5839 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5840 struct net_device *dev = wdev->netdev;
5841 hdd_adapter_t *adapter;
5842 struct nlattr
5843 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5844 uint32_t freq_len, i;
5845 uint32_t *freq;
5846 uint8_t chans[QDF_MAX_NUM_CHAN];
5847
5848 ENTER_DEV(dev);
5849
5850 ret = wlan_hdd_validate_context(hdd_ctx);
5851 if (ret)
5852 return ret;
5853
5854 if (!hdd_ctx->config->enableDFSMasterCap) {
5855 hdd_err("DFS master capability is not present in the driver");
5856 return -EINVAL;
5857 }
5858
5859 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5860 hdd_err("Command not allowed in FTM mode");
5861 return -EPERM;
5862 }
5863
5864 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5865 if (adapter->device_mode != QDF_SAP_MODE) {
5866 hdd_err("Invalid device mode %d", adapter->device_mode);
5867 return -EINVAL;
5868 }
5869
5870 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
5871 data, data_len, NULL)) {
5872 hdd_err("Invalid ATTR");
5873 return -EINVAL;
5874 }
5875
5876 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
5877 hdd_err("Frequency list is missing");
5878 return -EINVAL;
5879 }
5880
5881 freq_len = nla_len(
5882 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
5883 sizeof(uint32_t);
5884
5885 if (freq_len > QDF_MAX_NUM_CHAN) {
5886 hdd_err("insufficient space to hold channels");
5887 return -ENOMEM;
5888 }
5889
5890 hdd_debug("freq_len=%d", freq_len);
5891
5892 freq = nla_data(
5893 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
5894
5895
5896 for (i = 0; i < freq_len; i++) {
5897 if (freq[i] == 0)
5898 chans[i] = 0;
5899 else
5900 chans[i] = ieee80211_frequency_to_channel(freq[i]);
5901
5902 hdd_debug("freq[%d]=%d", i, freq[i]);
5903 }
5904
5905 /*
5906 * The input frequency list from user space is designed to be a
5907 * priority based frequency list. This is only to accommodate any
5908 * future request. But, current requirement is only to perform CAC
5909 * on a single channel. So, the first entry from the list is picked.
5910 *
5911 * If channel is zero, any channel in the available outdoor regulatory
5912 * domain will be selected.
5913 */
5914 ret = wlan_hdd_request_pre_cac(chans[0]);
5915 if (ret) {
5916 hdd_err("pre cac request failed with reason:%d", ret);
5917 return ret;
5918 }
5919
5920 return 0;
5921}
5922
5923/**
Peng Xu8fdaa492016-06-22 10:20:47 -07005924 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
5925 * @wiphy: Pointer to wireless phy
5926 * @wdev: Pointer to wireless device
5927 * @data: Pointer to data
5928 * @data_len: Data length
5929 *
5930 * This function is to process the p2p listen offload start vendor
5931 * command. It parses the input parameters and invoke WMA API to
5932 * send the command to firmware.
5933 *
5934 * Return: 0 on success, negative errno on failure
5935 */
5936static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
5937 struct wireless_dev *wdev,
5938 const void *data,
5939 int data_len)
5940{
5941 int ret;
5942 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5943 struct net_device *dev = wdev->netdev;
5944 hdd_adapter_t *adapter;
5945 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
5946 struct sir_p2p_lo_start params;
5947 QDF_STATUS status;
5948
5949 ENTER_DEV(dev);
5950
5951 ret = wlan_hdd_validate_context(hdd_ctx);
5952 if (ret)
5953 return ret;
5954
5955 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5956 hdd_err("Command not allowed in FTM mode");
5957 return -EPERM;
5958 }
5959
5960 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5961 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
5962 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
5963 (adapter->device_mode != QDF_P2P_GO_MODE)) {
5964 hdd_err("Invalid device mode %d", adapter->device_mode);
5965 return -EINVAL;
5966 }
5967
5968 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
5969 data, data_len, NULL)) {
5970 hdd_err("Invalid ATTR");
5971 return -EINVAL;
5972 }
5973
5974 memset(&params, 0, sizeof(params));
5975
5976 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
5977 params.ctl_flags = 1; /* set to default value */
5978 else
5979 params.ctl_flags = nla_get_u32(tb
5980 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
5981
5982 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
5983 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
5984 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
5985 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
5986 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
5987 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
5988 hdd_err("Attribute parsing failed");
5989 return -EINVAL;
5990 }
5991
5992 params.vdev_id = adapter->sessionId;
5993 params.freq = nla_get_u32(tb
5994 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
5995 if ((params.freq != 2412) && (params.freq != 2437) &&
5996 (params.freq != 2462)) {
5997 hdd_err("Invalid listening channel: %d", params.freq);
5998 return -EINVAL;
5999 }
6000
6001 params.period = nla_get_u32(tb
6002 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6003 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6004 hdd_err("Invalid period: %d", params.period);
6005 return -EINVAL;
6006 }
6007
6008 params.interval = nla_get_u32(tb
6009 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6010 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6011 hdd_err("Invalid interval: %d", params.interval);
6012 return -EINVAL;
6013 }
6014
6015 params.count = nla_get_u32(tb
6016 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
6017 if (!((params.count > 0) && (params.count < UINT_MAX))) {
6018 hdd_err("Invalid count: %d", params.count);
6019 return -EINVAL;
6020 }
6021
6022 params.device_types = nla_data(tb
6023 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6024 if (params.device_types == NULL) {
6025 hdd_err("Invalid device types");
6026 return -EINVAL;
6027 }
6028
6029 params.dev_types_len = nla_len(tb
6030 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6031 if (params.dev_types_len < 8) {
6032 hdd_err("Invalid device type length: %d", params.dev_types_len);
6033 return -EINVAL;
6034 }
6035
6036 params.probe_resp_tmplt = nla_data(tb
6037 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6038 if (params.probe_resp_tmplt == NULL) {
6039 hdd_err("Invalid probe response template");
6040 return -EINVAL;
6041 }
6042
6043 params.probe_resp_len = nla_len(tb
6044 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6045 if (params.probe_resp_len == 0) {
6046 hdd_err("Invalid probe resp template length: %d",
6047 params.probe_resp_len);
6048 return -EINVAL;
6049 }
6050
6051 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6052 params.freq, params.period, params.interval, params.count);
6053
6054 status = wma_p2p_lo_start(&params);
6055
6056 if (!QDF_IS_STATUS_SUCCESS(status)) {
6057 hdd_err("P2P LO start failed");
6058 return -EINVAL;
6059 }
6060
6061 return 0;
6062}
6063
6064
6065/**
6066 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6067 * @wiphy: Pointer to wireless phy
6068 * @wdev: Pointer to wireless device
6069 * @data: Pointer to data
6070 * @data_len: Data length
6071 *
6072 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6073 * to process p2p listen offload start vendor command.
6074 *
6075 * Return: 0 on success, negative errno on failure
6076 */
6077static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6078 struct wireless_dev *wdev,
6079 const void *data,
6080 int data_len)
6081{
6082 int ret = 0;
6083
6084 cds_ssr_protect(__func__);
6085 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6086 data, data_len);
6087 cds_ssr_unprotect(__func__);
6088
6089 return ret;
6090}
6091
6092/**
6093 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6094 * @wiphy: Pointer to wireless phy
6095 * @wdev: Pointer to wireless device
6096 * @data: Pointer to data
6097 * @data_len: Data length
6098 *
6099 * This function is to process the p2p listen offload stop vendor
6100 * command. It invokes WMA API to send command to firmware.
6101 *
6102 * Return: 0 on success, negative errno on failure
6103 */
6104static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6105 struct wireless_dev *wdev,
6106 const void *data,
6107 int data_len)
6108{
6109 QDF_STATUS status;
6110 hdd_adapter_t *adapter;
6111 struct net_device *dev = wdev->netdev;
6112
6113 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6114 hdd_err("Command not allowed in FTM mode");
6115 return -EPERM;
6116 }
6117
6118 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6119 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6120 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6121 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6122 hdd_err("Invalid device mode");
6123 return -EINVAL;
6124 }
6125
6126 status = wma_p2p_lo_stop(adapter->sessionId);
6127
6128 if (!QDF_IS_STATUS_SUCCESS(status)) {
6129 hdd_err("P2P LO stop failed");
6130 return -EINVAL;
6131 }
6132
6133 return 0;
6134}
6135
6136/**
6137 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6138 * @wiphy: Pointer to wireless phy
6139 * @wdev: Pointer to wireless device
6140 * @data: Pointer to data
6141 * @data_len: Data length
6142 *
6143 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6144 * to process p2p listen offload stop vendor command.
6145 *
6146 * Return: 0 on success, negative errno on failure
6147 */
6148static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6149 struct wireless_dev *wdev,
6150 const void *data,
6151 int data_len)
6152{
6153 int ret = 0;
6154
6155 cds_ssr_protect(__func__);
6156 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6157 data, data_len);
6158 cds_ssr_unprotect(__func__);
6159
6160 return ret;
6161}
6162
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306163/**
6164 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6165 * @wiphy: Pointer to wireless phy
6166 * @wdev: Pointer to wireless device
6167 * @data: Pointer to data
6168 * @data_len: Data length
6169 *
6170 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6171 * to process the conditional channel switch request.
6172 *
6173 * Return: 0 on success, negative errno on failure
6174 */
6175static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6176 struct wireless_dev *wdev,
6177 const void *data,
6178 int data_len)
6179{
6180 int ret;
6181
6182 cds_ssr_protect(__func__);
6183 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6184 data, data_len);
6185 cds_ssr_unprotect(__func__);
6186
6187 return ret;
6188}
6189
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306190/*
6191 * define short names for the global vendor params
6192 * used by __wlan_hdd_cfg80211_bpf_offload()
6193 */
6194#define BPF_INVALID \
6195 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6196#define BPF_SET_RESET \
6197 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6198#define BPF_VERSION \
6199 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6200#define BPF_FILTER_ID \
6201 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6202#define BPF_PACKET_SIZE \
6203 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6204#define BPF_CURRENT_OFFSET \
6205 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6206#define BPF_PROGRAM \
6207 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6208#define BPF_MAX \
6209 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006210
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306211static const struct nla_policy
6212wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6213 [BPF_SET_RESET] = {.type = NLA_U32},
6214 [BPF_VERSION] = {.type = NLA_U32},
6215 [BPF_FILTER_ID] = {.type = NLA_U32},
6216 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6217 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6218 [BPF_PROGRAM] = {.type = NLA_U8},
6219};
6220
6221/**
6222 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6223 * @hdd_context: hdd_context
6224 * @bpf_get_offload: struct for get offload
6225 *
6226 * This function receives the response/data from the lower layer and
6227 * checks to see if the thread is still waiting then post the results to
6228 * upper layer, if the request has timed out then ignore.
6229 *
6230 * Return: None
6231 */
6232void hdd_get_bpf_offload_cb(void *hdd_context,
6233 struct sir_bpf_get_offload *data)
6234{
6235 hdd_context_t *hdd_ctx = hdd_context;
6236 struct hdd_bpf_context *context;
6237
6238 ENTER();
6239
6240 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006241 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306242 data);
6243 return;
6244 }
6245
6246 spin_lock(&hdd_context_lock);
6247
6248 context = &bpf_context;
6249 /* The caller presumably timed out so there is nothing we can do */
6250 if (context->magic != BPF_CONTEXT_MAGIC) {
6251 spin_unlock(&hdd_context_lock);
6252 return;
6253 }
6254
6255 /* context is valid so caller is still waiting */
6256 /* paranoia: invalidate the magic */
6257 context->magic = 0;
6258
6259 context->capability_response = *data;
6260 complete(&context->completion);
6261
6262 spin_unlock(&hdd_context_lock);
6263
6264 return;
6265}
6266
6267/**
6268 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6269 * @hdd_context: hdd_context
6270 * @bpf_get_offload: struct for get offload
6271 *
6272 * Return: 0 on success, error number otherwise.
6273 */
6274static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6275 struct sir_bpf_get_offload *bpf_get_offload)
6276{
6277 struct sk_buff *skb;
6278 uint32_t nl_buf_len;
6279
6280 ENTER();
6281
6282 nl_buf_len = NLMSG_HDRLEN;
6283 nl_buf_len +=
6284 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6285 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6286
6287 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6288 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006289 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306290 return -ENOMEM;
6291 }
6292
Jeff Johnson77848112016-06-29 14:52:06 -07006293 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306294 bpf_get_offload->bpf_version,
6295 bpf_get_offload->max_bytes_for_bpf_inst);
6296
6297 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6298 bpf_get_offload->max_bytes_for_bpf_inst) ||
6299 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006300 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306301 goto nla_put_failure;
6302 }
6303
6304 cfg80211_vendor_cmd_reply(skb);
6305 EXIT();
6306 return 0;
6307
6308nla_put_failure:
6309 kfree_skb(skb);
6310 return -EINVAL;
6311}
6312
6313/**
6314 * hdd_get_bpf_offload - Get BPF offload Capabilities
6315 * @hdd_ctx: Hdd context
6316 *
6317 * Return: 0 on success, errno on failure
6318 */
6319static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6320{
6321 unsigned long rc;
6322 struct hdd_bpf_context *context;
6323 QDF_STATUS status;
6324 int ret;
6325
6326 ENTER();
6327
6328 spin_lock(&hdd_context_lock);
6329 context = &bpf_context;
6330 context->magic = BPF_CONTEXT_MAGIC;
6331 INIT_COMPLETION(context->completion);
6332 spin_unlock(&hdd_context_lock);
6333
6334 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6335 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006336 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306337 return -EINVAL;
6338 }
6339 /* request was sent -- wait for the response */
6340 rc = wait_for_completion_timeout(&context->completion,
6341 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6342 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006343 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306344 spin_lock(&hdd_context_lock);
6345 context->magic = 0;
6346 spin_unlock(&hdd_context_lock);
6347
6348 return -ETIMEDOUT;
6349 }
6350 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6351 &bpf_context.capability_response);
6352 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006353 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306354
6355 EXIT();
6356 return ret;
6357}
6358
6359/**
6360 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6361 * @hdd_ctx: Hdd context
6362 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306363 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306364 *
6365 * Return: 0 on success; errno on failure
6366 */
6367static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6368 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306369 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306370{
6371 struct sir_bpf_set_offload *bpf_set_offload;
6372 QDF_STATUS status;
6373 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306374 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306375
6376 ENTER();
6377
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306378 if (adapter->device_mode == QDF_STA_MODE ||
6379 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6380 if (!hdd_conn_is_connected(
6381 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6382 hdd_err("Not in Connected state!");
6383 return -ENOTSUPP;
6384 }
6385 }
6386
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306387 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6388 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006389 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306390 return -ENOMEM;
6391 }
6392 qdf_mem_zero(bpf_set_offload, sizeof(*bpf_set_offload));
6393
6394 /* Parse and fetch bpf packet size */
6395 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006396 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306397 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306398 goto fail;
6399 }
6400 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6401
6402 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006403 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306404 goto post_sme;
6405 }
6406
6407 /* Parse and fetch bpf program */
6408 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006409 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306410 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306411 goto fail;
6412 }
6413
6414 prog_len = nla_len(tb[BPF_PROGRAM]);
6415 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306416
6417 if (bpf_set_offload->program == NULL) {
6418 hdd_err("qdf_mem_malloc failed for bpf offload program");
6419 ret = -ENOMEM;
6420 goto fail;
6421 }
6422
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306423 bpf_set_offload->current_length = prog_len;
6424 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306425 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306426
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306427 hdd_info("BPF set instructions");
6428 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6429 bpf_set_offload->program, prog_len);
6430
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306431 /* Parse and fetch filter Id */
6432 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006433 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306434 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306435 goto fail;
6436 }
6437 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6438
6439 /* Parse and fetch current offset */
6440 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006441 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306442 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306443 goto fail;
6444 }
6445 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6446
6447post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006448 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 +05306449 bpf_set_offload->session_id,
6450 bpf_set_offload->version,
6451 bpf_set_offload->filter_id,
6452 bpf_set_offload->total_length,
6453 bpf_set_offload->current_length,
6454 bpf_set_offload->current_offset);
6455
6456 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6457 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006458 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306459 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306460 goto fail;
6461 }
6462 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306463
6464fail:
6465 if (bpf_set_offload->current_length)
6466 qdf_mem_free(bpf_set_offload->program);
6467 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306468 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306469}
6470
6471/**
6472 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6473 * @wiphy: wiphy structure pointer
6474 * @wdev: Wireless device structure pointer
6475 * @data: Pointer to the data received
6476 * @data_len: Length of @data
6477 *
6478 * Return: 0 on success; errno on failure
6479 */
6480static int
6481__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6482 struct wireless_dev *wdev,
6483 const void *data, int data_len)
6484{
6485 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6486 struct net_device *dev = wdev->netdev;
6487 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6488 struct nlattr *tb[BPF_MAX + 1];
6489 int ret_val, packet_filter_subcmd;
6490
6491 ENTER();
6492
6493 ret_val = wlan_hdd_validate_context(hdd_ctx);
6494 if (ret_val)
6495 return ret_val;
6496
6497 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006498 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306499 return -EINVAL;
6500 }
6501
6502 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006503 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306504 return -ENOTSUPP;
6505 }
6506
6507 if (nla_parse(tb, BPF_MAX, data, data_len,
6508 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006509 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306510 return -EINVAL;
6511 }
6512
6513 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006514 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306515 return -EINVAL;
6516 }
6517
6518 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6519
6520 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6521 return hdd_get_bpf_offload(hdd_ctx);
6522 else
6523 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306524 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306525}
6526
6527/**
6528 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6529 * @wiphy: wiphy structure pointer
6530 * @wdev: Wireless device structure pointer
6531 * @data: Pointer to the data received
6532 * @data_len: Length of @data
6533 *
6534 * Return: 0 on success; errno on failure
6535 */
6536
6537static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6538 struct wireless_dev *wdev,
6539 const void *data, int data_len)
6540{
6541 int ret;
6542
6543 cds_ssr_protect(__func__);
6544 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6545 cds_ssr_unprotect(__func__);
6546
6547 return ret;
6548}
6549
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306550/**
6551 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6552 * @pre_cac_adapter: AP adapter used for pre cac
6553 * @status: Status (true or false)
6554 * @handle: Global handle
6555 *
6556 * Sets the status of pre cac i.e., whether the pre cac is active or not
6557 *
6558 * Return: Zero on success, non-zero on failure
6559 */
6560static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6561 bool status, tHalHandle handle)
6562{
6563 QDF_STATUS ret;
6564
6565 ret = wlan_sap_set_pre_cac_status(
6566 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6567 if (QDF_IS_STATUS_ERROR(ret))
6568 return -EINVAL;
6569
6570 return 0;
6571}
6572
6573/**
6574 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6575 * @ap_adapter: AP adapter
6576 * @chan_before_pre_cac: Channel
6577 *
6578 * Saves the channel which the AP was beaconing on before moving to the pre
6579 * cac channel. If radar is detected on the pre cac channel, this saved
6580 * channel will be used for AP operations.
6581 *
6582 * Return: Zero on success, non-zero on failure
6583 */
6584static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6585 uint8_t chan_before_pre_cac)
6586{
6587 QDF_STATUS ret;
6588
6589 ret = wlan_sap_set_chan_before_pre_cac(
6590 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6591 if (QDF_IS_STATUS_ERROR(ret))
6592 return -EINVAL;
6593
6594 return 0;
6595}
6596
6597/**
6598 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6599 * @ap_adapter: AP adapter
6600 * @nol: Non-occupancy list
6601 * @nol_len: Length of NOL
6602 *
6603 * Get the NOL for SAP
6604 *
6605 * Return: Zero on success, non-zero on failure
6606 */
6607static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6608 uint32_t *nol_len)
6609{
6610 QDF_STATUS ret;
6611
6612 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6613 nol, nol_len);
6614 if (QDF_IS_STATUS_ERROR(ret))
6615 return -EINVAL;
6616
6617 return 0;
6618}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306619
6620/**
6621 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6622 * @hdd_ctx: HDD context
6623 * @ap_adapter: AP adapter
6624 * @channel: Channel requested by userspace
6625 * @pre_cac_chan: Pointer to the pre CAC channel
6626 *
6627 * Validates the channel provided by userspace. If user provided channel 0,
6628 * a valid outdoor channel must be selected from the regulatory channel.
6629 *
6630 * Return: Zero on success and non zero value on error
6631 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006632static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6633 hdd_adapter_t *ap_adapter,
6634 uint8_t channel,
6635 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306636{
6637 uint32_t i, j;
6638 QDF_STATUS status;
6639 int ret;
6640 uint8_t nol[QDF_MAX_NUM_CHAN];
6641 uint32_t nol_len = 0, weight_len = 0;
6642 bool found;
6643 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6644 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6645 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6646
6647 if (0 == channel) {
6648 /* Channel is not obtained from PCL because PCL may not have
6649 * the entire channel list. For example: if SAP is up on
6650 * channel 6 and PCL is queried for the next SAP interface,
6651 * if SCC is preferred, the PCL will contain only the channel
6652 * 6. But, we are in need of a DFS channel. So, going with the
6653 * first channel from the valid channel list.
6654 */
6655 status = cds_get_valid_chans(channel_list, &len);
6656 if (QDF_IS_STATUS_ERROR(status)) {
6657 hdd_err("Failed to get channel list");
6658 return -EINVAL;
6659 }
6660 cds_update_with_safe_channel_list(channel_list, &len,
6661 pcl_weights, weight_len);
6662 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6663 for (i = 0; i < len; i++) {
6664 found = false;
6665 for (j = 0; j < nol_len; j++) {
6666 if (channel_list[i] == nol[j]) {
6667 found = true;
6668 break;
6669 }
6670 }
6671 if (found)
6672 continue;
6673 if (CDS_IS_DFS_CH(channel_list[i])) {
6674 *pre_cac_chan = channel_list[i];
6675 break;
6676 }
6677 }
6678 if (*pre_cac_chan == 0) {
6679 hdd_err("unable to find outdoor channel");
6680 return -EINVAL;
6681 }
6682 } else {
6683 /* Only when driver selects a channel, check is done for
6684 * unnsafe and NOL channels. When user provides a fixed channel
6685 * the user is expected to take care of this.
6686 */
6687 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6688 !CDS_IS_DFS_CH(channel)) {
6689 hdd_err("Invalid channel for pre cac:%d", channel);
6690 return -EINVAL;
6691 } else {
6692 *pre_cac_chan = channel;
6693 }
6694 }
6695 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6696 return 0;
6697}
6698
6699/**
6700 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6701 * @channel: Channel option provided by userspace
6702 *
6703 * Sets the driver to the required hardware mode and start an adapater for
6704 * pre CAC which will mimic an AP.
6705 *
6706 * Return: Zero on success, non-zero value on error
6707 */
6708int wlan_hdd_request_pre_cac(uint8_t channel)
6709{
6710 uint8_t pre_cac_chan = 0;
6711 hdd_context_t *hdd_ctx;
6712 int ret;
6713 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6714 hdd_ap_ctx_t *hdd_ap_ctx;
6715 QDF_STATUS status;
6716 struct wiphy *wiphy;
6717 struct net_device *dev;
6718 struct cfg80211_chan_def chandef;
6719 enum nl80211_channel_type channel_type;
6720 uint32_t freq;
6721 struct ieee80211_channel *chan;
6722 tHalHandle handle;
6723 bool val;
6724
6725 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6726 if (0 != wlan_hdd_validate_context(hdd_ctx))
6727 return -EINVAL;
6728
6729 if (cds_get_connection_count() > 1) {
6730 hdd_err("pre cac not allowed in concurrency");
6731 return -EINVAL;
6732 }
6733
6734 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6735 if (!ap_adapter) {
6736 hdd_err("unable to get SAP adapter");
6737 return -EINVAL;
6738 }
6739
6740 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6741 if (!handle) {
6742 hdd_err("Invalid handle");
6743 return -EINVAL;
6744 }
6745
6746 val = wlan_sap_is_pre_cac_active(handle);
6747 if (val) {
6748 hdd_err("pre cac is already in progress");
6749 return -EINVAL;
6750 }
6751
6752 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6753 if (!hdd_ap_ctx) {
6754 hdd_err("SAP context is NULL");
6755 return -EINVAL;
6756 }
6757
6758 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6759 hdd_err("SAP is already on DFS channel:%d",
6760 hdd_ap_ctx->operatingChannel);
6761 return -EINVAL;
6762 }
6763
6764 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6765 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6766 hdd_ap_ctx->operatingChannel);
6767 return -EINVAL;
6768 }
6769
6770 hdd_info("channel:%d", channel);
6771
6772 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6773 &pre_cac_chan);
6774 if (ret != 0)
6775 return ret;
6776
6777 /* Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
6778 * connection update should result in DBS mode
6779 */
6780 status = cds_update_and_wait_for_connection_update(
6781 ap_adapter->sessionId,
6782 pre_cac_chan,
6783 SIR_UPDATE_REASON_PRE_CAC);
6784 if (QDF_IS_STATUS_ERROR(status)) {
6785 hdd_err("error in moving to DBS mode");
6786 return -EINVAL;
6787 }
6788
6789 hdd_debug("starting pre cac SAP adapter");
6790
6791 /* Starting a SAP adapter:
6792 * Instead of opening an adapter, we could just do a SME open session
6793 * for AP type. But, start BSS would still need an adapter.
6794 * So, this option is not taken.
6795 *
6796 * hdd open adapter is going to register this precac interface with
6797 * user space. This interface though exposed to user space will be in
6798 * DOWN state. Consideration was done to avoid this registration to the
6799 * user space. But, as part of SAP operations multiple events are sent
6800 * to user space. Some of these events received from unregistered
6801 * interface was causing crashes. So, retaining the registration.
6802 *
6803 * So, this interface would remain registered and will remain in DOWN
6804 * state for the CAC duration. We will add notes in the feature
6805 * announcement to not use this temporary interface for any activity
6806 * from user space.
6807 */
6808 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
6809 wlan_hdd_get_intf_addr(hdd_ctx),
6810 NET_NAME_UNKNOWN, true);
6811 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306812 hdd_err("error opening the pre cac adapter");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306813 return -EINVAL;
6814 }
6815
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306816 /*
6817 * This interface is internally created by the driver. So, no interface
6818 * up comes for this interface from user space and hence starting
6819 * the adapter internally.
6820 */
6821 if (hdd_start_adapter(pre_cac_adapter)) {
6822 hdd_err("error starting the pre cac adapter");
6823 goto close_pre_cac_adapter;
6824 }
6825
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306826 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6827
6828 wiphy = hdd_ctx->wiphy;
6829 dev = pre_cac_adapter->dev;
6830
6831 /* Since this is only a dummy interface lets us use the IEs from the
6832 * other active SAP interface. In regular scenarios, these IEs would
6833 * come from the user space entity
6834 */
6835 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6836 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6837 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6838 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306839 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306840 }
6841 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6842 ap_adapter->sessionCtx.ap.beacon,
6843 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6844 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6845 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6846 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6847 ap_adapter->sessionCtx.ap.sapConfig.authType;
6848
6849 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6850 * to operate on the same bandwidth as that of the 2.4GHz operations.
6851 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6852 */
6853 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6854 case CH_WIDTH_20MHZ:
6855 channel_type = NL80211_CHAN_HT20;
6856 break;
6857 case CH_WIDTH_40MHZ:
6858 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6859 ap_adapter->sessionCtx.ap.sapConfig.channel)
6860 channel_type = NL80211_CHAN_HT40PLUS;
6861 else
6862 channel_type = NL80211_CHAN_HT40MINUS;
6863 break;
6864 default:
6865 channel_type = NL80211_CHAN_NO_HT;
6866 break;
6867 }
6868
6869 freq = cds_chan_to_freq(pre_cac_chan);
6870 chan = __ieee80211_get_channel(wiphy, freq);
6871 if (!chan) {
6872 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306873 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306874 }
6875
6876 cfg80211_chandef_create(&chandef, chan, channel_type);
6877
6878 hdd_debug("orig width:%d channel_type:%d freq:%d",
6879 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
6880 channel_type, freq);
6881
6882 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
6883 if (0 != ret) {
6884 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306885 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306886 }
6887
6888 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
6889 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
6890 eHIDDEN_SSID_NOT_IN_USE, false);
6891 if (QDF_IS_STATUS_ERROR(status)) {
6892 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306893 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306894 }
6895
6896 /*
6897 * The pre cac status is set here. But, it would not be reset explicitly
6898 * anywhere, since after the pre cac success/failure, the pre cac
6899 * adapter itself would be removed.
6900 */
6901 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
6902 if (0 != ret) {
6903 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306904 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306905 }
6906
6907 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
6908 hdd_ap_ctx->operatingChannel);
6909 if (0 != ret) {
6910 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306911 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306912 }
6913
6914 ap_adapter->pre_cac_chan = pre_cac_chan;
6915
6916 return 0;
6917
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306918stop_close_pre_cac_adapter:
6919 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306920 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
6921 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306922close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306923 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
6924 return -EINVAL;
6925}
6926
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306927/**
6928 * hdd_init_bpf_completion() - Initialize the completion event for bpf
6929 *
6930 * Return: None
6931 */
6932void hdd_init_bpf_completion(void)
6933{
6934 init_completion(&bpf_context.completion);
6935}
6936
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306937static const struct nla_policy
6938wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
6939 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
6940};
6941
Agrawal Ashish65634612016-08-18 13:24:32 +05306942static const struct nla_policy
6943wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
6944 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
6945 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
6946};
6947
6948/**
6949 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
6950 * @wiphy: Pointer to wireless phy
6951 * @wdev: Pointer to wireless device
6952 * @data: Pointer to data
6953 * @data_len: Length of @data
6954 *
6955 * This function parses the incoming NL vendor command data attributes and
6956 * updates the SAP context about channel_hint and DFS mode.
6957 * If channel_hint is set, SAP will choose that channel
6958 * as operating channel.
6959 *
6960 * If DFS mode is enabled, driver will include DFS channels
6961 * in ACS else driver will skip DFS channels.
6962 *
6963 * Return: 0 on success, negative errno on failure
6964 */
6965static int
6966__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
6967 struct wireless_dev *wdev,
6968 const void *data, int data_len)
6969{
6970 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6971 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
6972 int ret;
6973 struct acs_dfs_policy *acs_policy;
6974 int mode = DFS_MODE_NONE;
6975 int channel_hint = 0;
6976
6977 ENTER_DEV(wdev->netdev);
6978
6979 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6980 hdd_err("Command not allowed in FTM mode");
6981 return -EINVAL;
6982 }
6983
6984 ret = wlan_hdd_validate_context(hdd_ctx);
6985 if (0 != ret)
6986 return ret;
6987
6988 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
6989 data, data_len,
6990 wlan_hdd_set_acs_dfs_config_policy)) {
6991 hdd_err("invalid attr");
6992 return -EINVAL;
6993 }
6994
6995 acs_policy = &hdd_ctx->acs_policy;
6996 /*
6997 * SCM sends this attribute to restrict SAP from choosing
6998 * DFS channels from ACS.
6999 */
7000 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7001 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7002
7003 if (!IS_DFS_MODE_VALID(mode)) {
7004 hdd_err("attr acs dfs mode is not valid");
7005 return -EINVAL;
7006 }
7007 acs_policy->acs_dfs_mode = mode;
7008
7009 /*
7010 * SCM sends this attribute to provide an active channel,
7011 * to skip redundant ACS between drivers, and save driver start up time
7012 */
7013 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7014 channel_hint = nla_get_u8(
7015 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7016
7017 if (!IS_CHANNEL_VALID(channel_hint)) {
7018 hdd_err("acs channel is not valid");
7019 return -EINVAL;
7020 }
7021 acs_policy->acs_channel = channel_hint;
7022
7023 return 0;
7024}
7025
7026/**
7027 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7028 * @wiphy: wiphy structure pointer
7029 * @wdev: Wireless device structure pointer
7030 * @data: Pointer to the data received
7031 * @data_len: Length of @data
7032 *
7033 * This function parses the incoming NL vendor command data attributes and
7034 * updates the SAP context about channel_hint and DFS mode.
7035 *
7036 * Return: 0 on success; errno on failure
7037 */
7038static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7039 struct wireless_dev *wdev,
7040 const void *data, int data_len)
7041{
7042 int ret;
7043
7044 cds_ssr_protect(__func__);
7045 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7046 cds_ssr_unprotect(__func__);
7047
7048 return ret;
7049}
7050
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307051/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307052 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7053 * @mode : cfg80211 dfs mode
7054 *
7055 * Return: return csr sta roam dfs mode else return NONE
7056 */
7057static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7058 enum dfs_mode mode)
7059{
7060 switch (mode) {
7061 case DFS_MODE_ENABLE:
7062 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7063 break;
7064 case DFS_MODE_DISABLE:
7065 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7066 break;
7067 case DFS_MODE_DEPRIORITIZE:
7068 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7069 break;
7070 default:
7071 hdd_err("STA Roam policy dfs mode is NONE");
7072 return CSR_STA_ROAM_POLICY_NONE;
7073 }
7074}
7075
7076static const struct nla_policy
7077wlan_hdd_set_sta_roam_config_policy[
7078QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7079 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7080 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7081};
7082
7083/**
7084 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7085 * for station connection or roaming.
7086 * @wiphy: Pointer to wireless phy
7087 * @wdev: Pointer to wireless device
7088 * @data: Pointer to data
7089 * @data_len: Length of @data
7090 *
7091 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7092 * channels needs to be skipped in scanning or not.
7093 * If dfs_mode is disabled, driver will not scan DFS channels.
7094 * If skip_unsafe_channels is set, driver will skip unsafe channels
7095 * in Scanning.
7096 *
7097 * Return: 0 on success, negative errno on failure
7098 */
7099static int
7100__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7101 struct wireless_dev *wdev,
7102 const void *data, int data_len)
7103{
7104 struct net_device *dev = wdev->netdev;
7105 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7106 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7107 struct nlattr *tb[
7108 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7109 int ret;
7110 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7111 enum dfs_mode mode = DFS_MODE_NONE;
7112 bool skip_unsafe_channels = false;
7113 QDF_STATUS status;
7114
7115 ENTER_DEV(dev);
7116
7117 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7118 hdd_err("Command not allowed in FTM mode");
7119 return -EINVAL;
7120 }
7121
7122 ret = wlan_hdd_validate_context(hdd_ctx);
7123 if (0 != ret)
7124 return ret;
7125 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7126 data, data_len,
7127 wlan_hdd_set_sta_roam_config_policy)) {
7128 hdd_err("invalid attr");
7129 return -EINVAL;
7130 }
7131 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7132 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7133 if (!IS_DFS_MODE_VALID(mode)) {
7134 hdd_err("attr sta roam dfs mode policy is not valid");
7135 return -EINVAL;
7136 }
7137
7138 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7139
7140 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7141 skip_unsafe_channels = nla_get_u8(
7142 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7143
7144 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7145 skip_unsafe_channels, adapter->sessionId);
7146
7147 if (!QDF_IS_STATUS_SUCCESS(status)) {
7148 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7149 return -EINVAL;
7150 }
7151 return 0;
7152}
7153
7154/**
7155 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7156 * connection and roaming for station.
7157 * @wiphy: wiphy structure pointer
7158 * @wdev: Wireless device structure pointer
7159 * @data: Pointer to the data received
7160 * @data_len: Length of @data
7161 *
7162 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7163 * channels needs to be skipped in scanning or not.
7164 * If dfs_mode is disabled, driver will not scan DFS channels.
7165 * If skip_unsafe_channels is set, driver will skip unsafe channels
7166 * in Scanning.
7167 * Return: 0 on success; errno on failure
7168 */
7169static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7170 struct wireless_dev *wdev,
7171 const void *data, int data_len)
7172{
7173 int ret;
7174
7175 cds_ssr_protect(__func__);
7176 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7177 cds_ssr_unprotect(__func__);
7178
7179 return ret;
7180}
7181
Agrawal Ashish467dde42016-09-08 18:44:22 +05307182#ifdef FEATURE_WLAN_CH_AVOID
7183/**
7184 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7185 * is on unsafe channel.
7186 * @wiphy: wiphy structure pointer
7187 * @wdev: Wireless device structure pointer
7188 * @data: Pointer to the data received
7189 * @data_len: Length of @data
7190 *
7191 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7192 * on any of unsafe channels.
7193 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7194 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7195 *
7196 * Return: 0 on success; errno on failure
7197 */
7198static int
7199__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7200 struct wireless_dev *wdev,
7201 const void *data, int data_len)
7202{
7203 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7204 int ret;
7205 uint16_t unsafe_channel_count;
7206 int unsafe_channel_index;
7207 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7208
7209 ENTER_DEV(wdev->netdev);
7210
7211 if (!qdf_ctx) {
7212 cds_err("qdf_ctx is NULL");
7213 return -EINVAL;
7214 }
7215
7216 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7217 hdd_err("Command not allowed in FTM mode");
7218 return -EINVAL;
7219 }
7220
7221 ret = wlan_hdd_validate_context(hdd_ctx);
7222 if (0 != ret)
7223 return ret;
7224 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7225 &(hdd_ctx->unsafe_channel_count),
7226 sizeof(hdd_ctx->unsafe_channel_list));
7227
7228 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7229 (uint16_t)NUM_CHANNELS);
7230 for (unsafe_channel_index = 0;
7231 unsafe_channel_index < unsafe_channel_count;
7232 unsafe_channel_index++) {
7233 hdd_info("Channel %d is not safe",
7234 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7235 }
7236 hdd_unsafe_channel_restart_sap(hdd_ctx);
7237 return 0;
7238}
7239
7240/**
7241 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7242 * is on unsafe channel.
7243 * @wiphy: wiphy structure pointer
7244 * @wdev: Wireless device structure pointer
7245 * @data: Pointer to the data received
7246 * @data_len: Length of @data
7247 *
7248 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7249 * on any of unsafe channels.
7250 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7251 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7252 *
7253 * Return: 0 on success; errno on failure
7254 */
7255static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7256 struct wireless_dev *wdev,
7257 const void *data, int data_len)
7258{
7259 int ret;
7260
7261 cds_ssr_protect(__func__);
7262 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7263 cds_ssr_unprotect(__func__);
7264
7265 return ret;
7266}
7267
7268#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307269/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307270 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7271 * SAP is on unsafe channel.
7272 * @wiphy: wiphy structure pointer
7273 * @wdev: Wireless device structure pointer
7274 * @data: Pointer to the data received
7275 * @data_len: Length of @data
7276 *
7277 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7278 * driver.
7279 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7280 * will initiate restart of sap.
7281 *
7282 * Return: 0 on success; errno on failure
7283 */
7284static int
7285__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7286 struct wireless_dev *wdev,
7287 const void *data, int data_len)
7288{
7289 struct net_device *ndev = wdev->netdev;
7290 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7291 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7292 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7293 uint8_t config_channel = 0;
7294 hdd_ap_ctx_t *ap_ctx;
7295 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307296 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307297
7298 ENTER();
7299
7300 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007301 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307302 return -EINVAL;
7303 }
7304
7305 ret = wlan_hdd_validate_context(hdd_ctx);
7306 if (0 != ret)
7307 return -EINVAL;
7308
7309 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7310 data, data_len,
7311 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007312 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307313 return -EINVAL;
7314 }
7315
7316 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7317 if (!test_bit(SOFTAP_BSS_STARTED,
7318 &hostapd_adapter->event_flags)) {
7319 hdd_err("SAP is not started yet. Restart sap will be invalid");
7320 return -EINVAL;
7321 }
7322
7323 config_channel =
7324 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7325
7326 if (!((IS_24G_CH(config_channel)) ||
7327 (IS_5G_CH(config_channel)))) {
7328 hdd_err("Channel %d is not valid to restart SAP",
7329 config_channel);
7330 return -ENOTSUPP;
7331 }
7332
7333 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7334 ap_ctx->sapConfig.channel = config_channel;
7335 ap_ctx->sapConfig.ch_params.ch_width =
7336 ap_ctx->sapConfig.ch_width_orig;
7337
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007338 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307339 ap_ctx->sapConfig.sec_ch,
7340 &ap_ctx->sapConfig.ch_params);
7341
7342 cds_restart_sap(hostapd_adapter);
7343 }
7344
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307345 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7346 uint32_t freq_len, i;
7347 uint32_t *freq;
7348 uint8_t chans[QDF_MAX_NUM_CHAN];
7349
7350 hdd_debug("setting mandatory freq/chan list");
7351
7352 freq_len = nla_len(
7353 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7354 sizeof(uint32_t);
7355
7356 if (freq_len > QDF_MAX_NUM_CHAN) {
7357 hdd_err("insufficient space to hold channels");
7358 return -ENOMEM;
7359 }
7360
7361 freq = nla_data(
7362 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7363
7364 hdd_debug("freq_len=%d", freq_len);
7365
7366 for (i = 0; i < freq_len; i++) {
7367 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7368 hdd_debug("freq[%d]=%d", i, freq[i]);
7369 }
7370
7371 status = cds_set_sap_mandatory_channels(chans, freq_len);
7372 if (QDF_IS_STATUS_ERROR(status))
7373 return -EINVAL;
7374 }
7375
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307376 return 0;
7377}
7378
7379/**
7380 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7381 * @wiphy: wiphy structure pointer
7382 * @wdev: Wireless device structure pointer
7383 * @data: Pointer to the data received
7384 * @data_len: Length of @data
7385 *
7386 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7387 * driver.
7388 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7389 * will initiate restart of sap.
7390 *
7391 * Return: 0 on success; errno on failure
7392 */
7393static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7394 struct wireless_dev *wdev,
7395 const void *data, int data_len)
7396{
7397 int ret;
7398
7399 cds_ssr_protect(__func__);
7400 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7401 wdev, data, data_len);
7402 cds_ssr_unprotect(__func__);
7403
7404 return ret;
7405}
7406
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307407#undef BPF_INVALID
7408#undef BPF_SET_RESET
7409#undef BPF_VERSION
7410#undef BPF_ID
7411#undef BPF_PACKET_SIZE
7412#undef BPF_CURRENT_OFFSET
7413#undef BPF_PROGRAM
7414#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307415
7416/**
7417 * define short names for the global vendor params
7418 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7419 */
7420#define PARAM_TOTAL_CMD_EVENT_WAKE \
7421 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7422#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7423 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7424#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7425 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7426#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7427 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7428#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7429 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7430#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7431 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7432#define PARAM_TOTAL_RX_DATA_WAKE \
7433 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7434#define PARAM_RX_UNICAST_CNT \
7435 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7436#define PARAM_RX_MULTICAST_CNT \
7437 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7438#define PARAM_RX_BROADCAST_CNT \
7439 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7440#define PARAM_ICMP_PKT \
7441 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7442#define PARAM_ICMP6_PKT \
7443 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7444#define PARAM_ICMP6_RA \
7445 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7446#define PARAM_ICMP6_NA \
7447 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7448#define PARAM_ICMP6_NS \
7449 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7450#define PARAM_ICMP4_RX_MULTICAST_CNT \
7451 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7452#define PARAM_ICMP6_RX_MULTICAST_CNT \
7453 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7454#define PARAM_OTHER_RX_MULTICAST_CNT \
7455 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
7456
7457
7458/**
7459 * hdd_send_wakelock_stats() - API to send wakelock stats
7460 * @ctx: context to be passed to callback
7461 * @data: data passed to callback
7462 *
7463 * This function is used to send wake lock stats to HAL layer
7464 *
7465 * Return: 0 on success, error number otherwise.
7466 */
7467static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7468 const struct sir_wake_lock_stats *data)
7469{
7470 struct sk_buff *skb;
7471 uint32_t nl_buf_len;
7472 uint32_t total_rx_data_wake, rx_multicast_cnt;
7473 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307474 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307475
7476 ENTER();
7477
7478 nl_buf_len = NLMSG_HDRLEN;
7479 nl_buf_len +=
7480 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7481 (NLMSG_HDRLEN + sizeof(uint32_t));
7482
7483 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7484
7485 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007486 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307487 return -ENOMEM;
7488 }
7489
Jeff Johnson64943bd2016-08-23 13:14:06 -07007490 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307491 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007492 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307493 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007494 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307495 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007496 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307497 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007498 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307499 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007500 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307501 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007502 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307503 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007504 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7505 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307506 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307507
7508 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307509 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307510
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307511 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307512 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307513
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307514 rx_multicast_cnt =
7515 data->wow_ipv4_mcast_wake_up_count +
7516 ipv6_rx_multicast_addr_cnt;
7517
7518 total_rx_data_wake =
7519 data->wow_ucast_wake_up_count +
7520 data->wow_bcast_wake_up_count +
7521 rx_multicast_cnt;
7522
7523 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7524 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7525 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7526 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7527 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7528 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7529 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7530 total_rx_data_wake) ||
7531 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7532 data->wow_ucast_wake_up_count) ||
7533 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7534 rx_multicast_cnt) ||
7535 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7536 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307537 nla_put_u32(skb, PARAM_ICMP_PKT,
7538 data->wow_icmpv4_count) ||
7539 nla_put_u32(skb, PARAM_ICMP6_PKT,
7540 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307541 nla_put_u32(skb, PARAM_ICMP6_RA,
7542 data->wow_ipv6_mcast_ra_stats) ||
7543 nla_put_u32(skb, PARAM_ICMP6_NA,
7544 data->wow_ipv6_mcast_na_stats) ||
7545 nla_put_u32(skb, PARAM_ICMP6_NS,
7546 data->wow_ipv6_mcast_ns_stats) ||
7547 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7548 data->wow_ipv4_mcast_wake_up_count) ||
7549 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7550 ipv6_rx_multicast_addr_cnt) ||
7551 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007552 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307553 goto nla_put_failure;
7554 }
7555
7556 cfg80211_vendor_cmd_reply(skb);
7557
7558 EXIT();
7559 return 0;
7560
7561nla_put_failure:
7562 kfree_skb(skb);
7563 return -EINVAL;
7564}
7565
7566/**
7567 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7568 * @wiphy: wiphy pointer
7569 * @wdev: pointer to struct wireless_dev
7570 * @data: pointer to incoming NL vendor data
7571 * @data_len: length of @data
7572 *
7573 * This function parses the incoming NL vendor command data attributes and
7574 * invokes the SME Api and blocks on a completion variable.
7575 * WMA copies required data and invokes callback
7576 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7577 *
7578 * Return: 0 on success; error number otherwise.
7579 */
7580static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7581 struct wireless_dev *wdev,
7582 const void *data,
7583 int data_len)
7584{
7585 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7586 int status, ret;
7587 struct sir_wake_lock_stats wake_lock_stats;
7588 QDF_STATUS qdf_status;
7589
7590 ENTER();
7591
7592 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007593 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307594 return -EINVAL;
7595 }
7596
7597 status = wlan_hdd_validate_context(hdd_ctx);
7598 if (0 != status)
7599 return -EINVAL;
7600
7601 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7602 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007603 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307604 return -EINVAL;
7605 }
7606
7607 ret = hdd_send_wakelock_stats(hdd_ctx,
7608 &wake_lock_stats);
7609 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007610 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307611
7612 EXIT();
7613 return ret;
7614}
7615
7616/**
7617 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7618 * @wiphy: wiphy pointer
7619 * @wdev: pointer to struct wireless_dev
7620 * @data: pointer to incoming NL vendor data
7621 * @data_len: length of @data
7622 *
7623 * This function parses the incoming NL vendor command data attributes and
7624 * invokes the SME Api and blocks on a completion variable.
7625 * WMA copies required data and invokes callback
7626 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7627 *
7628 * Return: 0 on success; error number otherwise.
7629 */
7630static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7631 struct wireless_dev *wdev,
7632 const void *data, int data_len)
7633{
7634 int ret;
7635
7636 cds_ssr_protect(__func__);
7637 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7638 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007639 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307640
7641 return ret;
7642}
7643
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307644/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307645 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7646 * @wiphy: wiphy structure pointer
7647 * @wdev: Wireless device structure pointer
7648 * @data: Pointer to the data received
7649 * @data_len: Length of @data
7650 *
7651 * This function reads wmi max bus size and fill in the skb with
7652 * NL attributes and send up the NL event.
7653 * Return: 0 on success; errno on failure
7654 */
7655static int
7656__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7657 struct wireless_dev *wdev,
7658 const void *data, int data_len)
7659{
7660 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7661 int ret_val;
7662 struct sk_buff *skb;
7663 uint32_t nl_buf_len;
7664
7665 ENTER();
7666
7667 ret_val = wlan_hdd_validate_context(hdd_ctx);
7668 if (ret_val)
7669 return ret_val;
7670
7671 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7672 hdd_err("Command not allowed in FTM mode");
7673 return -EINVAL;
7674 }
7675
7676 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7677
7678 nl_buf_len = NLMSG_HDRLEN;
7679 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7680
7681 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7682 if (!skb) {
7683 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7684 return -ENOMEM;
7685 }
7686
7687 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7688 hdd_ctx->wmi_max_len)) {
7689 hdd_err("nla put failure");
7690 goto nla_put_failure;
7691 }
7692
7693 cfg80211_vendor_cmd_reply(skb);
7694
7695 EXIT();
7696
7697 return 0;
7698
7699nla_put_failure:
7700 kfree_skb(skb);
7701 return -EINVAL;
7702}
7703
7704/**
7705 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7706 * @wiphy: wiphy structure pointer
7707 * @wdev: Wireless device structure pointer
7708 * @data: Pointer to the data received
7709 * @data_len: Length of @data
7710 *
7711 * Return: 0 on success; errno on failure
7712 */
7713static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7714 struct wireless_dev *wdev,
7715 const void *data, int data_len)
7716{
7717 int ret;
7718
7719 cds_ssr_protect(__func__);
7720 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7721 cds_ssr_unprotect(__func__);
7722
7723 return ret;
7724}
7725
7726/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307727 *__wlan_hdd_cfg80211_setband() - set band
7728 * @wiphy: Pointer to wireless phy
7729 * @wdev: Pointer to wireless device
7730 * @data: Pointer to data
7731 * @data_len: Length of @data
7732 *
7733 * Return: 0 on success, negative errno on failure
7734 */
7735static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7736 struct wireless_dev *wdev,
7737 const void *data, int data_len)
7738{
7739 struct net_device *dev = wdev->netdev;
7740 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7741 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7742 int ret;
7743 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7744 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7745
7746 ENTER();
7747
7748 ret = wlan_hdd_validate_context(hdd_ctx);
7749 if (ret)
7750 return ret;
7751
7752 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7753 hdd_err(FL("Invalid ATTR"));
7754 return -EINVAL;
7755 }
7756
7757 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7758 hdd_err(FL("attr SETBAND_VALUE failed"));
7759 return -EINVAL;
7760 }
7761
7762 ret = hdd_set_band(dev,
7763 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7764
7765 EXIT();
7766 return ret;
7767}
7768
7769/**
7770 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7771 * @wiphy: wiphy structure pointer
7772 * @wdev: Wireless device structure pointer
7773 * @data: Pointer to the data received
7774 * @data_len: Length of @data
7775 *
7776 * Return: 0 on success; errno on failure
7777 */
7778static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7779 struct wireless_dev *wdev,
7780 const void *data, int data_len)
7781{
7782 int ret;
7783
7784 cds_ssr_protect(__func__);
7785 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7786 cds_ssr_unprotect(__func__);
7787
7788 return ret;
7789}
7790
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307791static const struct
7792nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7793 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7794 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7795 .len = QDF_MAC_ADDR_SIZE},
7796};
7797
7798/**
7799 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7800 * @wiphy: Pointer to wireless phy
7801 * @wdev: Pointer to wireless device
7802 * @data: Pointer to data
7803 * @data_len: Length of @data
7804 *
7805 * This function is used to enable/disable roaming using vendor commands
7806 *
7807 * Return: 0 on success, negative errno on failure
7808 */
7809static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7810 struct wireless_dev *wdev,
7811 const void *data, int data_len)
7812{
7813 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7814 struct net_device *dev = wdev->netdev;
7815 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7816 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7817 uint32_t is_fast_roam_enabled;
7818 int ret;
7819
7820 ENTER_DEV(dev);
7821
7822 ret = wlan_hdd_validate_context(hdd_ctx);
7823 if (0 != ret)
7824 return ret;
7825
7826 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7827 hdd_err("Command not allowed in FTM mode");
7828 return -EINVAL;
7829 }
7830
7831 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
7832 qca_wlan_vendor_attr);
7833 if (ret) {
7834 hdd_err("Invalid ATTR");
7835 return -EINVAL;
7836 }
7837
7838 /* Parse and fetch Enable flag */
7839 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
7840 hdd_err("attr enable failed");
7841 return -EINVAL;
7842 }
7843
7844 is_fast_roam_enabled = nla_get_u32(
7845 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
7846 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
7847
7848 /* Update roaming */
7849 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
7850 is_fast_roam_enabled);
7851 if (ret)
7852 hdd_err("sme_config_fast_roaming failed");
7853 EXIT();
7854 return ret;
7855}
7856
7857/**
7858 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7859 * @wiphy: Pointer to wireless phy
7860 * @wdev: Pointer to wireless device
7861 * @data: Pointer to data
7862 * @data_len: Length of @data
7863 *
7864 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
7865 *
7866 * Return: 0 on success, negative errno on failure
7867 */
7868static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7869 struct wireless_dev *wdev,
7870 const void *data, int data_len)
7871{
7872 int ret;
7873
7874 cds_ssr_protect(__func__);
7875 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
7876 cds_ssr_unprotect(__func__);
7877
7878 return ret;
7879}
7880
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007881const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
7882 {
7883 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7884 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
7885 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05307886 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007887 .doit = is_driver_dfs_capable
7888 },
7889
7890#ifdef WLAN_FEATURE_NAN
7891 {
7892 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7893 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
7894 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7895 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7896 .doit = wlan_hdd_cfg80211_nan_request
7897 },
7898#endif
7899
7900#ifdef WLAN_FEATURE_STATS_EXT
7901 {
7902 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7903 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
7904 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7905 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7906 .doit = wlan_hdd_cfg80211_stats_ext_request
7907 },
7908#endif
7909#ifdef FEATURE_WLAN_EXTSCAN
7910 {
7911 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7912 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
7913 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7914 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7915 .doit = wlan_hdd_cfg80211_extscan_start
7916 },
7917 {
7918 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7919 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
7920 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7921 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7922 .doit = wlan_hdd_cfg80211_extscan_stop
7923 },
7924 {
7925 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7926 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
7927 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7928 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
7929 },
7930 {
7931 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7932 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
7933 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7934 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7935 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
7936 },
7937 {
7938 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7939 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
7940 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7941 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7942 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
7943 },
7944 {
7945 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7946 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
7947 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7948 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7949 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
7950 },
7951 {
7952 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7953 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
7954 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7955 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7956 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
7957 },
7958 {
7959 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7960 .info.subcmd =
7961 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
7962 .flags =
7963 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7964 WIPHY_VENDOR_CMD_NEED_RUNNING,
7965 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
7966 },
7967 {
7968 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7969 .info.subcmd =
7970 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
7971 .flags =
7972 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7973 WIPHY_VENDOR_CMD_NEED_RUNNING,
7974 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
7975 },
7976 {
7977 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7978 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
7979 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7980 WIPHY_VENDOR_CMD_NEED_NETDEV |
7981 WIPHY_VENDOR_CMD_NEED_RUNNING,
7982 .doit = wlan_hdd_cfg80211_set_epno_list
7983 },
7984#endif /* FEATURE_WLAN_EXTSCAN */
7985
7986#ifdef WLAN_FEATURE_LINK_LAYER_STATS
7987 {
7988 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7989 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
7990 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7991 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7992 .doit = wlan_hdd_cfg80211_ll_stats_clear
7993 },
7994
7995 {
7996 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7997 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
7998 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7999 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8000 .doit = wlan_hdd_cfg80211_ll_stats_set
8001 },
8002
8003 {
8004 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8005 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8006 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8007 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8008 .doit = wlan_hdd_cfg80211_ll_stats_get
8009 },
8010#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8011#ifdef FEATURE_WLAN_TDLS
8012 {
8013 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8014 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8015 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8016 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8017 .doit = wlan_hdd_cfg80211_exttdls_enable
8018 },
8019 {
8020 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8021 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8022 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8023 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8024 .doit = wlan_hdd_cfg80211_exttdls_disable
8025 },
8026 {
8027 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8028 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8029 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8030 .doit = wlan_hdd_cfg80211_exttdls_get_status
8031 },
8032#endif
8033 {
8034 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8035 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8036 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8037 .doit = wlan_hdd_cfg80211_get_supported_features
8038 },
8039 {
8040 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8041 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8042 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8043 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8044 },
8045 {
8046 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8047 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8048 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308049 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008050 },
8051 {
8052 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8053 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8054 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8055 WIPHY_VENDOR_CMD_NEED_NETDEV,
8056 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8057 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008058 {
8059 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8060 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8061 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8062 WIPHY_VENDOR_CMD_NEED_NETDEV,
8063 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8064 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008065 {
8066 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308067 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8068 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8069 WIPHY_VENDOR_CMD_NEED_NETDEV |
8070 WIPHY_VENDOR_CMD_NEED_RUNNING,
8071 .doit = hdd_cfg80211_get_station_cmd
8072 },
8073 {
8074 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008075 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8076 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8077 WIPHY_VENDOR_CMD_NEED_NETDEV |
8078 WIPHY_VENDOR_CMD_NEED_RUNNING,
8079 .doit = wlan_hdd_cfg80211_do_acs
8080 },
8081
8082 {
8083 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8084 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8085 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8086 WIPHY_VENDOR_CMD_NEED_NETDEV,
8087 .doit = wlan_hdd_cfg80211_get_features
8088 },
8089#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8090 {
8091 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8092 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8093 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8094 WIPHY_VENDOR_CMD_NEED_NETDEV |
8095 WIPHY_VENDOR_CMD_NEED_RUNNING,
8096 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8097 },
8098#endif
8099#ifdef FEATURE_WLAN_EXTSCAN
8100 {
8101 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8102 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8103 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8104 WIPHY_VENDOR_CMD_NEED_NETDEV |
8105 WIPHY_VENDOR_CMD_NEED_RUNNING,
8106 .doit = wlan_hdd_cfg80211_set_passpoint_list
8107 },
8108 {
8109 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8110 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8111 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8112 WIPHY_VENDOR_CMD_NEED_NETDEV |
8113 WIPHY_VENDOR_CMD_NEED_RUNNING,
8114 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8115 },
8116 {
8117 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8118 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8119 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8120 WIPHY_VENDOR_CMD_NEED_NETDEV |
8121 WIPHY_VENDOR_CMD_NEED_RUNNING,
8122 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8123 },
8124 {
8125 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8126 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8127 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8128 WIPHY_VENDOR_CMD_NEED_NETDEV |
8129 WIPHY_VENDOR_CMD_NEED_RUNNING,
8130 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8131 },
8132#endif /* FEATURE_WLAN_EXTSCAN */
8133 {
8134 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8135 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8136 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8137 WIPHY_VENDOR_CMD_NEED_NETDEV,
8138 .doit = wlan_hdd_cfg80211_get_wifi_info
8139 },
8140 {
8141 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8142 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8143 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8144 WIPHY_VENDOR_CMD_NEED_NETDEV |
8145 WIPHY_VENDOR_CMD_NEED_RUNNING,
8146 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8147 },
8148 {
8149 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8150 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8151 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8152 WIPHY_VENDOR_CMD_NEED_NETDEV,
8153 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8154 },
8155 {
8156 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8157 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8158 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8159 WIPHY_VENDOR_CMD_NEED_NETDEV,
8160 .doit = wlan_hdd_cfg80211_wifi_logger_start
8161 },
8162 {
8163 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8164 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8165 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8166 WIPHY_VENDOR_CMD_NEED_NETDEV,
8167 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8168 },
8169 {
8170 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8171 .info.subcmd =
8172 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8173 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8174 WIPHY_VENDOR_CMD_NEED_NETDEV |
8175 WIPHY_VENDOR_CMD_NEED_RUNNING,
8176 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8177 },
8178 {
8179 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8180 .info.subcmd =
8181 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8182 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8183 WIPHY_VENDOR_CMD_NEED_NETDEV |
8184 WIPHY_VENDOR_CMD_NEED_RUNNING,
8185 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8186 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008187#ifdef WLAN_FEATURE_TSF
8188 {
8189 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8190 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8191 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8192 WIPHY_VENDOR_CMD_NEED_NETDEV |
8193 WIPHY_VENDOR_CMD_NEED_RUNNING,
8194 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8195 },
8196#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008197#ifdef FEATURE_WLAN_TDLS
8198 {
8199 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8200 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8201 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8202 WIPHY_VENDOR_CMD_NEED_NETDEV |
8203 WIPHY_VENDOR_CMD_NEED_RUNNING,
8204 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8205 },
8206#endif
8207#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8208 {
8209 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8210 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8211 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8212 WIPHY_VENDOR_CMD_NEED_NETDEV |
8213 WIPHY_VENDOR_CMD_NEED_RUNNING,
8214 .doit = wlan_hdd_cfg80211_offloaded_packets
8215 },
8216#endif
8217 {
8218 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8219 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8220 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8221 WIPHY_VENDOR_CMD_NEED_NETDEV |
8222 WIPHY_VENDOR_CMD_NEED_RUNNING,
8223 .doit = wlan_hdd_cfg80211_monitor_rssi
8224 },
8225 {
8226 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308227 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8228 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8229 WIPHY_VENDOR_CMD_NEED_NETDEV |
8230 WIPHY_VENDOR_CMD_NEED_RUNNING,
8231 .doit = wlan_hdd_cfg80211_set_ns_offload
8232 },
8233 {
8234 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008235 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8236 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8237 WIPHY_VENDOR_CMD_NEED_NETDEV |
8238 WIPHY_VENDOR_CMD_NEED_RUNNING,
8239 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8240 },
8241#ifdef WLAN_FEATURE_MEMDUMP
8242 {
8243 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8244 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8245 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8246 WIPHY_VENDOR_CMD_NEED_NETDEV |
8247 WIPHY_VENDOR_CMD_NEED_RUNNING,
8248 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8249 },
8250#endif /* WLAN_FEATURE_MEMDUMP */
8251 {
8252 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8253 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8254 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8255 WIPHY_VENDOR_CMD_NEED_NETDEV |
8256 WIPHY_VENDOR_CMD_NEED_RUNNING,
8257 .doit = wlan_hdd_cfg80211_vendor_scan
8258 },
8259
8260 /* OCB commands */
8261 {
8262 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8263 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8264 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8265 WIPHY_VENDOR_CMD_NEED_NETDEV |
8266 WIPHY_VENDOR_CMD_NEED_RUNNING,
8267 .doit = wlan_hdd_cfg80211_ocb_set_config
8268 },
8269 {
8270 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8271 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8272 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8273 WIPHY_VENDOR_CMD_NEED_NETDEV |
8274 WIPHY_VENDOR_CMD_NEED_RUNNING,
8275 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8276 },
8277 {
8278 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8279 .info.subcmd =
8280 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8281 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8282 WIPHY_VENDOR_CMD_NEED_NETDEV |
8283 WIPHY_VENDOR_CMD_NEED_RUNNING,
8284 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8285 },
8286 {
8287 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8288 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8289 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8290 WIPHY_VENDOR_CMD_NEED_NETDEV |
8291 WIPHY_VENDOR_CMD_NEED_RUNNING,
8292 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8293 },
8294 {
8295 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8296 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8297 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8298 WIPHY_VENDOR_CMD_NEED_NETDEV |
8299 WIPHY_VENDOR_CMD_NEED_RUNNING,
8300 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8301 },
8302 {
8303 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8304 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8305 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8306 WIPHY_VENDOR_CMD_NEED_NETDEV |
8307 WIPHY_VENDOR_CMD_NEED_RUNNING,
8308 .doit = wlan_hdd_cfg80211_dcc_get_stats
8309 },
8310 {
8311 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8312 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8313 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8314 WIPHY_VENDOR_CMD_NEED_NETDEV |
8315 WIPHY_VENDOR_CMD_NEED_RUNNING,
8316 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8317 },
8318 {
8319 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8320 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8321 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8322 WIPHY_VENDOR_CMD_NEED_NETDEV |
8323 WIPHY_VENDOR_CMD_NEED_RUNNING,
8324 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8325 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308326 {
8327 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8328 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8329 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8330 WIPHY_VENDOR_CMD_NEED_NETDEV |
8331 WIPHY_VENDOR_CMD_NEED_RUNNING,
8332 .doit = wlan_hdd_cfg80211_get_link_properties
8333 },
Peng Xu278d0122015-09-24 16:34:17 -07008334 {
Peng Xud2220962016-07-11 17:59:17 -07008335 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008336 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8337 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8338 WIPHY_VENDOR_CMD_NEED_NETDEV |
8339 WIPHY_VENDOR_CMD_NEED_RUNNING,
8340 .doit = wlan_hdd_cfg80211_set_ota_test
8341 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008342#ifdef FEATURE_LFR_SUBNET_DETECTION
8343 {
8344 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8345 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8346 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8347 WIPHY_VENDOR_CMD_NEED_NETDEV |
8348 WIPHY_VENDOR_CMD_NEED_RUNNING,
8349 .doit = wlan_hdd_cfg80211_set_gateway_params
8350 },
8351#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008352 {
Peng Xud2220962016-07-11 17:59:17 -07008353 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008354 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8355 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8356 WIPHY_VENDOR_CMD_NEED_NETDEV |
8357 WIPHY_VENDOR_CMD_NEED_RUNNING,
8358 .doit = wlan_hdd_cfg80211_txpower_scale
8359 },
8360 {
8361 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8362 .info.subcmd =
8363 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8364 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8365 WIPHY_VENDOR_CMD_NEED_NETDEV |
8366 WIPHY_VENDOR_CMD_NEED_RUNNING,
8367 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8368 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308369 {
8370 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8371 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8372 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8373 WIPHY_VENDOR_CMD_NEED_NETDEV |
8374 WIPHY_VENDOR_CMD_NEED_RUNNING,
8375 .doit = wlan_hdd_cfg80211_bpf_offload
8376 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308377 {
8378 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308379 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8380 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8381 WIPHY_VENDOR_CMD_NEED_NETDEV |
8382 WIPHY_VENDOR_CMD_NEED_RUNNING,
8383 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8384 },
8385 {
8386 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308387 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8388 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8389 WIPHY_VENDOR_CMD_NEED_NETDEV |
8390 WIPHY_VENDOR_CMD_NEED_RUNNING,
8391 .doit = wlan_hdd_cfg80211_sta_roam_policy
8392 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308393#ifdef FEATURE_WLAN_CH_AVOID
8394 {
8395 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8396 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8397 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8398 WIPHY_VENDOR_CMD_NEED_NETDEV |
8399 WIPHY_VENDOR_CMD_NEED_RUNNING,
8400 .doit = wlan_hdd_cfg80211_avoid_freq
8401 },
8402#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308403 {
8404 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308405 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8406 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8407 WIPHY_VENDOR_CMD_NEED_NETDEV |
8408 WIPHY_VENDOR_CMD_NEED_RUNNING,
8409 .doit = wlan_hdd_cfg80211_sap_configuration_set
8410 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008411 {
Peng Xu4225c152016-07-14 21:18:14 -07008412 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008413 .info.subcmd =
8414 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8415 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8416 WIPHY_VENDOR_CMD_NEED_NETDEV |
8417 WIPHY_VENDOR_CMD_NEED_RUNNING,
8418 .doit = wlan_hdd_cfg80211_p2p_lo_start
8419 },
8420 {
8421 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8422 .info.subcmd =
8423 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8424 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8425 WIPHY_VENDOR_CMD_NEED_NETDEV |
8426 WIPHY_VENDOR_CMD_NEED_RUNNING,
8427 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8428 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308429 {
8430 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8431 .info.subcmd =
8432 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8433 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8434 WIPHY_VENDOR_CMD_NEED_NETDEV |
8435 WIPHY_VENDOR_CMD_NEED_RUNNING,
8436 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8437 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008438#ifdef WLAN_FEATURE_NAN_DATAPATH
8439 {
8440 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8441 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8442 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8443 WIPHY_VENDOR_CMD_NEED_NETDEV |
8444 WIPHY_VENDOR_CMD_NEED_RUNNING,
8445 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8446 },
8447#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308448 {
8449 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8450 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8451 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8452 WIPHY_VENDOR_CMD_NEED_NETDEV |
8453 WIPHY_VENDOR_CMD_NEED_RUNNING,
8454 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8455 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308456 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308457 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8458 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8459 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8460 WIPHY_VENDOR_CMD_NEED_NETDEV |
8461 WIPHY_VENDOR_CMD_NEED_RUNNING,
8462 .doit = wlan_hdd_cfg80211_get_bus_size
8463 },
8464 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308465 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8466 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8467 WIPHY_VENDOR_CMD_NEED_NETDEV |
8468 WIPHY_VENDOR_CMD_NEED_RUNNING,
8469 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308470 },
8471 {
8472 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8473 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8474 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8475 WIPHY_VENDOR_CMD_NEED_NETDEV |
8476 WIPHY_VENDOR_CMD_NEED_RUNNING,
8477 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308478 },
8479#ifdef WLAN_FEATURE_DISA
8480 {
8481 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8482 .info.subcmd =
8483 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8484 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8485 WIPHY_VENDOR_CMD_NEED_NETDEV |
8486 WIPHY_VENDOR_CMD_NEED_RUNNING,
8487 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8488 },
8489#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008490};
8491
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008492/**
8493 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8494 * @priv_size: Size of the hdd context.
8495 *
8496 * Allocate wiphy context and hdd context.
8497 *
8498 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008499 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008500hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008501{
8502 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008503 hdd_context_t *hdd_ctx;
8504
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008505 ENTER();
8506
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008507 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8508
8509 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008510 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008511 return NULL;
8512 }
8513
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008514 hdd_ctx = wiphy_priv(wiphy);
8515
8516 hdd_ctx->wiphy = wiphy;
8517
8518 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008519}
8520
8521/*
8522 * FUNCTION: wlan_hdd_cfg80211_update_band
8523 * This function is called from the supplicant through a
8524 * private ioctl to change the band value
8525 */
8526int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8527{
8528 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008529 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008530
8531 ENTER();
8532
8533 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8534
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008535 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008536 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008537
8538 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8539 struct ieee80211_supported_band *band = wiphy->bands[i];
8540
8541 channelEnabledState =
8542 cds_get_channel_state(band->channels[j].
8543 hw_value);
8544
8545 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
8546 /* 5G only */
8547#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8548 /* Enable Social channels for P2P */
8549 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8550 (band->channels[j].center_freq)
8551 && CHANNEL_STATE_ENABLE ==
8552 channelEnabledState)
8553 band->channels[j].flags &=
8554 ~IEEE80211_CHAN_DISABLED;
8555 else
8556#endif
8557 band->channels[j].flags |=
8558 IEEE80211_CHAN_DISABLED;
8559 continue;
8560 } else if (IEEE80211_BAND_5GHZ == i &&
8561 eCSR_BAND_24 == eBand) {
8562 /* 2G only */
8563 band->channels[j].flags |=
8564 IEEE80211_CHAN_DISABLED;
8565 continue;
8566 }
8567
Amar Singhal6842e8f2016-02-23 16:30:32 -08008568 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008569 band->channels[j].flags &=
8570 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008571 }
8572 }
8573 return 0;
8574}
8575
8576/*
8577 * FUNCTION: wlan_hdd_cfg80211_init
8578 * This function is called by hdd_wlan_startup()
8579 * during initialization.
8580 * This function is used to initialize and register wiphy structure.
8581 */
8582int wlan_hdd_cfg80211_init(struct device *dev,
8583 struct wiphy *wiphy, struct hdd_config *pCfg)
8584{
8585 int i, j;
8586 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8587
8588 ENTER();
8589
8590 /* Now bind the underlying wlan device with wiphy */
8591 set_wiphy_dev(wiphy, dev);
8592
8593 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8594
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008595#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8596 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008597 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008598#else
8599 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008600 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008601#endif
8602
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008603 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8604 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8605 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8606#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8607 | WIPHY_FLAG_4ADDR_STATION
8608#endif
8609 | WIPHY_FLAG_OFFCHAN_TX;
8610
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008611#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8612 wiphy->wowlan = &wowlan_support_cfg80211_init;
8613#else
8614 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8615 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8616 wiphy->wowlan.pattern_min_len = 1;
8617 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8618#endif
8619
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008620 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008621#ifdef FEATURE_WLAN_ESE
8622 || pCfg->isEseIniFeatureEnabled
8623#endif
8624 ) {
8625 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8626 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008627#ifdef FEATURE_WLAN_TDLS
8628 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8629 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8630#endif
8631
8632 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8633
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008634#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8635 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8636#endif
8637
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008638#ifdef FEATURE_WLAN_SCAN_PNO
8639 if (pCfg->configPNOScanSupport) {
8640 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8641 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8642 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8643 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008644#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8645 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8646#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008647 }
8648#endif /*FEATURE_WLAN_SCAN_PNO */
8649
8650#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308651 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008652#endif
8653
8654 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8655 driver can still register regulatory callback and
8656 it will get regulatory settings in wiphy->band[], but
8657 driver need to determine what to do with both
8658 regulatory settings */
8659
8660 wiphy->reg_notifier = hdd_reg_notifier;
8661
8662#if defined QCA_WIFI_FTM
8663}
8664#endif
8665
8666 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8667
8668 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8669
8670 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8671
Arun Khandavallifae92942016-08-01 13:31:08 +05308672 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8673 | BIT(NL80211_IFTYPE_ADHOC)
8674 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8675 | BIT(NL80211_IFTYPE_P2P_GO)
8676 | BIT(NL80211_IFTYPE_AP)
8677 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008678
Arun Khandavallifae92942016-08-01 13:31:08 +05308679 if (pCfg->advertiseConcurrentOperation) {
8680 if (pCfg->enableMCC) {
8681 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008682
Arun Khandavallifae92942016-08-01 13:31:08 +05308683 for (i = 0;
8684 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8685 i++) {
8686 if (!pCfg->allowMCCGODiffBI)
8687 wlan_hdd_iface_combination[i].
8688 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008689 }
8690 }
8691 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308692 ARRAY_SIZE(wlan_hdd_iface_combination);
8693 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008694 }
8695
8696 /* Before registering we need to update the ht capabilitied based
8697 * on ini values*/
8698 if (!pCfg->ShortGI20MhzEnable) {
8699 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8700 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008701 }
8702
8703 if (!pCfg->ShortGI40MhzEnable) {
8704 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8705 }
8706
8707 if (!pCfg->nChannelBondingMode5GHz) {
8708 wlan_hdd_band_5_ghz.ht_cap.cap &=
8709 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8710 }
8711
Abhishek Singhf512bf32016-05-04 16:47:46 +05308712 /*
8713 * In case of static linked driver at the time of driver unload,
8714 * module exit doesn't happens. Module cleanup helps in cleaning
8715 * of static memory.
8716 * If driver load happens statically, at the time of driver unload,
8717 * wiphy flags don't get reset because of static memory.
8718 * It's better not to store channel in static memory.
8719 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008720 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308721 wiphy->bands[IEEE80211_BAND_2GHZ]->channels =
8722 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
8723 if (wiphy->bands[IEEE80211_BAND_2GHZ]->channels == NULL) {
8724 hdd_err("Not enough memory to allocate channels");
8725 return -ENOMEM;
8726 }
8727 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_2GHZ]->channels,
8728 &hdd_channels_2_4_ghz[0],
8729 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308730 if ((hdd_is_5g_supported(pHddCtx)) &&
8731 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8732 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8733 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8734 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008735 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308736 wiphy->bands[IEEE80211_BAND_5GHZ]->channels =
8737 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
8738 if (wiphy->bands[IEEE80211_BAND_5GHZ]->channels == NULL) {
8739 hdd_err("Not enough memory to allocate channels");
8740 qdf_mem_free(wiphy->
8741 bands[IEEE80211_BAND_2GHZ]->channels);
8742 wiphy->bands[IEEE80211_BAND_2GHZ]->channels = NULL;
8743 return -ENOMEM;
8744 }
8745 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_5GHZ]->channels,
8746 &hdd_channels_5_ghz[0],
8747 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008748 }
8749
8750 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8751
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008752 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008753 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008754
8755 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8756 struct ieee80211_supported_band *band = wiphy->bands[i];
8757
8758 if (IEEE80211_BAND_2GHZ == i &&
8759 eCSR_BAND_5G == pCfg->nBandCapability) {
8760 /* 5G only */
8761#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8762 /* Enable social channels for P2P */
8763 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8764 (band->channels[j].center_freq))
8765 band->channels[j].flags &=
8766 ~IEEE80211_CHAN_DISABLED;
8767 else
8768#endif
8769 band->channels[j].flags |=
8770 IEEE80211_CHAN_DISABLED;
8771 continue;
8772 } else if (IEEE80211_BAND_5GHZ == i &&
8773 eCSR_BAND_24 == pCfg->nBandCapability) {
8774 /* 2G only */
8775 band->channels[j].flags |=
8776 IEEE80211_CHAN_DISABLED;
8777 continue;
8778 }
8779 }
8780 }
8781 /*Initialise the supported cipher suite details */
8782 wiphy->cipher_suites = hdd_cipher_suites;
8783 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8784
8785 /*signal strength in mBm (100*dBm) */
8786 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8787 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8788
Anurag Chouhan6d760662016-02-20 16:05:43 +05308789 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008790 wiphy->n_vendor_commands =
8791 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8792 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8793
8794 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8795 wiphy->n_vendor_events =
8796 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8797 }
8798
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008799 if (pCfg->enableDFSMasterCap) {
8800 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8801 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008802
8803 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8804
8805#ifdef QCA_HT_2040_COEX
8806 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8807#endif
8808
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308809 hdd_add_channel_switch_support(&wiphy->flags);
8810
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008811 EXIT();
8812 return 0;
8813}
8814
Abhishek Singhf512bf32016-05-04 16:47:46 +05308815/**
8816 * wlan_hdd_cfg80211_deinit - Deinit cfg80211
8817 * @ wiphy: the wiphy to validate against
8818 *
8819 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308820 * memory allocated in wlan_hdd_cfg80211_init also
8821 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308822 *
8823 * Return: void
8824 */
8825void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8826{
8827 int i;
8828
8829 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8830 if (NULL != wiphy->bands[i] &&
8831 (NULL != wiphy->bands[i]->channels)) {
8832 qdf_mem_free(wiphy->bands[i]->channels);
8833 wiphy->bands[i]->channels = NULL;
8834 }
8835 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308836 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05308837}
8838
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008839/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308840 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008841 * initialization. In wlan_hdd_cfg80211_init, only the
8842 * default values will be initialized. The final initialization
8843 * of all required members can be done here.
8844 */
8845void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
8846{
8847 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8848}
8849
8850/* In this function we are registering wiphy. */
8851int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
8852{
8853 ENTER();
8854 /* Register our wiphy dev with cfg80211 */
8855 if (0 > wiphy_register(wiphy)) {
8856 /* print error */
Jeff Johnson77848112016-06-29 14:52:06 -07008857 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008858 return -EIO;
8859 }
8860
8861 EXIT();
8862 return 0;
8863}
8864
8865/*
8866 HDD function to update wiphy capability based on target offload status.
8867
8868 wlan_hdd_cfg80211_init() does initialization of all wiphy related
8869 capability even before downloading firmware to the target. In discrete
8870 case, host will get know certain offload capability (say sched_scan
8871 caps) only after downloading firmware to the target and target boots up.
8872 This function is used to override setting done in wlan_hdd_cfg80211_init()
8873 based on target capability.
8874 */
8875void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
8876{
8877#ifdef FEATURE_WLAN_SCAN_PNO
8878 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8879 struct hdd_config *pCfg = pHddCtx->config;
8880
8881 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
8882 * control comes here. Here just we need to clear it if firmware doesn't
8883 * have PNO support. */
8884 if (!pCfg->PnoOffload) {
8885 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8886 wiphy->max_sched_scan_ssids = 0;
8887 wiphy->max_match_sets = 0;
8888 wiphy->max_sched_scan_ie_len = 0;
8889 }
8890#endif
8891}
8892
8893/* This function registers for all frame which supplicant is interested in */
8894void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
8895{
8896 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8897 /* Register for all P2P action, public action etc frames */
8898 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8899
8900 ENTER();
8901
Abhishek Singh7996eb72015-12-30 17:24:02 +05308902 /* Register frame indication call back */
8903 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
8904
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05308905 /* Register for p2p ack indication */
8906 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
8907
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008908 /* Right now we are registering these frame when driver is getting
8909 initialized. Once we will move to 2.6.37 kernel, in which we have
8910 frame register ops, we will move this code as a part of that */
8911 /* GAS Initial Request */
8912 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8913 (uint8_t *) GAS_INITIAL_REQ,
8914 GAS_INITIAL_REQ_SIZE);
8915
8916 /* GAS Initial Response */
8917 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8918 (uint8_t *) GAS_INITIAL_RSP,
8919 GAS_INITIAL_RSP_SIZE);
8920
8921 /* GAS Comeback Request */
8922 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8923 (uint8_t *) GAS_COMEBACK_REQ,
8924 GAS_COMEBACK_REQ_SIZE);
8925
8926 /* GAS Comeback Response */
8927 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8928 (uint8_t *) GAS_COMEBACK_RSP,
8929 GAS_COMEBACK_RSP_SIZE);
8930
8931 /* P2P Public Action */
8932 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8933 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
8934 P2P_PUBLIC_ACTION_FRAME_SIZE);
8935
8936 /* P2P Action */
8937 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8938 (uint8_t *) P2P_ACTION_FRAME,
8939 P2P_ACTION_FRAME_SIZE);
8940
8941 /* WNM BSS Transition Request frame */
8942 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8943 (uint8_t *) WNM_BSS_ACTION_FRAME,
8944 WNM_BSS_ACTION_FRAME_SIZE);
8945
8946 /* WNM-Notification */
8947 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
8948 (uint8_t *) WNM_NOTIFICATION_FRAME,
8949 WNM_NOTIFICATION_FRAME_SIZE);
8950}
8951
8952void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
8953{
8954 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8955 /* Register for all P2P action, public action etc frames */
8956 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8957
8958 ENTER();
8959
8960 /* Right now we are registering these frame when driver is getting
8961 initialized. Once we will move to 2.6.37 kernel, in which we have
8962 frame register ops, we will move this code as a part of that */
8963 /* GAS Initial Request */
8964
8965 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8966 (uint8_t *) GAS_INITIAL_REQ,
8967 GAS_INITIAL_REQ_SIZE);
8968
8969 /* GAS Initial Response */
8970 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8971 (uint8_t *) GAS_INITIAL_RSP,
8972 GAS_INITIAL_RSP_SIZE);
8973
8974 /* GAS Comeback Request */
8975 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8976 (uint8_t *) GAS_COMEBACK_REQ,
8977 GAS_COMEBACK_REQ_SIZE);
8978
8979 /* GAS Comeback Response */
8980 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8981 (uint8_t *) GAS_COMEBACK_RSP,
8982 GAS_COMEBACK_RSP_SIZE);
8983
8984 /* P2P Public Action */
8985 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8986 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
8987 P2P_PUBLIC_ACTION_FRAME_SIZE);
8988
8989 /* P2P Action */
8990 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8991 (uint8_t *) P2P_ACTION_FRAME,
8992 P2P_ACTION_FRAME_SIZE);
8993
8994 /* WNM-Notification */
8995 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
8996 (uint8_t *) WNM_NOTIFICATION_FRAME,
8997 WNM_NOTIFICATION_FRAME_SIZE);
8998}
8999
9000#ifdef FEATURE_WLAN_WAPI
9001void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9002 const uint8_t *mac_addr, const uint8_t *key,
9003 int key_Len)
9004{
9005 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9006 tCsrRoamSetKey setKey;
9007 bool isConnected = true;
9008 int status = 0;
9009 uint32_t roamId = 0xFF;
9010 uint8_t *pKeyPtr = NULL;
9011 int n = 0;
9012
Jeff Johnson46b40792016-06-29 14:03:14 -07009013 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009014 hdd_device_mode_to_string(pAdapter->device_mode),
9015 pAdapter->device_mode);
9016
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309017 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009018 setKey.keyId = key_index; /* Store Key ID */
9019 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9020 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9021 setKey.paeRole = 0; /* the PAE role */
9022 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309023 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009024 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309025 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009026 }
9027 setKey.keyLength = key_Len;
9028 pKeyPtr = setKey.Key;
9029 memcpy(pKeyPtr, key, key_Len);
9030
Jeff Johnson46b40792016-06-29 14:03:14 -07009031 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009032 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009033 hdd_notice("WAPI KEY Data[%d]:%02x ",
9034 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009035
9036 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9037 if (isConnected) {
9038 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9039 pAdapter->sessionId, &setKey, &roamId);
9040 }
9041 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009042 hdd_err("sme_roam_set_key returned ERROR status= %d",
9043 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009044 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9045 }
9046}
9047#endif /* FEATURE_WLAN_WAPI */
9048
9049uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9050 uint8_t eid)
9051{
9052 int left = length;
9053 uint8_t *ptr = (uint8_t *)ies_ptr;
9054 uint8_t elem_id, elem_len;
9055
9056 while (left >= 2) {
9057 elem_id = ptr[0];
9058 elem_len = ptr[1];
9059 left -= 2;
9060 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009061 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009062 eid, elem_len, left);
9063 return NULL;
9064 }
9065 if (elem_id == eid) {
9066 return ptr;
9067 }
9068
9069 left -= elem_len;
9070 ptr += (elem_len + 2);
9071 }
9072 return NULL;
9073}
9074
9075/*
9076 * FUNCTION: wlan_hdd_validate_operation_channel
9077 * called by wlan_hdd_cfg80211_start_bss() and
9078 * wlan_hdd_set_channel()
9079 * This function validates whether given channel is part of valid
9080 * channel list.
9081 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309082QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009083 int channel)
9084{
9085
9086 uint32_t num_ch = 0;
9087 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9088 u32 indx = 0;
9089 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9090 uint8_t fValidChannel = false, count = 0;
9091 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9092
9093 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9094
9095 if (hdd_pConfig_ini->sapAllowAllChannel) {
9096 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009097 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009098 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009099 fValidChannel = true;
9100 break;
9101 }
9102 }
9103 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009104 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309105 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009106 }
9107 } else {
9108 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9109 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009110 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309111 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009112 }
9113 for (indx = 0; indx < num_ch; indx++) {
9114 if (channel == valid_ch[indx]) {
9115 break;
9116 }
9117 }
9118
9119 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009120 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309121 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009122 }
9123 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309124 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009125
9126}
9127
9128#ifdef DHCP_SERVER_OFFLOAD
9129static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9130{
9131 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9132 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9133 uint8_t numEntries = 0;
9134 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9135 uint8_t num;
9136 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309137 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009138 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009139 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009140 return;
9141 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309142 qdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009143 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9144 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9145 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9146 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9147 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9148 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009149 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009150 goto end;
9151 }
9152 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009153 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009154 goto end;
9155 }
9156 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009157 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009158 goto end;
9159 }
9160 for (num = 0; num < numEntries; num++) {
9161 temp = srv_ip[num];
9162 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9163 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309164 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009165 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009166 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009167 goto end;
9168 }
Jeff Johnson77848112016-06-29 14:52:06 -07009169 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009170end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309171 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009172 return;
9173}
9174#endif /* DHCP_SERVER_OFFLOAD */
9175
9176static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9177 struct net_device *dev,
9178 struct bss_parameters *params)
9179{
9180 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9181 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9182 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309183 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009184
9185 ENTER();
9186
Anurag Chouhan6d760662016-02-20 16:05:43 +05309187 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009188 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009189 return -EINVAL;
9190 }
9191
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309192 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009193 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9194 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009195 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009196 hdd_device_mode_to_string(pAdapter->device_mode),
9197 pAdapter->device_mode, params->ap_isolate);
9198
9199 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9200 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309201 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009202 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009203
Krunal Sonib4326f22016-03-10 13:05:51 -08009204 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9205 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009206 return -EOPNOTSUPP;
9207 }
9208
9209 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9210 * want to update this parameter */
9211 if (-1 != params->ap_isolate) {
9212 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9213 !!params->ap_isolate;
9214
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309215 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009216 pAdapter->sessionId,
9217 pAdapter->sessionCtx.
9218 ap.
9219 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309220 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009221 ret = -EINVAL;
9222 }
9223 }
9224
9225 EXIT();
9226 return ret;
9227}
9228
Krunal Soni8c37e322016-02-03 16:08:37 -08009229/**
9230 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9231 * @ndev: pointer to net device provided by supplicant
9232 * @type: type of the interface, upper layer wanted to change
9233 *
9234 * Upper layer provides the new interface mode that needs to be changed
9235 * for given net device
9236 *
9237 * Return: success or failure in terms of integer value
9238 */
9239static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009240 enum nl80211_iftype type)
9241{
Krunal Soni8c37e322016-02-03 16:08:37 -08009242 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9243 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9244 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009245 hdd_wext_state_t *wext;
9246 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309247 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009248
9249 ENTER();
9250
Krunal Soni8c37e322016-02-03 16:08:37 -08009251 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009252 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009253 return 0;
9254 }
9255
9256 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009257 hdd_stop_adapter(hdd_ctx, adapter, true);
9258 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009259 wdev->iftype = type;
9260 /*Check for sub-string p2p to confirm its a p2p interface */
9261 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009262 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009263 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009264 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009265 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009266 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009267 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009268 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009269 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009270 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009271 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009272 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9273 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009274 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9275 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009276 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009277 adapter->scan_info.scanAddIE.length;
9278 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309279 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009280 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9281 wext->roamProfile.phyMode =
9282 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9283 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009284 EXIT();
9285 return status;
9286}
9287
9288static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9289 struct net_device *dev,
9290 struct bss_parameters *params)
9291{
9292 int ret;
9293
9294 cds_ssr_protect(__func__);
9295 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9296 cds_ssr_unprotect(__func__);
9297
9298 return ret;
9299}
9300
9301/* FUNCTION: wlan_hdd_change_country_code_cd
9302 * to wait for contry code completion
9303 */
9304void *wlan_hdd_change_country_code_cb(void *pAdapter)
9305{
9306 hdd_adapter_t *call_back_pAdapter = pAdapter;
9307 complete(&call_back_pAdapter->change_country_code);
9308 return NULL;
9309}
9310
Rajeev Kumar98edb772016-01-19 12:42:19 -08009311/**
9312 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9313 * @wiphy: Pointer to the wiphy structure
9314 * @ndev: Pointer to the net device
9315 * @type: Interface type
9316 * @flags: Flags for change interface
9317 * @params: Pointer to change interface parameters
9318 *
9319 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009320 */
9321static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9322 struct net_device *ndev,
9323 enum nl80211_iftype type,
9324 u32 *flags,
9325 struct vif_params *params)
9326{
9327 struct wireless_dev *wdev;
9328 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9329 hdd_context_t *pHddCtx;
9330 tCsrRoamProfile *pRoamProfile = NULL;
9331 eCsrRoamBssType LastBSSType;
9332 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309333 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009334 int status;
9335
9336 ENTER();
9337
Anurag Chouhan6d760662016-02-20 16:05:43 +05309338 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009339 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009340 return -EINVAL;
9341 }
9342
9343 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9344 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309345 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009346 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009347
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309348 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009349 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9350 pAdapter->sessionId, type));
9351
Jeff Johnson77848112016-06-29 14:52:06 -07009352 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009353 pAdapter->device_mode, type);
9354
Arun Khandavallifae92942016-08-01 13:31:08 +05309355 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9356 if (status) {
9357 hdd_err("Failed to start modules");
9358 return -EINVAL;
9359 }
9360
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009361 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009362 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9363 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009364 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009365 return -EINVAL;
9366 }
9367
9368 pConfig = pHddCtx->config;
9369 wdev = ndev->ieee80211_ptr;
9370
9371 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009372 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009373
9374 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9375
Krunal Sonib4326f22016-03-10 13:05:51 -08009376 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9377 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9378 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9379 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009380 hdd_wext_state_t *pWextState =
9381 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9382
9383 pRoamProfile = &pWextState->roamProfile;
9384 LastBSSType = pRoamProfile->BSSType;
9385
9386 switch (type) {
9387 case NL80211_IFTYPE_STATION:
9388 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009389 case NL80211_IFTYPE_ADHOC:
9390 if (type == NL80211_IFTYPE_ADHOC) {
9391 wlan_hdd_tdls_exit(pAdapter);
9392 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009393 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009394 }
9395 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9396 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309397 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009398 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309399 if (hdd_start_adapter(pAdapter)) {
9400 hdd_err("Failed to start adapter :%d",
9401 pAdapter->device_mode);
9402 return -EINVAL;
9403 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009404 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009405 case NL80211_IFTYPE_AP:
9406 case NL80211_IFTYPE_P2P_GO:
9407 {
Jeff Johnson77848112016-06-29 14:52:06 -07009408 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009409 (type ==
9410 NL80211_IFTYPE_AP) ? "SoftAP" :
9411 "P2pGo");
9412
9413 /* Cancel any remain on channel for GO mode */
9414 if (NL80211_IFTYPE_P2P_GO == type) {
9415 wlan_hdd_cancel_existing_remain_on_channel
9416 (pAdapter);
9417 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009418
Arun Khandavallifae92942016-08-01 13:31:08 +05309419 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009420 /* De-init the adapter */
9421 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9422 memset(&pAdapter->sessionCtx, 0,
9423 sizeof(pAdapter->sessionCtx));
9424 pAdapter->device_mode =
9425 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009426 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9427 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009428
9429 /*
9430 * Fw will take care incase of concurrency
9431 */
9432
Krunal Sonib4326f22016-03-10 13:05:51 -08009433 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009434 && (pConfig->apRandomBssidEnabled)) {
9435 /* To meet Android requirements create a randomized
9436 MAC address of the form 02:1A:11:Fx:xx:xx */
9437 get_random_bytes(&ndev->dev_addr[3], 3);
9438 ndev->dev_addr[0] = 0x02;
9439 ndev->dev_addr[1] = 0x1A;
9440 ndev->dev_addr[2] = 0x11;
9441 ndev->dev_addr[3] |= 0xF0;
9442 memcpy(pAdapter->macAddressCurrent.
9443 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309444 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009445 pr_info("wlan: Generated HotSpot BSSID "
9446 MAC_ADDRESS_STR "\n",
9447 MAC_ADDR_ARRAY(ndev->dev_addr));
9448 }
9449
9450 hdd_set_ap_ops(pAdapter->dev);
9451
Arun Khandavallifae92942016-08-01 13:31:08 +05309452 if (hdd_start_adapter(pAdapter)) {
9453 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009454 return -EINVAL;
9455 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009456 /* Interface type changed update in wiphy structure */
9457 if (wdev) {
9458 wdev->iftype = type;
9459 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009460 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009461 return -EINVAL;
9462 }
9463 goto done;
9464 }
9465
9466 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009467 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009468 type);
9469 return -EOPNOTSUPP;
9470 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009471 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9472 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009473 switch (type) {
9474 case NL80211_IFTYPE_STATION:
9475 case NL80211_IFTYPE_P2P_CLIENT:
9476 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009477 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9478 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309479 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009480 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309481 if (hdd_start_adapter(pAdapter)) {
9482 hdd_err("Failed to start adapter :%d",
9483 pAdapter->device_mode);
9484 return -EINVAL;
9485 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009486 goto done;
9487
9488 case NL80211_IFTYPE_AP:
9489 case NL80211_IFTYPE_P2P_GO:
9490 wdev->iftype = type;
9491 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009492 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009493 goto done;
9494
9495 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009496 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009497 type);
9498 return -EOPNOTSUPP;
9499 }
9500 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009501 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009502 pAdapter->device_mode);
9503 return -EOPNOTSUPP;
9504 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009505done:
9506 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009507 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009508
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009509 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009510
9511 EXIT();
9512 return 0;
9513}
9514
Rajeev Kumar98edb772016-01-19 12:42:19 -08009515/**
9516 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9517 * @wiphy: Pointer to the wiphy structure
9518 * @ndev: Pointer to the net device
9519 * @type: Interface type
9520 * @flags: Flags for change interface
9521 * @params: Pointer to change interface parameters
9522 *
9523 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009524 */
9525static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9526 struct net_device *ndev,
9527 enum nl80211_iftype type,
9528 u32 *flags,
9529 struct vif_params *params)
9530{
9531 int ret;
9532
9533 cds_ssr_protect(__func__);
9534 ret =
9535 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9536 cds_ssr_unprotect(__func__);
9537
9538 return ret;
9539}
9540
9541#ifdef FEATURE_WLAN_TDLS
9542static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9543 int index, uint8_t match)
9544{
9545 int i;
9546 for (i = 0; i < index; i++) {
9547 if (arr[i] == match)
9548 return true;
9549 }
9550 return false;
9551}
9552#endif
9553
9554/**
9555 * __wlan_hdd_change_station() - change station
9556 * @wiphy: Pointer to the wiphy structure
9557 * @dev: Pointer to the net device.
9558 * @mac: bssid
9559 * @params: Pointer to station parameters
9560 *
9561 * Return: 0 for success, error number on failure.
9562 */
9563#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9564static int __wlan_hdd_change_station(struct wiphy *wiphy,
9565 struct net_device *dev,
9566 const uint8_t *mac,
9567 struct station_parameters *params)
9568#else
9569static int __wlan_hdd_change_station(struct wiphy *wiphy,
9570 struct net_device *dev,
9571 uint8_t *mac,
9572 struct station_parameters *params)
9573#endif
9574{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309575 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009576 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9577 hdd_context_t *pHddCtx;
9578 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309579 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009580#ifdef FEATURE_WLAN_TDLS
9581 tCsrStaParams StaParams = { 0 };
9582 uint8_t isBufSta = 0;
9583 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309584 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009585#endif
9586 int ret;
9587
9588 ENTER();
9589
Anurag Chouhan6d760662016-02-20 16:05:43 +05309590 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009591 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009592 return -EINVAL;
9593 }
9594
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309595 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009596 TRACE_CODE_HDD_CHANGE_STATION,
9597 pAdapter->sessionId, params->listen_interval));
9598
9599 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9600 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309601 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009602 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009603
9604 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9605
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309606 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009607
Krunal Sonib4326f22016-03-10 13:05:51 -08009608 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9609 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009610 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9611 status =
9612 hdd_softap_change_sta_state(pAdapter,
9613 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009614 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009615
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309616 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009617 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009618 return -EINVAL;
9619 }
9620 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009621 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9622 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009623#ifdef FEATURE_WLAN_TDLS
9624 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009625
9626 if (cds_is_sub_20_mhz_enabled()) {
9627 hdd_err("TDLS not allowed with sub 20 MHz");
9628 return -EINVAL;
9629 }
9630
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009631 StaParams.capability = params->capability;
9632 StaParams.uapsd_queues = params->uapsd_queues;
9633 StaParams.max_sp = params->max_sp;
9634
9635 /* Convert (first channel , number of channels) tuple to
9636 * the total list of channels. This goes with the assumption
9637 * that if the first channel is < 14, then the next channels
9638 * are an incremental of 1 else an incremental of 4 till the number
9639 * of channels.
9640 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009641 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009642 if (0 != params->supported_channels_len) {
9643 int i = 0, j = 0, k = 0, no_of_channels = 0;
9644 int num_unique_channels;
9645 int next;
9646 for (i = 0;
9647 i < params->supported_channels_len
9648 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9649 int wifi_chan_index;
9650 if (!wlan_hdd_is_duplicate_channel
9651 (StaParams.supported_channels, j,
9652 params->supported_channels[i])) {
9653 StaParams.
9654 supported_channels[j] =
9655 params->
9656 supported_channels[i];
9657 } else {
9658 continue;
9659 }
9660 wifi_chan_index =
9661 ((StaParams.supported_channels[j] <=
9662 HDD_CHANNEL_14) ? 1 : 4);
9663 no_of_channels =
9664 params->supported_channels[i + 1];
9665
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009666 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 -08009667 StaParams.
9668 supported_channels[j],
9669 wifi_chan_index,
9670 no_of_channels);
9671 for (k = 1; k <= no_of_channels &&
9672 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9673 k++) {
9674 next =
9675 StaParams.
9676 supported_channels[j] +
9677 wifi_chan_index;
9678 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9679 StaParams.
9680 supported_channels[j
9681 +
9682 1]
9683 = next;
9684 } else {
9685 continue;
9686 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009687 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009688 j + 1,
9689 StaParams.
9690 supported_channels[j +
9691 1]);
9692 j += 1;
9693 }
9694 }
9695 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009696 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009697 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009698 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009699 StaParams.
9700 supported_channels[i]);
9701 }
9702 if (MAX_CHANNEL < num_unique_channels)
9703 num_unique_channels = MAX_CHANNEL;
9704 StaParams.supported_channels_len =
9705 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009706 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009707 StaParams.supported_channels_len);
9708 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309709 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009710 params->supported_oper_classes,
9711 params->supported_oper_classes_len);
9712 StaParams.supported_oper_classes_len =
9713 params->supported_oper_classes_len;
9714
9715 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309716 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009717 params->ext_capab,
9718 sizeof(StaParams.extn_capability));
9719
9720 if (NULL != params->ht_capa) {
9721 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309722 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009723 sizeof(tSirHTCap));
9724 }
9725
9726 StaParams.supported_rates_len =
9727 params->supported_rates_len;
9728
9729 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9730 * The supported_rates array , for all the structures propogating till Add Sta
9731 * to the firmware has to be modified , if the supplicant (ieee80211) is
9732 * modified to send more rates.
9733 */
9734
9735 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
9736 */
9737 if (StaParams.supported_rates_len >
9738 SIR_MAC_MAX_SUPP_RATES)
9739 StaParams.supported_rates_len =
9740 SIR_MAC_MAX_SUPP_RATES;
9741
9742 if (0 != StaParams.supported_rates_len) {
9743 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309744 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009745 params->supported_rates,
9746 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009747 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009748 StaParams.supported_rates_len);
9749 for (i = 0; i < StaParams.supported_rates_len;
9750 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009751 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009752 StaParams.supported_rates[i]);
9753 }
9754
9755 if (NULL != params->vht_capa) {
9756 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309757 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009758 params->vht_capa,
9759 sizeof(tSirVHTCap));
9760 }
9761
9762 if (0 != params->ext_capab_len) {
9763 /*Define A Macro : TODO Sunil */
9764 if ((1 << 4) & StaParams.extn_capability[3]) {
9765 isBufSta = 1;
9766 }
9767 /* TDLS Channel Switching Support */
9768 if ((1 << 6) & StaParams.extn_capability[3]) {
9769 isOffChannelSupported = 1;
9770 }
9771 }
9772
Nitesh Shah99934ac2016-09-05 15:54:08 +05309773 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +05309774 (params->ht_capa || params->vht_capa ||
9775 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +05309776 is_qos_wmm_sta = true;
9777
9778 hdd_notice("%s: TDLS Peer is QOS capable"
9779 " is_qos_wmm_sta= %d HTcapPresent = %d",
9780 __func__, is_qos_wmm_sta,
9781 StaParams.htcap_present);
9782
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009783 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +05309784 &StaParams,
9785 isBufSta,
9786 isOffChannelSupported,
9787 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309788 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009789 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009790 return -EINVAL;
9791 }
9792
9793 status =
9794 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
9795 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309796 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009797 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009798 return -EINVAL;
9799 }
9800 }
9801#endif
9802 }
9803 EXIT();
9804 return ret;
9805}
9806
9807/**
9808 * wlan_hdd_change_station() - cfg80211 change station handler function
9809 * @wiphy: Pointer to the wiphy structure
9810 * @dev: Pointer to the net device.
9811 * @mac: bssid
9812 * @params: Pointer to station parameters
9813 *
9814 * This is the cfg80211 change station handler function which invokes
9815 * the internal function @__wlan_hdd_change_station with
9816 * SSR protection.
9817 *
9818 * Return: 0 for success, error number on failure.
9819 */
9820#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
9821static int wlan_hdd_change_station(struct wiphy *wiphy,
9822 struct net_device *dev,
9823 const u8 *mac,
9824 struct station_parameters *params)
9825#else
9826static int wlan_hdd_change_station(struct wiphy *wiphy,
9827 struct net_device *dev,
9828 u8 *mac,
9829 struct station_parameters *params)
9830#endif
9831{
9832 int ret;
9833
9834 cds_ssr_protect(__func__);
9835 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
9836 cds_ssr_unprotect(__func__);
9837
9838 return ret;
9839}
9840
9841/*
9842 * FUNCTION: __wlan_hdd_cfg80211_add_key
9843 * This function is used to initialize the key information
9844 */
9845static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
9846 struct net_device *ndev,
9847 u8 key_index, bool pairwise,
9848 const u8 *mac_addr,
9849 struct key_params *params)
9850{
9851 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9852 tCsrRoamSetKey setKey;
9853 int status;
9854 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009855 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309856 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009857 hdd_context_t *pHddCtx;
9858 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9859
9860 ENTER();
9861
Anurag Chouhan6d760662016-02-20 16:05:43 +05309862 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009863 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009864 return -EINVAL;
9865 }
9866
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309867 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009868 TRACE_CODE_HDD_CFG80211_ADD_KEY,
9869 pAdapter->sessionId, params->key_len));
9870 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9871 status = wlan_hdd_validate_context(pHddCtx);
9872
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309873 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009874 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009875
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009876 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009877 hdd_device_mode_to_string(pAdapter->device_mode),
9878 pAdapter->device_mode);
9879
9880 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009881 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009882
9883 return -EINVAL;
9884 }
9885
9886 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009887 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009888
9889 return -EINVAL;
9890 }
9891
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009892 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009893
9894 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309895 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009896 setKey.keyId = key_index;
9897 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309898 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009899
9900 switch (params->cipher) {
9901 case WLAN_CIPHER_SUITE_WEP40:
9902 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9903 break;
9904
9905 case WLAN_CIPHER_SUITE_WEP104:
9906 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
9907 break;
9908
9909 case WLAN_CIPHER_SUITE_TKIP:
9910 {
9911 u8 *pKey = &setKey.Key[0];
9912 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
9913
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309914 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009915
9916 /*Supplicant sends the 32bytes key in this order
9917
9918 |--------------|----------|----------|
9919 | Tk1 |TX-MIC | RX Mic |
9920 |||--------------|----------|----------|
9921 <---16bytes---><--8bytes--><--8bytes-->
9922
9923 */
9924 /*Sme expects the 32 bytes key to be in the below order
9925
9926 |--------------|----------|----------|
9927 | Tk1 |RX-MIC | TX Mic |
9928 |||--------------|----------|----------|
9929 <---16bytes---><--8bytes--><--8bytes-->
9930 */
9931 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309932 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009933
9934 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309935 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009936
9937 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309938 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009939
9940 break;
9941 }
9942
9943 case WLAN_CIPHER_SUITE_CCMP:
9944 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
9945 break;
9946
9947#ifdef FEATURE_WLAN_WAPI
9948 case WLAN_CIPHER_SUITE_SMS4:
9949 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309950 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009951 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
9952 mac_addr, params->key,
9953 params->key_len);
9954 return 0;
9955 }
9956#endif
9957
9958#ifdef FEATURE_WLAN_ESE
9959 case WLAN_CIPHER_SUITE_KRK:
9960 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
9961 break;
9962#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9963 case WLAN_CIPHER_SUITE_BTK:
9964 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
9965 break;
9966#endif
9967#endif
9968
9969#ifdef WLAN_FEATURE_11W
9970 case WLAN_CIPHER_SUITE_AES_CMAC:
9971 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
9972 break;
9973#endif
9974
9975 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009976 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009977 return -EOPNOTSUPP;
9978 }
9979
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009980 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009981
9982 if (!pairwise) {
9983 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009984 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009985 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05309986 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009987 } else {
9988 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009989 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009990 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309991 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009992 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009993 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009994 /* if a key is already installed, block all subsequent ones */
9995 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009996 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009997 return 0;
9998 }
9999
10000 setKey.keyDirection = eSIR_TX_RX;
10001 /*Set the group key */
10002 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10003 pAdapter->sessionId, &setKey, &roamId);
10004
10005 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010006 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010007 return -EINVAL;
10008 }
10009 /*Save the keys here and call sme_roam_set_key for setting
10010 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010011 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010012 &setKey, sizeof(tCsrRoamSetKey));
10013
10014 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10015 return status;
10016 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010017 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10018 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010019 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10020 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010021 status = wlansap_set_key_sta(
10022 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010023 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010024 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010025 __LINE__, status);
10026 }
10027 }
10028
10029 /* Save the key in ap ctx for use on START_BASS and restart */
10030 if (pairwise ||
10031 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10032 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010033 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010034 sizeof(tCsrRoamSetKey));
10035 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010036 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010037 sizeof(tCsrRoamSetKey));
10038
Krunal Sonib4326f22016-03-10 13:05:51 -080010039 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10040 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010041 hdd_wext_state_t *pWextState =
10042 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10043 hdd_station_ctx_t *pHddStaCtx =
10044 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10045
10046 if (!pairwise) {
10047 /* set group key */
10048 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010049 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010050 __func__, __LINE__);
10051 hdd_perform_roam_set_key_complete(pAdapter);
10052 }
10053 }
10054
10055 pWextState->roamProfile.Keys.KeyLength[key_index] =
10056 (u8) params->key_len;
10057
10058 pWextState->roamProfile.Keys.defaultIndex = key_index;
10059
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010060 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010061 KeyMaterial[key_index][0], params->key,
10062 params->key_len);
10063
10064 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10065
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010066 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010067 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10068 setKey.keyDirection);
10069
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010070 /* The supplicant may attempt to set the PTK once pre-authentication
10071 is done. Save the key in the UMAC and include it in the ADD BSS
10072 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010073 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010074 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010075 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010076 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010077 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010078 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010079 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010080 return -EINVAL;
10081 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010082
10083 /* issue set key request to SME */
10084 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10085 pAdapter->sessionId, &setKey, &roamId);
10086
10087 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010088 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010089 pHddStaCtx->roam_info.roamingState =
10090 HDD_ROAM_STATE_NONE;
10091 return -EINVAL;
10092 }
10093
10094 /* in case of IBSS as there was no information available about WEP keys during
10095 * IBSS join, group key intialized with NULL key, so re-initialize group key
10096 * with correct value*/
10097 if ((eCSR_BSS_TYPE_START_IBSS ==
10098 pWextState->roamProfile.BSSType)
10099 &&
10100 !((IW_AUTH_KEY_MGMT_802_1X ==
10101 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10102 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10103 pHddStaCtx->conn_info.authType)
10104 )
10105 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10106 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10107 )
10108 ) {
10109 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010110 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010111
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010112 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010113 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10114 setKey.keyDirection);
10115
10116 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10117 pAdapter->sessionId, &setKey,
10118 &roamId);
10119
10120 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010121 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010122 pHddStaCtx->roam_info.roamingState =
10123 HDD_ROAM_STATE_NONE;
10124 return -EINVAL;
10125 }
10126 }
10127 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010128 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010129 return 0;
10130}
10131
10132static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10133 struct net_device *ndev,
10134 u8 key_index, bool pairwise,
10135 const u8 *mac_addr,
10136 struct key_params *params)
10137{
10138 int ret;
10139 cds_ssr_protect(__func__);
10140 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10141 mac_addr, params);
10142 cds_ssr_unprotect(__func__);
10143
10144 return ret;
10145}
10146
10147/*
10148 * FUNCTION: __wlan_hdd_cfg80211_get_key
10149 * This function is used to get the key information
10150 */
10151static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10152 struct net_device *ndev,
10153 u8 key_index, bool pairwise,
10154 const u8 *mac_addr, void *cookie,
10155 void (*callback)(void *cookie,
10156 struct key_params *)
10157 )
10158{
10159 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10160 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10161 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10162 struct key_params params;
10163
10164 ENTER();
10165
Anurag Chouhan6d760662016-02-20 16:05:43 +053010166 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010167 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010168 return -EINVAL;
10169 }
10170
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010171 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010172 hdd_device_mode_to_string(pAdapter->device_mode),
10173 pAdapter->device_mode);
10174
10175 memset(&params, 0, sizeof(params));
10176
10177 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010178 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010179 key_index);
10180 return -EINVAL;
10181 }
10182
10183 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10184 case eCSR_ENCRYPT_TYPE_NONE:
10185 params.cipher = IW_AUTH_CIPHER_NONE;
10186 break;
10187
10188 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10189 case eCSR_ENCRYPT_TYPE_WEP40:
10190 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10191 break;
10192
10193 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10194 case eCSR_ENCRYPT_TYPE_WEP104:
10195 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10196 break;
10197
10198 case eCSR_ENCRYPT_TYPE_TKIP:
10199 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10200 break;
10201
10202 case eCSR_ENCRYPT_TYPE_AES:
10203 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10204 break;
10205
10206 default:
10207 params.cipher = IW_AUTH_CIPHER_NONE;
10208 break;
10209 }
10210
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010211 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010212 TRACE_CODE_HDD_CFG80211_GET_KEY,
10213 pAdapter->sessionId, params.cipher));
10214
10215 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10216 params.seq_len = 0;
10217 params.seq = NULL;
10218 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10219 callback(cookie, &params);
10220
10221 EXIT();
10222 return 0;
10223}
10224
10225static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10226 struct net_device *ndev,
10227 u8 key_index, bool pairwise,
10228 const u8 *mac_addr, void *cookie,
10229 void (*callback)(void *cookie,
10230 struct key_params *)
10231 )
10232{
10233 int ret;
10234
10235 cds_ssr_protect(__func__);
10236 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10237 mac_addr, cookie, callback);
10238 cds_ssr_unprotect(__func__);
10239
10240 return ret;
10241}
10242
10243/**
10244 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10245 * @wiphy: wiphy interface context
10246 * @ndev: pointer to net device
10247 * @key_index: Key index used in 802.11 frames
10248 * @unicast: true if it is unicast key
10249 * @multicast: true if it is multicast key
10250 *
10251 * This function is required for cfg80211_ops API.
10252 * It is used to delete the key information
10253 * Underlying hardware implementation does not have API to delete the
10254 * encryption key. It is automatically deleted when the peer is
10255 * removed. Hence this function currently does nothing.
10256 * Future implementation may interprete delete key operation to
10257 * replacing the key with a random junk value, effectively making it
10258 * useless.
10259 *
10260 * Return: status code, always 0.
10261 */
10262
10263static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10264 struct net_device *ndev,
10265 u8 key_index,
10266 bool pairwise, const u8 *mac_addr)
10267{
10268 EXIT();
10269 return 0;
10270}
10271
10272/**
10273 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10274 * @wiphy: Pointer to wiphy structure.
10275 * @dev: Pointer to net_device structure.
10276 * @key_index: key index
10277 * @pairwise: pairwise
10278 * @mac_addr: mac address
10279 *
10280 * This is the cfg80211 delete key handler function which invokes
10281 * the internal function @__wlan_hdd_cfg80211_del_key with
10282 * SSR protection.
10283 *
10284 * Return: 0 for success, error number on failure.
10285 */
10286static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10287 struct net_device *dev,
10288 u8 key_index,
10289 bool pairwise, const u8 *mac_addr)
10290{
10291 int ret;
10292
10293 cds_ssr_protect(__func__);
10294 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10295 pairwise, mac_addr);
10296 cds_ssr_unprotect(__func__);
10297
10298 return ret;
10299}
10300
10301/*
10302 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10303 * This function is used to set the default tx key index
10304 */
10305static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10306 struct net_device *ndev,
10307 u8 key_index,
10308 bool unicast, bool multicast)
10309{
10310 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10311 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10312 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10313 hdd_context_t *pHddCtx;
10314 int status;
10315
10316 ENTER();
10317
Anurag Chouhan6d760662016-02-20 16:05:43 +053010318 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010319 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010320 return -EINVAL;
10321 }
10322
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010323 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010324 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10325 pAdapter->sessionId, key_index));
10326
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010327 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010328 hdd_device_mode_to_string(pAdapter->device_mode),
10329 pAdapter->device_mode, key_index);
10330
10331 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010332 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010333 return -EINVAL;
10334 }
10335
10336 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10337 status = wlan_hdd_validate_context(pHddCtx);
10338
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010339 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010340 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010341
Krunal Sonib4326f22016-03-10 13:05:51 -080010342 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10343 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010344 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10345 pHddStaCtx->conn_info.ucEncryptionType) &&
10346 (eCSR_ENCRYPT_TYPE_AES !=
10347 pHddStaCtx->conn_info.ucEncryptionType)) {
10348 /* If default key index is not same as previous one,
10349 * then update the default key index */
10350
10351 tCsrRoamSetKey setKey;
10352 uint32_t roamId = 0xFF;
10353 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10354
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010355 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010356
10357 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010358 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010359 setKey.keyId = key_index;
10360 setKey.keyLength = Keys->KeyLength[key_index];
10361
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010362 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010363 &Keys->KeyMaterial[key_index][0],
10364 Keys->KeyLength[key_index]);
10365
10366 setKey.keyDirection = eSIR_TX_RX;
10367
Anurag Chouhanc5548422016-02-24 18:33:27 +053010368 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010369 &pHddStaCtx->conn_info.bssId);
10370
10371 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10372 pWextState->roamProfile.EncryptionType.
10373 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10374 /* In the case of dynamic wep supplicant hardcodes DWEP type
10375 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10376 * WEP-40 encryption. In this canse the key length is 5 but the
10377 * encryption type is 104 hence checking the key langht(5) and
10378 * encryption type(104) and switching encryption type to 40*/
10379 pWextState->roamProfile.EncryptionType.
10380 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10381 pWextState->roamProfile.mcEncryptionType.
10382 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10383 }
10384
10385 setKey.encType =
10386 pWextState->roamProfile.EncryptionType.
10387 encryptionType[0];
10388
10389 /* Issue set key request */
10390 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10391 pAdapter->sessionId, &setKey,
10392 &roamId);
10393
10394 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010395 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010396 status);
10397 return -EINVAL;
10398 }
10399 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010400 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010401 /* In SoftAp mode setting key direction for default mode */
10402 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10403 pWextState->roamProfile.EncryptionType.encryptionType[0])
10404 && (eCSR_ENCRYPT_TYPE_AES !=
10405 pWextState->roamProfile.EncryptionType.
10406 encryptionType[0])) {
10407 /* Saving key direction for default key index to TX default */
10408 hdd_ap_ctx_t *pAPCtx =
10409 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10410 pAPCtx->wepKey[key_index].keyDirection =
10411 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010412 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010413 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010414 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010415 }
10416 }
10417
10418 EXIT();
10419 return status;
10420}
10421
10422static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10423 struct net_device *ndev,
10424 u8 key_index,
10425 bool unicast, bool multicast)
10426{
10427 int ret;
10428 cds_ssr_protect(__func__);
10429 ret =
10430 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10431 multicast);
10432 cds_ssr_unprotect(__func__);
10433
10434 return ret;
10435}
10436
Abhishek Singhc9941602016-08-09 16:06:22 +053010437/*
10438 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10439 * @wiphy: wiphy pointer
10440 * @channel: channel of the BSS
10441 * @bssid: Bssid of BSS
10442 * @ssid: Ssid of the BSS
10443 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010444 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010445 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010446 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010447#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010448static
Abhishek Singhc9941602016-08-09 16:06:22 +053010449struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10450 struct ieee80211_channel *channel, const u8 *bssid,
10451 const u8 *ssid, size_t ssid_len)
10452{
10453 return cfg80211_get_bss(wiphy, channel, bssid,
10454 ssid,
10455 ssid_len,
10456 WLAN_CAPABILITY_ESS,
10457 WLAN_CAPABILITY_ESS);
10458}
10459#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010460static
Abhishek Singhc9941602016-08-09 16:06:22 +053010461struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10462 struct ieee80211_channel *channel, const u8 *bssid,
10463 const u8 *ssid, size_t ssid_len)
10464{
10465 return cfg80211_get_bss(wiphy, channel, bssid,
10466 ssid,
10467 ssid_len,
10468 IEEE80211_BSS_TYPE_ESS,
10469 IEEE80211_PRIVACY_ANY);
10470}
10471#endif
10472
10473
10474/*
10475 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10476 * interface that BSS might have been lost.
10477 * @pAdapter: adaptor
10478 * @bssid: bssid which might have been lost
10479 *
10480 * Return: bss which is unlinked from kernel cache
10481 */
10482struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10483 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010484{
10485 struct net_device *dev = pAdapter->dev;
10486 struct wireless_dev *wdev = dev->ieee80211_ptr;
10487 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010488 struct cfg80211_bss *bss = NULL;
10489
Abhishek Singhc9941602016-08-09 16:06:22 +053010490 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10491 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010492 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010493 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010494 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010495 hdd_info("cfg80211_unlink_bss called for BSSID "
10496 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010497 cfg80211_unlink_bss(wiphy, bss);
10498 }
10499 return bss;
10500}
10501
Abhishek Singhc9941602016-08-09 16:06:22 +053010502
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010503/**
10504 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10505 * @pAdapter: Pointer to adapter
10506 * @bss_desc: Pointer to bss descriptor
10507 *
10508 * This function is used to inform the BSS details to nl80211 interface.
10509 *
10510 * Return: struct cfg80211_bss pointer
10511 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010512struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10513 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010514{
10515 /*
10516 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10517 * already exists in bss data base of cfg80211 for that particular BSS
10518 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10519 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10520 * As of now there is no possibility to get the mgmt(probe response)
10521 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10522 * and passing to cfg80211_inform_bss_frame.
10523 */
10524 struct net_device *dev = pAdapter->dev;
10525 struct wireless_dev *wdev = dev->ieee80211_ptr;
10526 struct wiphy *wiphy = wdev->wiphy;
10527 int chan_no = bss_desc->channelId;
10528#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10529 qcom_ie_age *qie_age = NULL;
10530 int ie_length =
10531 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10532#else
10533 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10534#endif
10535 const char *ie =
10536 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10537 unsigned int freq;
10538 struct ieee80211_channel *chan;
10539 struct ieee80211_mgmt *mgmt = NULL;
10540 struct cfg80211_bss *bss_status = NULL;
10541 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10542 int rssi = 0;
10543 hdd_context_t *pHddCtx;
10544 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010545 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010546 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010547
10548 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10549 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010550 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010551 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010552
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010553 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010554 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10555 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010556 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010557 return NULL;
10558 }
10559
10560 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10561
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010562 /* Android does not want the timestamp from the frame.
10563 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010564 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010565 mgmt->u.probe_resp.timestamp =
10566 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010567
10568 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10569 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10570
10571#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10572 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10573 /* Assuming this is the last IE, copy at the end */
10574 ie_length -= sizeof(qcom_ie_age);
10575 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10576 qie_age->element_id = QCOM_VENDOR_IE_ID;
10577 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10578 qie_age->oui_1 = QCOM_OUI1;
10579 qie_age->oui_2 = QCOM_OUI2;
10580 qie_age->oui_3 = QCOM_OUI3;
10581 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
10582 qie_age->age =
Anurag Chouhan210db072016-02-22 18:42:15 +053010583 qdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010584 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010585 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10586 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010587 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10588 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010589#endif
10590
10591 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10592 if (bss_desc->fProbeRsp) {
10593 mgmt->frame_control |=
10594 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10595 } else {
10596 mgmt->frame_control |=
10597 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10598 }
10599
10600 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
10601 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
10602 freq =
10603 ieee80211_channel_to_frequency(chan_no,
10604 IEEE80211_BAND_2GHZ);
10605 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
10606 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
10607 freq =
10608 ieee80211_channel_to_frequency(chan_no,
10609 IEEE80211_BAND_5GHZ);
10610 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010611 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010612 kfree(mgmt);
10613 return NULL;
10614 }
10615
10616 chan = __ieee80211_get_channel(wiphy, freq);
10617 /* When the band is changed on the fly using the GUI, three things are done
10618 * 1. scan abort
10619 * 2. flush scan results from cache
10620 * 3. update the band with the new band user specified (refer to the
10621 * hdd_set_band_helper function) as part of the scan abort, message will be
10622 * queued to PE and we proceed with flushing and changinh the band.
10623 * PE will stop the scanning further and report back the results what ever
10624 * it had till now by calling the call back function.
10625 * if the time between update band and scandone call back is sufficient
10626 * enough the band change reflects in SME, SME validates the channels
10627 * and discards the channels correponding to previous band and calls back
10628 * with zero bss results. but if the time between band update and scan done
10629 * callback is very small then band change will not reflect in SME and SME
10630 * reports to HDD all the channels correponding to previous band.this is due
10631 * to race condition.but those channels are invalid to the new band and so
10632 * this function __ieee80211_get_channel will return NULL.Each time we
10633 * report scan result with this pointer null warning kernel trace is printed.
10634 * if the scan results contain large number of APs continuosly kernel
10635 * warning trace is printed and it will lead to apps watch dog bark.
10636 * So drop the bss and continue to next bss.
10637 */
10638 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010639 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10640 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010641 kfree(mgmt);
10642 return NULL;
10643 }
10644
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010645 /* Based on .ini configuration, raw rssi can be reported for bss.
10646 * Raw rssi is typically used for estimating power.
10647 */
10648
10649 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10650 bss_desc->rssi;
10651
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010652 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010653 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010654
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010655 hdd_notice("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010656 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010657 (int)(rssi / 100),
10658 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010659
10660 bss_status =
10661 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10662 GFP_KERNEL);
10663 kfree(mgmt);
10664 return bss_status;
10665}
10666
10667/**
10668 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10669 * @pAdapter: Pointer to adapter
10670 * @pRoamInfo: Pointer to roam info
10671 *
10672 * This function is used to update the BSS data base of CFG8011
10673 *
10674 * Return: struct cfg80211_bss pointer
10675 */
10676struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10677 tCsrRoamInfo *pRoamInfo)
10678{
10679 tCsrRoamConnectedProfile roamProfile;
10680 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10681 struct cfg80211_bss *bss = NULL;
10682
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010683 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10684 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10685
10686 if (NULL != roamProfile.pBssDesc) {
10687 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10688 roamProfile.pBssDesc);
10689
10690 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010691 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010692
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010693 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010694 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010695 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010696 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010697 return bss;
10698}
10699/**
10700 * wlan_hdd_cfg80211_update_bss() - update bss
10701 * @wiphy: Pointer to wiphy
10702 * @pAdapter: Pointer to adapter
10703 * @scan_time: scan request timestamp
10704 *
10705 * Return: zero if success, non-zero otherwise
10706 */
10707int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10708 hdd_adapter_t *pAdapter,
10709 uint32_t scan_time)
10710{
10711 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10712 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010713 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010714 tScanResultHandle pResult;
10715 struct cfg80211_bss *bss_status = NULL;
10716 hdd_context_t *pHddCtx;
10717 int ret;
10718
10719 ENTER();
10720
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010721 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010722 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10723 NO_SESSION, pAdapter->sessionId));
10724
10725 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10726 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010727 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010728 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010729
10730 /* start getting scan results and populate cgf80211 BSS database */
10731 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
10732
10733 /* no scan results */
10734 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010735 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053010736 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010737 }
10738
10739 pScanResult = sme_scan_result_get_first(hHal, pResult);
10740
10741 while (pScanResult) {
10742 /*
10743 * - cfg80211_inform_bss() is not updating ie field of bss
10744 * entry if entry already exists in bss data base of cfg80211
10745 * for that particular BSS ID. Using cfg80211_inform_bss_frame
10746 * to update thebss entry instead of cfg80211_inform_bss,
10747 * But this call expects mgmt packet as input. As of now
10748 * there is no possibility to get the mgmt(probe response)
10749 * frame from PE, converting bss_desc to
10750 * ieee80211_mgmt(probe response) and passing to c
10751 * fg80211_inform_bss_frame.
10752 * - Update BSS only if beacon timestamp is later than
10753 * scan request timestamp.
10754 */
10755 if ((scan_time == 0) ||
10756 (scan_time <
10757 pScanResult->BssDescriptor.nReceivedTime)) {
10758 bss_status =
10759 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10760 &pScanResult->BssDescriptor);
10761
10762 if (NULL == bss_status) {
10763 hdd_info("NULL returned by cfg80211_inform_bss_frame");
10764 } else {
10765 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010766 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010767 bss_status);
10768 }
10769 } else {
10770 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
10771 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
10772 }
10773 pScanResult = sme_scan_result_get_next(hHal, pResult);
10774 }
10775
10776 sme_scan_result_purge(hHal, pResult);
10777 /*
10778 * For SAP mode, scan is invoked by hostapd during SAP start
10779 * if hostapd is restarted, we need to flush previous scan
10780 * result so that it will reflect environment change
10781 */
Krunal Sonib4326f22016-03-10 13:05:51 -080010782 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010783#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
10784 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
10785#endif
10786 )
10787 sme_scan_flush_result(hHal);
10788
10789 EXIT();
10790 return 0;
10791}
10792
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010793/**
10794 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
10795 * @pAdapter: Pointer to adapter
10796 * @pRoamInfo: Pointer to roam info
10797 * @index: Index
10798 * @preauth: Preauth flag
10799 *
10800 * This function is used to notify the supplicant of a new PMKSA candidate.
10801 *
10802 * Return: 0 for success, non-zero for failure
10803 */
10804int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
10805 tCsrRoamInfo *pRoamInfo,
10806 int index, bool preauth)
10807{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010808 struct net_device *dev = pAdapter->dev;
10809 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
10810
10811 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010812 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010813
10814 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010815 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010816 return -EINVAL;
10817 }
10818
10819 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010820 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010821 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
10822 cfg80211_pmksa_candidate_notify(dev, index,
10823 pRoamInfo->bssid.bytes,
10824 preauth, GFP_KERNEL);
10825 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010826 return 0;
10827}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010828
10829#ifdef FEATURE_WLAN_LFR_METRICS
10830/**
10831 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
10832 * @pAdapter: Pointer to adapter
10833 * @pRoamInfo: Pointer to roam info
10834 *
10835 * 802.11r/LFR metrics reporting function to report preauth initiation
10836 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010837 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010838 */
10839#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010840QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010841 tCsrRoamInfo *pRoamInfo)
10842{
10843 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10844 union iwreq_data wrqu;
10845
10846 ENTER();
10847
10848 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010849 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010850 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010851 }
10852
10853 /* create the event */
10854 memset(&wrqu, 0, sizeof(wrqu));
10855 memset(metrics_notification, 0, sizeof(metrics_notification));
10856
10857 wrqu.data.pointer = metrics_notification;
10858 wrqu.data.length = scnprintf(metrics_notification,
10859 sizeof(metrics_notification),
10860 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
10861 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10862
10863 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10864 metrics_notification);
10865
10866 EXIT();
10867
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010868 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010869}
10870
10871/**
10872 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10873 * @pAdapter: Pointer to adapter
10874 * @pRoamInfo: Pointer to roam info
10875 * @preauth_status: Preauth status
10876 *
10877 * 802.11r/LFR metrics reporting function to report handover initiation
10878 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010879 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010880 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010881QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010882wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
10883 tCsrRoamInfo *pRoamInfo,
10884 bool preauth_status)
10885{
10886 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10887 union iwreq_data wrqu;
10888
10889 ENTER();
10890
10891 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010892 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010893 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010894 }
10895
10896 /* create the event */
10897 memset(&wrqu, 0, sizeof(wrqu));
10898 memset(metrics_notification, 0, sizeof(metrics_notification));
10899
10900 scnprintf(metrics_notification, sizeof(metrics_notification),
10901 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
10902 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10903
10904 if (1 == preauth_status)
10905 strlcat(metrics_notification, " true",
10906 sizeof(metrics_notification));
10907 else
10908 strlcat(metrics_notification, " false",
10909 sizeof(metrics_notification));
10910
10911 wrqu.data.pointer = metrics_notification;
10912 wrqu.data.length = strlen(metrics_notification);
10913
10914 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10915 metrics_notification);
10916
10917 EXIT();
10918
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010919 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010920}
10921
10922/**
10923 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10924 * @pAdapter: Pointer to adapter
10925 * @pRoamInfo: Pointer to roam info
10926 *
10927 * 802.11r/LFR metrics reporting function to report handover initiation
10928 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010929 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010930 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010931QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010932 tCsrRoamInfo *pRoamInfo)
10933{
10934 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10935 union iwreq_data wrqu;
10936
10937 ENTER();
10938
10939 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010940 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010941 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010942 }
10943
10944 /* create the event */
10945 memset(&wrqu, 0, sizeof(wrqu));
10946 memset(metrics_notification, 0, sizeof(metrics_notification));
10947
10948 wrqu.data.pointer = metrics_notification;
10949 wrqu.data.length = scnprintf(metrics_notification,
10950 sizeof(metrics_notification),
10951 "QCOM: LFR_PREAUTH_HANDOVER "
10952 MAC_ADDRESS_STR,
10953 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10954
10955 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10956 metrics_notification);
10957
10958 EXIT();
10959
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010960 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010961}
10962#endif
10963
10964/**
10965 * hdd_select_cbmode() - select channel bonding mode
10966 * @pAdapter: Pointer to adapter
10967 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010968 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010969 *
10970 * Return: none
10971 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010972void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
10973 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010974{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010975 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010976 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010977 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010978
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010979 /*
10980 * CDS api expects secondary channel for calculating
10981 * the channel params
10982 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010983 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010984 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
10985 if (operationChannel >= 1 && operationChannel <= 5)
10986 sec_ch = operationChannel + 4;
10987 else if (operationChannel >= 6 && operationChannel <= 13)
10988 sec_ch = operationChannel - 4;
10989 }
10990
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010991 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010992 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010993
10994 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010995 eHddDot11Mode hdd_dot11_mode;
10996 uint8_t iniDot11Mode =
10997 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
10998
10999 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11000 switch (iniDot11Mode) {
11001 case eHDD_DOT11_MODE_AUTO:
11002 case eHDD_DOT11_MODE_11ac:
11003 case eHDD_DOT11_MODE_11ac_ONLY:
11004 if (sme_is_feature_supported_by_fw(DOT11AC))
11005 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11006 else
11007 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11008 break;
11009 case eHDD_DOT11_MODE_11n:
11010 case eHDD_DOT11_MODE_11n_ONLY:
11011 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11012 break;
11013 default:
11014 hdd_dot11_mode = iniDot11Mode;
11015 break;
11016 }
11017 ch_info->channel_width = ch_params->ch_width;
11018 ch_info->phy_mode =
11019 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011020 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011021 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011022 hdd_info("ch_info width %d, phymode %d channel %d",
11023 ch_info->channel_width, ch_info->phy_mode,
11024 ch_info->channel);
11025 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011026}
11027
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011028/**
11029 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11030 * @adapter: STA adapter
11031 * @roam_profile: STA roam profile
11032 *
11033 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11034 *
11035 * Return: false if sta-sap conc is not allowed, else return true
11036 */
11037static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11038 tCsrRoamProfile *roam_profile)
11039{
11040 hdd_context_t *hdd_ctx;
11041 hdd_adapter_t *ap_adapter;
11042 hdd_ap_ctx_t *hdd_ap_ctx;
11043 hdd_hostapd_state_t *hostapd_state;
11044 uint8_t channel = 0;
11045 QDF_STATUS status;
11046
11047 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11048 if (!hdd_ctx) {
11049 hdd_err("HDD context is NULL");
11050 return true;
11051 }
11052
11053 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11054 /* probably no sap running, no handling required */
11055 if (ap_adapter == NULL)
11056 return true;
11057
11058 /*
11059 * sap is not in started state, so it is fine to go ahead with sta.
11060 * if sap is currently doing CAC then don't allow sta to go further.
11061 */
11062 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11063 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11064 return true;
11065
11066 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11067 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11068 return false;
11069 }
11070
11071 /*
11072 * log and return error, if we allow STA to go through, we don't
11073 * know what is going to happen better stop sta connection
11074 */
11075 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11076 if (NULL == hdd_ap_ctx) {
11077 hdd_err("AP context not found");
11078 return false;
11079 }
11080
11081 /* sap is on non-dfs channel, nothing to handle */
11082 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11083 hdd_info("sap is on non-dfs channel, sta is allowed");
11084 return true;
11085 }
11086 /*
11087 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011088 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011089 */
11090 status = cds_get_channel_from_scan_result(adapter,
11091 roam_profile, &channel);
11092
Nitesh Shah59774522016-09-16 15:14:21 +053011093 /*
11094 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11095 * channels for roaming case.
11096 */
11097 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11098 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11099 return true;
11100 }
11101
11102 /*
11103 * If channel is 0 or DFS then better to call pcl and find out the
11104 * best channel. If channel is non-dfs 5 GHz then better move SAP
11105 * to STA's channel to make scc, so we have room for 3port MCC
11106 * scenario.
11107 */
11108 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011109 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11110 true);
11111
11112 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11113 qdf_event_reset(&hostapd_state->qdf_event);
11114 status = wlansap_set_channel_change_with_csa(
11115 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11116 hdd_ap_ctx->sapConfig.ch_width_orig);
11117
11118 if (QDF_STATUS_SUCCESS != status) {
11119 hdd_err("Set channel with CSA IE failed, can't allow STA");
11120 return false;
11121 }
11122
11123 /*
11124 * wait here for SAP to finish the channel switch. When channel
11125 * switch happens, SAP sends few beacons with CSA_IE. After
11126 * successfully Transmission of those beacons, it will move its
11127 * state from started to disconnected and move to new channel.
11128 * once it moves to new channel, sap again moves its state
11129 * machine from disconnected to started and set this event.
11130 * wait for 10 secs to finish this.
11131 */
11132 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11133 if (!QDF_IS_STATUS_SUCCESS(status)) {
11134 hdd_err("wait for qdf_event failed, STA not allowed!!");
11135 return false;
11136 }
11137
11138 return true;
11139}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011140
Krunal Soni31949422016-07-29 17:17:53 -070011141/**
11142 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011143 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011144 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011145 * @ssid_len: Length of ssid
11146 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011147 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011148 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011149 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011150 *
11151 * This function is used to start the association process
11152 *
11153 * Return: 0 for success, non-zero for failure
11154 */
Krunal Soni31949422016-07-29 17:17:53 -070011155static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011156 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011157 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011158 u8 operatingChannel,
11159 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011160{
11161 int status = 0;
11162 hdd_wext_state_t *pWextState;
11163 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011164 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011165 uint32_t roamId;
11166 tCsrRoamProfile *pRoamProfile;
11167 eCsrAuthType RSNAuthType;
11168 tSmeConfigParams *sme_config;
11169
11170 ENTER();
11171
11172 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11173 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011174 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011175
11176 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011177 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011178 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011179
11180 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011181 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011182 return -EINVAL;
11183 }
11184
11185 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011186 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11187 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011188
11189 if (pRoamProfile) {
11190 hdd_station_ctx_t *pHddStaCtx;
11191 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11192
11193 if (HDD_WMM_USER_MODE_NO_QOS ==
11194 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11195 /*QoS not enabled in cfg file */
11196 pRoamProfile->uapsd_mask = 0;
11197 } else {
11198 /*QoS enabled, update uapsd mask from cfg file */
11199 pRoamProfile->uapsd_mask =
11200 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11201 }
11202
11203 pRoamProfile->SSIDs.numOfSSIDs = 1;
11204 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011205 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011206 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011207 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011208 ssid, ssid_len);
11209
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011210 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011211 if (bssid) {
11212 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011213 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011214 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011215 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011216 /*
11217 * Save BSSID in seperate variable as
11218 * pRoamProfile's BSSID is getting zeroed out in the
11219 * association process. In case of join failure
11220 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011221 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011222 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011223 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011224 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011225 } else if (bssid_hint) {
11226 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011227 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011228 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011229 /*
11230 * Save BSSID in a separate variable as
11231 * pRoamProfile's BSSID is getting zeroed out in the
11232 * association process. In case of join failure
11233 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011234 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011235 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011236 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011237 hdd_info("bssid_hint is given by upper layer %pM",
11238 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011239 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011240 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011241 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011242 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011243 }
11244
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011245 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011246 pRoamProfile->SSIDs.SSIDList->SSID.length,
11247 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11248 operatingChannel);
11249
11250 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11251 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011252 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011253 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11254 }
11255#ifdef FEATURE_WLAN_WAPI
11256 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011257 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011258 switch (pAdapter->wapi_info.wapiAuthMode) {
11259 case WAPI_AUTH_MODE_PSK:
11260 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011261 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011262 pAdapter->wapi_info.wapiAuthMode);
11263 pRoamProfile->AuthType.authType[0] =
11264 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11265 break;
11266 }
11267 case WAPI_AUTH_MODE_CERT:
11268 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011269 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270 pAdapter->wapi_info.wapiAuthMode);
11271 pRoamProfile->AuthType.authType[0] =
11272 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11273 break;
11274 }
11275 } /* End of switch */
11276 if (pAdapter->wapi_info.wapiAuthMode ==
11277 WAPI_AUTH_MODE_PSK
11278 || pAdapter->wapi_info.wapiAuthMode ==
11279 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011280 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011281 pRoamProfile->AuthType.numEntries = 1;
11282 pRoamProfile->EncryptionType.numEntries = 1;
11283 pRoamProfile->EncryptionType.encryptionType[0] =
11284 eCSR_ENCRYPT_TYPE_WPI;
11285 pRoamProfile->mcEncryptionType.numEntries = 1;
11286 pRoamProfile->mcEncryptionType.
11287 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11288 }
11289 }
Krunal Soni31949422016-07-29 17:17:53 -070011290#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011291#ifdef WLAN_FEATURE_GTK_OFFLOAD
11292 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011293 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11294 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011295 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11296 sizeof(tSirGtkOffloadParams));
11297 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11298 GTK_OFFLOAD_DISABLE;
11299 }
11300#endif
11301 pRoamProfile->csrPersona = pAdapter->device_mode;
11302
11303 if (operatingChannel) {
11304 pRoamProfile->ChannelInfo.ChannelList =
11305 &operatingChannel;
11306 pRoamProfile->ChannelInfo.numOfChannels = 1;
11307 } else {
11308 pRoamProfile->ChannelInfo.ChannelList = NULL;
11309 pRoamProfile->ChannelInfo.numOfChannels = 0;
11310 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011311 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011312 && operatingChannel) {
11313 /*
11314 * Need to post the IBSS power save parameters
11315 * to WMA. WMA will configure this parameters
11316 * to firmware if power save is enabled by the
11317 * firmware.
11318 */
11319 status = hdd_set_ibss_power_save_params(pAdapter);
11320
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011321 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011322 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011323 return -EINVAL;
11324 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011325 pRoamProfile->ch_params.ch_width =
11326 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011327 /*
11328 * In IBSS mode while operating in 2.4 GHz,
11329 * the device supports only 20 MHz.
11330 */
11331 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11332 pRoamProfile->ch_params.ch_width =
11333 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011334 hdd_select_cbmode(pAdapter, operatingChannel,
11335 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011336 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011337 /*
11338 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11339 * or pmf=2 is an explicit configuration in the supplicant
11340 * configuration, drop the connection request.
11341 */
11342 if (pWextState->roamProfile.MFPEnabled &&
11343 !(pWextState->roamProfile.MFPRequired ||
11344 pWextState->roamProfile.MFPCapable)) {
11345 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11346 pWextState->roamProfile.MFPEnabled,
11347 pWextState->roamProfile.MFPRequired,
11348 pWextState->roamProfile.MFPCapable);
11349 return -EINVAL;
11350 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011351
Krunal Soni3091bcc2016-06-23 12:28:21 -070011352 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011353 hdd_err("Connection refused: conn in progress");
11354 return -EINVAL;
11355 }
11356
Krunal Soni31949422016-07-29 17:17:53 -070011357 /*
11358 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011359 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011360 * enhancements, the supplicant is not issuing the scan command
11361 * now. So the unicast frames which are sent from the host are
11362 * not having the additional IEs. If it is P2P CLIENT and there
11363 * is no additional IE present in roamProfile, then use the
11364 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011365 */
11366
Krunal Sonib4326f22016-03-10 13:05:51 -080011367 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011368 (!pRoamProfile->pAddIEScan)) {
11369 pRoamProfile->pAddIEScan =
11370 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11371 pRoamProfile->nAddIEScanLength =
11372 pAdapter->scan_info.scanAddIE.length;
11373 }
11374 /*
11375 * When policy manager is enabled from ini file, we shouldn't
11376 * check for other concurrency rules.
11377 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011378 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011379 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011380 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011381 pAdapter, pRoamProfile, &roamId))
11382 return 0;
11383 }
11384
Krunal Soni3091bcc2016-06-23 12:28:21 -070011385 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011386 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11387 pRoamProfile))) {
11388 hdd_err("sap-sta conc will fail, can't allow sta");
11389 hdd_conn_set_connection_state(pAdapter,
11390 eConnectionState_NotConnected);
11391 return -ENOMEM;
11392 }
11393
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011394 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011395 if (!sme_config) {
11396 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011397 hdd_conn_set_connection_state(pAdapter,
11398 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011399 return -ENOMEM;
11400 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011401 qdf_mem_zero(sme_config, sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011402 sme_get_config_param(pHddCtx->hHal, sme_config);
11403 /* These values are not sessionized. So, any change in these SME
11404 * configs on an older or parallel interface will affect the
11405 * cb mode. So, restoring the default INI params before starting
11406 * interfaces such as sta, cli etc.,
11407 */
11408 sme_config->csrConfig.channelBondingMode5GHz =
11409 pHddCtx->config->nChannelBondingMode5GHz;
11410 sme_config->csrConfig.channelBondingMode24GHz =
11411 pHddCtx->config->nChannelBondingMode24GHz;
11412 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011413 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011414 /*
11415 * Change conn_state to connecting before sme_roam_connect(),
11416 * because sme_roam_connect() has a direct path to call
11417 * hdd_sme_roam_callback(), which will change the conn_state
11418 * If direct path, conn_state will be accordingly changed to
11419 * NotConnected or Associated by either
11420 * hdd_association_completion_handler() or
11421 * hdd_dis_connect_handler() in sme_RoamCallback()if
11422 * sme_RomConnect is to be queued,
11423 * Connecting state will remain until it is completed.
11424 *
11425 * If connection state is not changed, connection state will
11426 * remain in eConnectionState_NotConnected state.
11427 * In hdd_association_completion_handler, "hddDisconInProgress"
11428 * is set to true if conn state is
11429 * eConnectionState_NotConnected.
11430 * If "hddDisconInProgress" is set to true then cfg80211 layer
11431 * is not informed of connect result indication which
11432 * is an issue.
11433 */
11434 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011435 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011436 hdd_conn_set_connection_state(pAdapter,
11437 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011438
11439 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11440 pAdapter->sessionId, pRoamProfile,
11441 &roamId);
11442
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011443 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011444 (QDF_STA_MODE == pAdapter->device_mode ||
11445 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011446 hdd_err("sme_roam_connect (session %d) failed with "
11447 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011448 pAdapter->sessionId, status);
11449 /* change back to NotAssociated */
11450 hdd_conn_set_connection_state(pAdapter,
11451 eConnectionState_NotConnected);
11452 }
11453
11454 pRoamProfile->ChannelInfo.ChannelList = NULL;
11455 pRoamProfile->ChannelInfo.numOfChannels = 0;
11456
11457 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011458 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011459 return -EINVAL;
11460 }
11461 EXIT();
11462 return status;
11463}
11464
11465/**
11466 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11467 * @pAdapter: Pointer to adapter
11468 * @auth_type: Auth type
11469 *
11470 * This function is used to set the authentication type (OPEN/SHARED).
11471 *
11472 * Return: 0 for success, non-zero for failure
11473 */
11474static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11475 enum nl80211_auth_type auth_type)
11476{
11477 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11478 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11479
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011480 /*set authentication type */
11481 switch (auth_type) {
11482 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011483 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011484 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11485 break;
11486
11487 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011488 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011489 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011490 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11491 break;
11492
11493 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011494 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011495 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11496 break;
11497#ifdef FEATURE_WLAN_ESE
11498 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011499 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011500 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11501 break;
11502#endif
11503
11504 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011505 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011506 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11507 return -EINVAL;
11508 }
11509
11510 pWextState->roamProfile.AuthType.authType[0] =
11511 pHddStaCtx->conn_info.authType;
11512 return 0;
11513}
11514
11515/**
11516 * wlan_hdd_set_akm_suite() - set key management type
11517 * @pAdapter: Pointer to adapter
11518 * @key_mgmt: Key management type
11519 *
11520 * This function is used to set the key mgmt type(PSK/8021x).
11521 *
11522 * Return: 0 for success, non-zero for failure
11523 */
11524static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11525{
11526 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11527
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011528#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11529#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11530 /*set key mgmt type */
11531 switch (key_mgmt) {
11532 case WLAN_AKM_SUITE_PSK:
11533 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011534 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011535 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011536 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11537 break;
11538
11539 case WLAN_AKM_SUITE_8021X_SHA256:
11540 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011541 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011542 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011543 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11544 break;
11545#ifdef FEATURE_WLAN_ESE
11546#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11547#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11548 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011549 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011550 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11551 break;
11552#endif
11553#ifndef WLAN_AKM_SUITE_OSEN
11554#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11555#endif
11556 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011557 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011558 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11559 break;
11560
11561 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011562 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011563 return -EINVAL;
11564
11565 }
11566 return 0;
11567}
11568
11569/**
11570 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11571 * @pAdapter: Pointer to adapter
11572 * @cipher: Cipher type
11573 * @ucast: Unicast flag
11574 *
11575 * This function is used to set the encryption type
11576 * (NONE/WEP40/WEP104/TKIP/CCMP).
11577 *
11578 * Return: 0 for success, non-zero for failure
11579 */
11580static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11581 u32 cipher, bool ucast)
11582{
11583 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11584 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11585 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11586
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011588 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011589 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11590 } else {
11591
11592 /*set encryption method */
11593 switch (cipher) {
11594 case IW_AUTH_CIPHER_NONE:
11595 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11596 break;
11597
11598 case WLAN_CIPHER_SUITE_WEP40:
11599 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11600 break;
11601
11602 case WLAN_CIPHER_SUITE_WEP104:
11603 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11604 break;
11605
11606 case WLAN_CIPHER_SUITE_TKIP:
11607 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11608 break;
11609
11610 case WLAN_CIPHER_SUITE_CCMP:
11611 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11612 break;
11613#ifdef FEATURE_WLAN_WAPI
11614 case WLAN_CIPHER_SUITE_SMS4:
11615 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11616 break;
11617#endif
11618
11619#ifdef FEATURE_WLAN_ESE
11620 case WLAN_CIPHER_SUITE_KRK:
11621 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11622 break;
11623#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11624 case WLAN_CIPHER_SUITE_BTK:
11625 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11626 break;
11627#endif
11628#endif
11629 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011630 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011631 return -EOPNOTSUPP;
11632 }
11633 }
11634
11635 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011636 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011637 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11638 pWextState->roamProfile.EncryptionType.numEntries = 1;
11639 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11640 encryptionType;
11641 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011642 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011643 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11644 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11645 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11646 encryptionType;
11647 }
11648
11649 return 0;
11650}
11651
11652/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011653 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11654 * @wext_state: Pointer to wext state
11655 * @gen_ie: Pointer to IE data
11656 * @len: length of IE data
11657 *
11658 * Return: 0 for success, non-zero for failure
11659 */
11660static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11661 const uint8_t *gen_ie, uint16_t len)
11662{
11663 uint16_t cur_add_ie_len =
11664 wext_state->assocAddIE.length;
11665
11666 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11667 (wext_state->assocAddIE.length + len)) {
11668 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11669 QDF_ASSERT(0);
11670 return -ENOMEM;
11671 }
11672 memcpy(wext_state->assocAddIE.addIEdata +
11673 cur_add_ie_len, gen_ie, len);
11674 wext_state->assocAddIE.length += len;
11675
11676 wext_state->roamProfile.pAddIEAssoc =
11677 wext_state->assocAddIE.addIEdata;
11678 wext_state->roamProfile.nAddIEAssocLength =
11679 wext_state->assocAddIE.length;
11680 return 0;
11681}
11682
11683/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011684 * wlan_hdd_cfg80211_set_ie() - set IEs
11685 * @pAdapter: Pointer to adapter
11686 * @ie: Pointer ot ie
11687 * @ie: IE length
11688 *
11689 * Return: 0 for success, non-zero for failure
11690 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011691static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011692 size_t ie_len)
11693{
11694 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11695 const uint8_t *genie = ie;
11696 uint16_t remLen = ie_len;
11697#ifdef FEATURE_WLAN_WAPI
11698 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
11699 u16 *tmp;
11700 uint16_t akmsuiteCount;
11701 int *akmlist;
11702#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011703 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011704
11705 /* clear previous assocAddIE */
11706 pWextState->assocAddIE.length = 0;
11707 pWextState->roamProfile.bWPSAssociation = false;
11708 pWextState->roamProfile.bOSENAssociation = false;
11709
11710 while (remLen >= 2) {
11711 uint16_t eLen = 0;
11712 uint8_t elementId;
11713 elementId = *genie++;
11714 eLen = *genie++;
11715 remLen -= 2;
11716
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011717 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011718
11719 switch (elementId) {
11720 case DOT11F_EID_WPA:
11721 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 -070011722 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011723 return -EINVAL;
11724 } else if (0 ==
11725 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
11726 uint16_t curAddIELen =
11727 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011728 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011729
11730 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11731 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011732 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011733 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011734 return -ENOMEM;
11735 }
11736 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11737 memcpy(pWextState->assocAddIE.addIEdata +
11738 curAddIELen, genie - 2, eLen + 2);
11739 pWextState->assocAddIE.length += eLen + 2;
11740
11741 pWextState->roamProfile.bWPSAssociation = true;
11742 pWextState->roamProfile.pAddIEAssoc =
11743 pWextState->assocAddIE.addIEdata;
11744 pWextState->roamProfile.nAddIEAssocLength =
11745 pWextState->assocAddIE.length;
11746 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011747 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011748 memset(pWextState->WPARSNIE, 0,
11749 MAX_WPA_RSN_IE_LEN);
11750 memcpy(pWextState->WPARSNIE, genie - 2,
11751 (eLen + 2));
11752 pWextState->roamProfile.pWPAReqIE =
11753 pWextState->WPARSNIE;
11754 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
11755 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
11756 P2P_OUI_TYPE_SIZE))) {
11757 uint16_t curAddIELen =
11758 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011759 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011760
11761 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11762 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011763 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011764 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011765 return -ENOMEM;
11766 }
11767 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11768 memcpy(pWextState->assocAddIE.addIEdata +
11769 curAddIELen, genie - 2, eLen + 2);
11770 pWextState->assocAddIE.length += eLen + 2;
11771
11772 pWextState->roamProfile.pAddIEAssoc =
11773 pWextState->assocAddIE.addIEdata;
11774 pWextState->roamProfile.nAddIEAssocLength =
11775 pWextState->assocAddIE.length;
11776 }
11777#ifdef WLAN_FEATURE_WFD
11778 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
11779 WFD_OUI_TYPE_SIZE)) &&
11780 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080011781 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011782 pAdapter->device_mode)) {
11783 uint16_t curAddIELen =
11784 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011785 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011786
11787 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11788 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011789 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011790 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011791 return -ENOMEM;
11792 }
11793 /* WFD IE is saved to Additional IE ; it should
11794 * be accumulated to handle WPS IE + P2P IE +
11795 * WFD IE */
11796 memcpy(pWextState->assocAddIE.addIEdata +
11797 curAddIELen, genie - 2, eLen + 2);
11798 pWextState->assocAddIE.length += eLen + 2;
11799
11800 pWextState->roamProfile.pAddIEAssoc =
11801 pWextState->assocAddIE.addIEdata;
11802 pWextState->roamProfile.nAddIEAssocLength =
11803 pWextState->assocAddIE.length;
11804 }
11805#endif
11806 /* Appending HS 2.0 Indication Element in Assiciation Request */
11807 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
11808 HS20_OUI_TYPE_SIZE))) {
11809 uint16_t curAddIELen =
11810 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011811 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011812
11813 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11814 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011815 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011816 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011817 return -ENOMEM;
11818 }
11819 memcpy(pWextState->assocAddIE.addIEdata +
11820 curAddIELen, genie - 2, eLen + 2);
11821 pWextState->assocAddIE.length += eLen + 2;
11822
11823 pWextState->roamProfile.pAddIEAssoc =
11824 pWextState->assocAddIE.addIEdata;
11825 pWextState->roamProfile.nAddIEAssocLength =
11826 pWextState->assocAddIE.length;
11827 }
11828 /* Appending OSEN Information Element in Assiciation Request */
11829 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
11830 OSEN_OUI_TYPE_SIZE))) {
11831 uint16_t curAddIELen =
11832 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011833 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834
11835 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11836 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011837 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011838 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011839 return -ENOMEM;
11840 }
11841 memcpy(pWextState->assocAddIE.addIEdata +
11842 curAddIELen, genie - 2, eLen + 2);
11843 pWextState->assocAddIE.length += eLen + 2;
11844
11845 pWextState->roamProfile.bOSENAssociation = true;
11846 pWextState->roamProfile.pAddIEAssoc =
11847 pWextState->assocAddIE.addIEdata;
11848 pWextState->roamProfile.nAddIEAssocLength =
11849 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011850 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
11851 MBO_OUI_TYPE_SIZE))){
11852 hdd_info("Set MBO IE(len %d)", eLen + 2);
11853 status = wlan_hdd_add_assoc_ie(pWextState,
11854 genie - 2, eLen + 2);
11855 if (status)
11856 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011857 } else {
11858 uint16_t add_ie_len =
11859 pWextState->assocAddIE.length;
11860
11861 hdd_info("Set OSEN IE(len %d)", eLen + 2);
11862
11863 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11864 (pWextState->assocAddIE.length + eLen)) {
11865 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011866 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011867 return -ENOMEM;
11868 }
11869
11870 memcpy(pWextState->assocAddIE.addIEdata +
11871 add_ie_len, genie - 2, eLen + 2);
11872 pWextState->assocAddIE.length += eLen + 2;
11873
11874 pWextState->roamProfile.pAddIEAssoc =
11875 pWextState->assocAddIE.addIEdata;
11876 pWextState->roamProfile.nAddIEAssocLength =
11877 pWextState->assocAddIE.length;
11878 }
11879 break;
11880 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011881 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011882 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
11883 memcpy(pWextState->WPARSNIE, genie - 2,
11884 (eLen + 2));
11885 pWextState->roamProfile.pRSNReqIE =
11886 pWextState->WPARSNIE;
11887 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
11888 break;
11889 /*
11890 * Appending Extended Capabilities with Interworking bit set
11891 * in Assoc Req.
11892 *
11893 * In assoc req this EXT Cap will only be taken into account if
11894 * interworkingService bit is set to 1. Currently
11895 * driver is only interested in interworkingService capability
11896 * from supplicant. If in future any other EXT Cap info is
11897 * required from supplicat, it needs to be handled while
11898 * sending Assoc Req in LIM.
11899 */
11900 case DOT11F_EID_EXTCAP:
11901 {
11902 uint16_t curAddIELen =
11903 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011904 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011905
11906 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11907 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011908 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011909 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011910 return -ENOMEM;
11911 }
11912 memcpy(pWextState->assocAddIE.addIEdata +
11913 curAddIELen, genie - 2, eLen + 2);
11914 pWextState->assocAddIE.length += eLen + 2;
11915
11916 pWextState->roamProfile.pAddIEAssoc =
11917 pWextState->assocAddIE.addIEdata;
11918 pWextState->roamProfile.nAddIEAssocLength =
11919 pWextState->assocAddIE.length;
11920 break;
11921 }
11922#ifdef FEATURE_WLAN_WAPI
11923 case WLAN_EID_WAPI:
11924 /* Setting WAPI Mode to ON=1 */
11925 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011926 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011927 tmp = (u16 *) ie;
11928 tmp = tmp + 2; /* Skip element Id and Len, Version */
11929 akmsuiteCount = WPA_GET_LE16(tmp);
11930 tmp = tmp + 1;
11931 akmlist = (int *)(tmp);
11932 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
11933 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
11934 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011935 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011936 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011937 return -EINVAL;
11938 }
11939
11940 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011941 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011942 pAdapter->wapi_info.wapiAuthMode =
11943 WAPI_AUTH_MODE_PSK;
11944 }
11945 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011946 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011947 pAdapter->wapi_info.wapiAuthMode =
11948 WAPI_AUTH_MODE_CERT;
11949 }
11950 break;
11951#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011952 case DOT11F_EID_SUPPOPERATINGCLASSES:
11953 {
11954 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
11955 status = wlan_hdd_add_assoc_ie(pWextState,
11956 genie - 2, eLen + 2);
11957 if (status)
11958 return status;
11959 break;
11960 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011961 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011962 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011963 /* when Unknown IE is received we should break and continue
11964 * to the next IE in the buffer instead we were returning
11965 * so changing this to break */
11966 break;
11967 }
11968 genie += eLen;
11969 remLen -= eLen;
11970 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011971 return 0;
11972}
11973
11974/**
11975 * hdd_is_wpaie_present() - check for WPA ie
11976 * @ie: Pointer to ie
11977 * @ie_len: Ie length
11978 *
11979 * Parse the received IE to find the WPA IE
11980 *
11981 * Return: true if wpa ie is found else false
11982 */
11983static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
11984{
11985 uint8_t eLen = 0;
11986 uint16_t remLen = ie_len;
11987 uint8_t elementId = 0;
11988
11989 while (remLen >= 2) {
11990 elementId = *ie++;
11991 eLen = *ie++;
11992 remLen -= 2;
11993 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011994 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011995 return false;
11996 }
11997 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
11998 /* OUI - 0x00 0X50 0XF2
11999 * WPA Information Element - 0x01
12000 * WPA version - 0x01
12001 */
12002 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12003 return true;
12004 }
12005 ie += eLen;
12006 remLen -= eLen;
12007 }
12008 return false;
12009}
12010
12011/**
12012 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12013 * @pAdapter: Pointer to adapter
12014 * @req: Pointer to security parameters
12015 *
12016 * Return: 0 for success, non-zero for failure
12017 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012018static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12019 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012020{
12021 int status = 0;
12022 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12023 ENTER();
12024
12025 /*set wpa version */
12026 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12027
12028 if (req->crypto.wpa_versions) {
12029 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12030 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12031 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12032 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12033 }
12034 }
12035
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012036 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012037
12038 /*set authentication type */
12039 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12040
12041 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012042 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012043 return status;
12044 }
12045
12046 /*set key mgmt type */
12047 if (req->crypto.n_akm_suites) {
12048 status =
12049 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12050 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012051 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012052 return status;
12053 }
12054 }
12055
12056 /*set pairwise cipher type */
12057 if (req->crypto.n_ciphers_pairwise) {
12058 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12059 req->crypto.
12060 ciphers_pairwise[0],
12061 true);
12062 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012063 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012064 return status;
12065 }
12066 } else {
12067 /*Reset previous cipher suite to none */
12068 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12069 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012070 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012071 return status;
12072 }
12073 }
12074
12075 /*set group cipher type */
12076 status =
12077 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12078 false);
12079
12080 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012081 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012082 return status;
12083 }
12084#ifdef WLAN_FEATURE_11W
12085 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12086#endif
12087
12088 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12089 if (req->ie_len) {
12090 status =
12091 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12092 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012093 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012094 return status;
12095 }
12096 }
12097
12098 /*incase of WEP set default key information */
12099 if (req->key && req->key_len) {
12100 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12101 || (WLAN_CIPHER_SUITE_WEP104 ==
12102 req->crypto.ciphers_pairwise[0])
12103 ) {
12104 if (IW_AUTH_KEY_MGMT_802_1X
12105 ==
12106 (pWextState->
12107 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012108 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012109 return -EOPNOTSUPP;
12110 } else {
12111 u8 key_len = req->key_len;
12112 u8 key_idx = req->key_idx;
12113
12114 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12115 key_len)
12116 && (CSR_MAX_NUM_KEY > key_idx)
12117 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012118 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012119 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012120 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012121 Keys.
12122 KeyMaterial[key_idx][0],
12123 req->key, key_len);
12124 pWextState->roamProfile.Keys.
12125 KeyLength[key_idx] = (u8) key_len;
12126 pWextState->roamProfile.Keys.
12127 defaultIndex = (u8) key_idx;
12128 }
12129 }
12130 }
12131 }
12132
12133 return status;
12134}
12135
12136/**
12137 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12138 * @pAdapter: Pointer to adapter
12139 *
12140 * This function is used to disconnect from previous connection
12141 *
12142 * Return: 0 for success, non-zero for failure
12143 */
12144static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12145{
12146 unsigned long rc;
12147 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012148 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012149
12150 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12151
Jeff Johnson9edf9572016-10-03 15:24:49 -070012152 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012153 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12154 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12155 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012156 hdd_conn_set_connection_state(pAdapter,
12157 eConnectionState_Disconnecting);
12158 /* Issue disconnect to CSR */
12159 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012160
12161 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12162 pAdapter->sessionId,
12163 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12164 /*
12165 * Wait here instead of returning directly, this will block the
12166 * next connect command and allow processing of the scan for
12167 * ssid and the previous connect command in CSR. Else we might
12168 * hit some race conditions leading to SME and HDD out of sync.
12169 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012170 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012171 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12172 } else if (0 != status) {
12173 hdd_err("csrRoamDisconnect failure, returned %d",
12174 (int)status);
12175 pHddStaCtx->staDebugState = status;
12176 result = -EINVAL;
12177 goto disconnected;
12178 }
12179
12180 rc = wait_for_completion_timeout(
12181 &pAdapter->disconnect_comp_var,
12182 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012183 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012184 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12185 pAdapter->sessionId, pHddStaCtx->staDebugState);
12186 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012187 }
12188 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012189 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012190 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012191 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012192 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012193 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012194 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012195 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012196 }
12197 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012198disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012199 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12200 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012201}
12202
12203/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012204 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12205 * @adapter: Pointer to the HDD adapter
12206 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012207 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012208 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012209 * This function will start reassociation if prev_bssid is set and bssid/
12210 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012211 *
Naveen Rawat07332902016-07-27 09:13:17 -070012212 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012213 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012214#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12215 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012216static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12217 struct cfg80211_connect_params *req,
12218 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012219{
Naveen Rawat07332902016-07-27 09:13:17 -070012220 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012221 const uint8_t *bssid = NULL;
12222 uint16_t channel = 0;
12223
12224 if (req->bssid)
12225 bssid = req->bssid;
12226 else if (req->bssid_hint)
12227 bssid = req->bssid_hint;
12228
12229 if (req->channel)
12230 channel = req->channel->hw_value;
12231 else if (req->channel_hint)
12232 channel = req->channel_hint->hw_value;
12233
12234 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012235 reassoc = true;
12236 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012237 channel, MAC_ADDR_ARRAY(bssid));
12238 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012239 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012240 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012241 }
Naveen Rawat07332902016-07-27 09:13:17 -070012242 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012243}
12244#else
Naveen Rawat07332902016-07-27 09:13:17 -070012245static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12246 struct cfg80211_connect_params *req,
12247 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012248{
Naveen Rawat07332902016-07-27 09:13:17 -070012249 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012250}
12251#endif
12252
12253/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012254 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12255 * @wiphy: Pointer to wiphy
12256 * @dev: Pointer to network device
12257 * @req: Pointer to cfg80211 connect request
12258 *
12259 * This function is used to start the association process
12260 *
12261 * Return: 0 for success, non-zero for failure
12262 */
12263static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12264 struct net_device *ndev,
12265 struct cfg80211_connect_params *req)
12266{
12267 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012268 u16 channel;
12269#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12270 const u8 *bssid_hint = req->bssid_hint;
12271#else
12272 const u8 *bssid_hint = NULL;
12273#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012274 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12275 hdd_context_t *pHddCtx;
12276
12277 ENTER();
12278
Anurag Chouhan6d760662016-02-20 16:05:43 +053012279 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012280 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012281 return -EINVAL;
12282 }
12283
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012284 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012285 TRACE_CODE_HDD_CFG80211_CONNECT,
12286 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012287 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012288 hdd_device_mode_to_string(pAdapter->device_mode),
12289 pAdapter->device_mode);
12290
Krunal Sonib4326f22016-03-10 13:05:51 -080012291 if (pAdapter->device_mode != QDF_STA_MODE &&
12292 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012293 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012294 hdd_device_mode_to_string(pAdapter->device_mode),
12295 pAdapter->device_mode);
12296 return -EINVAL;
12297 }
12298
12299 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12300 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012301 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012302 return -EINVAL;
12303 }
12304
12305 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012306 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012307 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012308
Naveen Rawat07332902016-07-27 09:13:17 -070012309 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012310 return status;
12311
Agrawal Ashishf156e942016-08-04 14:54:47 +053012312 wlan_hdd_disable_roaming(pAdapter);
12313
12314 /* Try disconnecting if already in connected state */
12315 status = wlan_hdd_try_disconnect(pAdapter);
12316 if (0 > status) {
12317 hdd_err("Failed to disconnect the existing connection");
12318 return -EALREADY;
12319 }
12320
12321 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012322 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012323 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012324 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012325 pAdapter->device_mode),
12326 req->channel->hw_value, HW_MODE_20_MHZ)) {
12327 hdd_err("This concurrency combination is not allowed");
12328 return -ECONNREFUSED;
12329 }
12330 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012331 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012332 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012333 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12334 hdd_err("This concurrency combination is not allowed");
12335 return -ECONNREFUSED;
12336 }
12337 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012338
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012339 /*initialise security parameters */
12340 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12341
12342 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012343 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012344 return status;
12345 }
12346
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012347 if (req->channel)
12348 channel = req->channel->hw_value;
12349 else
12350 channel = 0;
12351 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12352 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012353 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012354 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012355 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012356 return status;
12357 }
12358 EXIT();
12359 return status;
12360}
12361
12362/**
12363 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12364 * @wiphy: Pointer to wiphy
12365 * @dev: Pointer to network device
12366 * @req: Pointer to cfg80211 connect request
12367 *
12368 * Return: 0 for success, non-zero for failure
12369 */
12370static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12371 struct net_device *ndev,
12372 struct cfg80211_connect_params *req)
12373{
12374 int ret;
12375 cds_ssr_protect(__func__);
12376 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12377 cds_ssr_unprotect(__func__);
12378
12379 return ret;
12380}
12381
12382/**
12383 * wlan_hdd_disconnect() - hdd disconnect api
12384 * @pAdapter: Pointer to adapter
12385 * @reason: Disconnect reason code
12386 *
12387 * This function is used to issue a disconnect request to SME
12388 *
12389 * Return: 0 for success, non-zero for failure
12390 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012391static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012392{
12393 int status, result = 0;
12394 unsigned long rc;
12395 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12396 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12397
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012398 ENTER();
12399
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012400 status = wlan_hdd_validate_context(pHddCtx);
12401
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012402 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012403 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012404
12405 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012406 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012407 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12408 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012409 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012410 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12411 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12412
12413 /*issue disconnect */
12414
12415 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12416 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012417 /*
12418 * Wait here instead of returning directly, this will block the next
12419 * connect command and allow processing of the scan for ssid and
12420 * the previous connect command in CSR. Else we might hit some
12421 * race conditions leading to SME and HDD out of sync.
12422 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012423 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012424 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012425 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012426 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012427 (int)status);
12428 pHddStaCtx->staDebugState = status;
12429 result = -EINVAL;
12430 goto disconnected;
12431 }
12432 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12433 msecs_to_jiffies
12434 (WLAN_WAIT_TIME_DISCONNECT));
12435
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012436 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012437 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012438 result = -ETIMEDOUT;
12439 }
12440disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012441 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12442#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12443 /* Sending disconnect event to userspace for kernel version < 3.11
12444 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12445 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012446 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012447 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12448 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012449#endif
12450
12451 return result;
12452}
12453
12454/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012455 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12456 * @reason: ieee80211 reason code.
12457 *
12458 * This utility function helps log string conversion of reason code.
12459 *
12460 * Return: string conversion of reason code, if match found;
12461 * "Unknown" otherwise.
12462 */
12463static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12464{
12465 switch (reason) {
12466 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12467 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12468 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12469 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12470 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12471 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12472 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12473 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12474 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12475 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12476 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12477 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12478 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12479 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12480 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12481 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12482 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12483 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12484 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12485 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12486 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12487 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12488 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12489 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12490 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12491 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12492 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12493 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12494 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12495 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12496 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12497 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12498 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12499 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12500 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12501 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12502 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12503 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12504 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12505 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12506 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12507 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12508 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12509 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12510 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12511 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12512 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12513 default:
12514 return "Unknown";
12515 }
12516}
12517
12518/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012519 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12520 * @wiphy: Pointer to wiphy
12521 * @dev: Pointer to network device
12522 * @reason: Disconnect reason code
12523 *
12524 * This function is used to issue a disconnect request to SME
12525 *
12526 * Return: 0 for success, non-zero for failure
12527 */
12528static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12529 struct net_device *dev, u16 reason)
12530{
12531 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12532 int status;
12533 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12534 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12535#ifdef FEATURE_WLAN_TDLS
12536 uint8_t staIdx;
12537#endif
12538
12539 ENTER();
12540
Anurag Chouhan6d760662016-02-20 16:05:43 +053012541 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012542 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012543 return -EINVAL;
12544 }
12545
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012546 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012547 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12548 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012549 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012550 hdd_device_mode_to_string(pAdapter->device_mode),
12551 pAdapter->device_mode, reason);
12552
12553 status = wlan_hdd_validate_context(pHddCtx);
12554
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012555 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012556 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012557
12558 /* Issue disconnect request to SME, if station is in connected state */
12559 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12560 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12561 eCsrRoamDisconnectReason reasonCode =
12562 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12563 hdd_scaninfo_t *pScanInfo;
12564
12565 switch (reason) {
12566 case WLAN_REASON_MIC_FAILURE:
12567 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12568 break;
12569
12570 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12571 case WLAN_REASON_DISASSOC_AP_BUSY:
12572 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12573 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12574 break;
12575
12576 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12577 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12578 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12579 break;
12580
12581 case WLAN_REASON_DEAUTH_LEAVING:
12582 reasonCode =
12583 pHddCtx->config->
12584 gEnableDeauthToDisassocMap ?
12585 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12586 eCSR_DISCONNECT_REASON_DEAUTH;
12587 break;
12588 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12589 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12590 break;
12591 default:
12592 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12593 break;
12594 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012595 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012596 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012597 pScanInfo = &pAdapter->scan_info;
12598 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012599 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012600 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12601 eCSR_SCAN_ABORT_DEFAULT);
12602 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012603 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012604#ifdef FEATURE_WLAN_TDLS
12605 /* First clean up the tdls peers if any */
12606 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12607 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12608 pAdapter->sessionId)
12609 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12610 uint8_t *mac;
12611 mac =
12612 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012613 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12614 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012615 pHddCtx->tdlsConnInfo[staIdx].staId,
12616 pAdapter->sessionId,
12617 MAC_ADDR_ARRAY(mac));
12618 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12619 (pAdapter),
12620 pAdapter->sessionId, mac);
12621 }
12622 }
12623#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012624 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012625 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012626 hdd_info("Disconnect request from user space with reason: %s",
12627 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012628 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12629 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012630 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012631 return -EINVAL;
12632 }
12633 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012634 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012635 pHddStaCtx->conn_info.connState);
12636 }
12637
12638 return status;
12639}
12640
12641/**
12642 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12643 * @wiphy: Pointer to wiphy
12644 * @dev: Pointer to network device
12645 * @reason: Disconnect reason code
12646 *
12647 * Return: 0 for success, non-zero for failure
12648 */
12649static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12650 struct net_device *dev, u16 reason)
12651{
12652 int ret;
12653 cds_ssr_protect(__func__);
12654 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12655 cds_ssr_unprotect(__func__);
12656
12657 return ret;
12658}
12659
12660/**
12661 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12662 * @pAdapter: Pointer to adapter
12663 * @param: Pointer to IBSS parameters
12664 *
12665 * This function is used to initialize the security settings in IBSS mode
12666 *
12667 * Return: 0 for success, non-zero for failure
12668 */
12669static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12670 struct cfg80211_ibss_params
12671 *params)
12672{
12673 int status = 0;
12674 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12675 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12676 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12677
12678 ENTER();
12679
12680 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012681 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012682 pHddStaCtx->ibss_enc_key_installed = 0;
12683
12684 if (params->ie_len && (NULL != params->ie)) {
12685 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12686 params->ie_len, WLAN_EID_RSN)) {
12687 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12688 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12689 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
12690 tDot11fIEWPA dot11WPAIE;
12691 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12692 u8 *ie;
12693
12694 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12695 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12696 params->ie_len,
12697 DOT11F_EID_WPA);
12698 if (NULL != ie) {
12699 pWextState->wpaVersion =
12700 IW_AUTH_WPA_VERSION_WPA;
12701 /* Unpack the WPA IE */
12702 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
12703 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
12704 &ie[2 + 4],
12705 ie[1] - 4, &dot11WPAIE);
12706 /*Extract the multicast cipher, the encType for unicast
12707 cipher for wpa-none is none */
12708 encryptionType =
12709 hdd_translate_wpa_to_csr_encryption_type
12710 (dot11WPAIE.multicast_cipher);
12711 }
12712 }
12713
12714 status =
12715 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
12716 params->ie_len);
12717
12718 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012719 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012720 return status;
12721 }
12722 }
12723
12724 pWextState->roamProfile.AuthType.authType[0] =
12725 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12726
12727 if (params->privacy) {
12728 /* Security enabled IBSS, At this time there is no information
12729 * available about the security paramters, so initialise the
12730 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
12731 * The correct security parameters will be updated later in
12732 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
12733 * set inorder enable privacy bit in beacons
12734 */
12735
12736 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12737 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012738 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012739 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12740 pWextState->roamProfile.EncryptionType.numEntries = 1;
12741 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12742 encryptionType;
12743 return status;
12744}
12745
12746/**
12747 * __wlan_hdd_cfg80211_join_ibss() - join ibss
12748 * @wiphy: Pointer to wiphy
12749 * @dev: Pointer to network device
12750 * @param: Pointer to IBSS join parameters
12751 *
12752 * This function is used to create/join an IBSS network
12753 *
12754 * Return: 0 for success, non-zero for failure
12755 */
12756static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12757 struct net_device *dev,
12758 struct cfg80211_ibss_params *params)
12759{
12760 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12761 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12762 tCsrRoamProfile *pRoamProfile;
12763 int status;
12764 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12765 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053012766 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012767 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012768
12769 ENTER();
12770
Anurag Chouhan6d760662016-02-20 16:05:43 +053012771 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012772 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012773 return -EINVAL;
12774 }
12775
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012776 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012777 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
12778 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012779 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012780 hdd_device_mode_to_string(pAdapter->device_mode),
12781 pAdapter->device_mode);
12782
12783 status = wlan_hdd_validate_context(pHddCtx);
12784
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012785 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012786 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012787
12788 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053012789 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012790 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12791 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
12792 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12793 int indx;
12794
12795 /* Get channel number */
12796 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012797 params->
12798 chandef.
12799 chan->
12800 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012801
12802 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12803 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012804 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012805 return -EOPNOTSUPP;
12806 }
12807
12808 for (indx = 0; indx < numChans; indx++) {
12809 if (channelNum == validChan[indx]) {
12810 break;
12811 }
12812 }
12813 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012814 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012815 return -EINVAL;
12816 }
12817 }
12818
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012819 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012820 HW_MODE_20_MHZ)) {
12821 hdd_err("This concurrency combination is not allowed");
12822 return -ECONNREFUSED;
12823 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012824
Krunal Soni3091bcc2016-06-23 12:28:21 -070012825 status = qdf_reset_connection_update();
12826 if (!QDF_IS_STATUS_SUCCESS(status))
12827 hdd_err("ERR: clear event failed");
12828
12829 status = cds_current_connections_update(pAdapter->sessionId,
12830 channelNum,
12831 SIR_UPDATE_REASON_JOIN_IBSS);
12832 if (QDF_STATUS_E_FAILURE == status) {
12833 hdd_err("ERROR: connections update failed!!");
12834 return -EINVAL;
12835 }
12836
12837 if (QDF_STATUS_SUCCESS == status) {
12838 status = qdf_wait_for_connection_update();
12839 if (!QDF_IS_STATUS_SUCCESS(status)) {
12840 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012841 return -EINVAL;
12842 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012843 }
12844
12845 /*Try disconnecting if already in connected state */
12846 status = wlan_hdd_try_disconnect(pAdapter);
12847 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012848 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012849 return -EALREADY;
12850 }
12851
12852 pRoamProfile = &pWextState->roamProfile;
12853
12854 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012855 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012856 return -EINVAL;
12857 }
12858
12859 /* enable selected protection checks in IBSS mode */
12860 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
12861
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012862 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012863 WNI_CFG_IBSS_ATIM_WIN_SIZE,
12864 pHddCtx->config->
12865 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012866 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012867 }
12868
12869 /* BSSID is provided by upper layers hence no need to AUTO generate */
12870 if (NULL != params->bssid) {
12871 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012872 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012873 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012874 return -EIO;
12875 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012876 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012877 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
12878 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012879 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012880 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012881 return -EIO;
12882 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053012883 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012884 }
12885 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
12886 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
12887 pRoamProfile->beaconInterval = params->beacon_interval;
12888 else {
12889 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012890 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012891 params->beacon_interval, pRoamProfile->beaconInterval);
12892 }
12893
12894 /* Set Channel */
12895 if (channelNum) {
12896 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012897 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012898 pRoamProfile->ChannelInfo.numOfChannels = 1;
12899 pHddStaCtx->conn_info.operationChannel = channelNum;
12900 pRoamProfile->ChannelInfo.ChannelList =
12901 &pHddStaCtx->conn_info.operationChannel;
12902 }
12903
12904 /* Initialize security parameters */
12905 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
12906 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012907 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012908 return status;
12909 }
12910
12911 /* Issue connect start */
12912 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
12913 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012914 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012915 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012916 operationChannel,
12917 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012918
12919 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012920 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012921 return status;
12922 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012923 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012924 return 0;
12925}
12926
12927/**
12928 * wlan_hdd_cfg80211_join_ibss() - join ibss
12929 * @wiphy: Pointer to wiphy
12930 * @dev: Pointer to network device
12931 * @param: Pointer to IBSS join parameters
12932 *
12933 * This function is used to create/join an IBSS network
12934 *
12935 * Return: 0 for success, non-zero for failure
12936 */
12937static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12938 struct net_device *dev,
12939 struct cfg80211_ibss_params *params)
12940{
12941 int ret = 0;
12942
12943 cds_ssr_protect(__func__);
12944 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
12945 cds_ssr_unprotect(__func__);
12946
12947 return ret;
12948}
12949
12950/**
12951 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
12952 * @wiphy: Pointer to wiphy
12953 * @dev: Pointer to network device
12954 *
12955 * This function is used to leave an IBSS network
12956 *
12957 * Return: 0 for success, non-zero for failure
12958 */
12959static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
12960 struct net_device *dev)
12961{
12962 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12963 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12964 tCsrRoamProfile *pRoamProfile;
12965 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12966 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012967 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053012968 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012969 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012970
12971 ENTER();
12972
Anurag Chouhan6d760662016-02-20 16:05:43 +053012973 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012974 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012975 return -EINVAL;
12976 }
12977
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012978 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012979 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
12980 pAdapter->sessionId,
12981 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
12982 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012983 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012984 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012985
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012986 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012987 hdd_device_mode_to_string(pAdapter->device_mode),
12988 pAdapter->device_mode);
12989 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012990 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012991 return -EIO;
12992 }
12993
12994 pRoamProfile = &pWextState->roamProfile;
12995
12996 /* Issue disconnect only if interface type is set to IBSS */
12997 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012998 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012999 return -EINVAL;
13000 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013001 /* Clearing add IE of beacon */
13002 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13003 sizeof(tSirMacAddr));
13004 updateIE.smeSessionId = pAdapter->sessionId;
13005 updateIE.ieBufferlength = 0;
13006 updateIE.pAdditionIEBuffer = NULL;
13007 updateIE.append = true;
13008 updateIE.notify = true;
13009 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13010 &updateIE,
13011 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013012 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013013 }
13014
13015 /* Reset WNI_CFG_PROBE_RSP Flags */
13016 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013017
13018 /* Issue Disconnect request */
13019 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13020 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13021 pAdapter->sessionId,
13022 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013023 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013024 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013025 hal_status);
13026 return -EAGAIN;
13027 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013028
13029 /* wait for mc thread to cleanup and then return to upper stack
13030 * so by the time upper layer calls the change interface, we are
13031 * all set to proceed further
13032 */
13033 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13034 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13035 if (!rc) {
13036 hdd_err("Failed to disconnect, timed out");
13037 return -ETIMEDOUT;
13038 }
13039
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013040 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013041 return 0;
13042}
13043
13044/**
13045 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13046 * @wiphy: Pointer to wiphy
13047 * @dev: Pointer to network device
13048 *
13049 * This function is used to leave an IBSS network
13050 *
13051 * Return: 0 for success, non-zero for failure
13052 */
13053static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13054 struct net_device *dev)
13055{
13056 int ret = 0;
13057
13058 cds_ssr_protect(__func__);
13059 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13060 cds_ssr_unprotect(__func__);
13061
13062 return ret;
13063}
13064
13065/**
13066 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13067 * @wiphy: Pointer to wiphy
13068 * @changed: Parameters changed
13069 *
13070 * This function is used to set the phy parameters. RTS Threshold/FRAG
13071 * Threshold/Retry Count etc.
13072 *
13073 * Return: 0 for success, non-zero for failure
13074 */
13075static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13076 u32 changed)
13077{
13078 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13079 tHalHandle hHal = pHddCtx->hHal;
13080 int status;
13081
13082 ENTER();
13083
Anurag Chouhan6d760662016-02-20 16:05:43 +053013084 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013085 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013086 return -EINVAL;
13087 }
13088
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013089 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013090 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13091 NO_SESSION, wiphy->rts_threshold));
13092 status = wlan_hdd_validate_context(pHddCtx);
13093
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013094 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013095 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013096
13097 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13098 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13099 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13100
13101 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13102 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013103 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013104 rts_threshold);
13105 return -EINVAL;
13106 }
13107
13108 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13109 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013110 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013111 rts_threshold);
13112 return -EIO;
13113 }
13114
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013115 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013116 }
13117
13118 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13119 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13120 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13121 wiphy->frag_threshold;
13122
13123 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13124 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013125 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013126 frag_threshold);
13127 return -EINVAL;
13128 }
13129
13130 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13131 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013132 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013133 frag_threshold);
13134 return -EIO;
13135 }
13136
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013137 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013138 }
13139
13140 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13141 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13142 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13143 wiphy->retry_short : wiphy->retry_long;
13144
13145 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13146 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013147 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013148 return -EINVAL;
13149 }
13150
13151 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13152 if (0 != sme_cfg_set_int(hHal,
13153 WNI_CFG_LONG_RETRY_LIMIT,
13154 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013155 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013156 retry_value);
13157 return -EIO;
13158 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013159 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013160 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13161 if (0 != sme_cfg_set_int(hHal,
13162 WNI_CFG_SHORT_RETRY_LIMIT,
13163 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013164 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013165 retry_value);
13166 return -EIO;
13167 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013168 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013169 }
13170 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013171 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013172 return 0;
13173}
13174
13175/**
13176 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13177 * @wiphy: Pointer to wiphy
13178 * @changed: Parameters changed
13179 *
13180 * Return: 0 for success, non-zero for failure
13181 */
13182static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13183{
13184 int ret;
13185
13186 cds_ssr_protect(__func__);
13187 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13188 cds_ssr_unprotect(__func__);
13189
13190 return ret;
13191}
13192
13193/**
13194 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13195 * key
13196 * @wiphy: Pointer to wiphy
13197 * @dev: Pointer to network device
13198 * @key_index: Key index
13199 *
13200 * Return: 0
13201 */
13202static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13203 struct net_device *netdev,
13204 u8 key_index)
13205{
13206 ENTER();
13207 return 0;
13208}
13209
13210/**
13211 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13212 * wlan_hdd_set_default_mgmt_key
13213 * @wiphy: pointer to wiphy
13214 * @netdev: pointer to net_device structure
13215 * @key_index: key index
13216 *
13217 * Return: 0 on success, error number on failure
13218 */
13219static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13220 struct net_device *netdev,
13221 u8 key_index)
13222{
13223 int ret;
13224
13225 cds_ssr_protect(__func__);
13226 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13227 cds_ssr_unprotect(__func__);
13228
13229 return ret;
13230}
13231
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013232/**
13233 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13234 * @wiphy: Pointer to wiphy
13235 * @dev: Pointer to network device
13236 * @params: Pointer to tx queue parameters
13237 *
13238 * Return: 0
13239 */
13240static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13241 struct net_device *dev,
13242 struct ieee80211_txq_params *params)
13243{
13244 ENTER();
13245 return 0;
13246}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013247
13248/**
13249 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13250 * @wiphy: pointer to wiphy
13251 * @netdev: pointer to net_device structure
13252 * @params: pointer to ieee80211_txq_params
13253 *
13254 * Return: 0 on success, error number on failure
13255 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013256static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13257 struct net_device *dev,
13258 struct ieee80211_txq_params *params)
13259{
13260 int ret;
13261
13262 cds_ssr_protect(__func__);
13263 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13264 cds_ssr_unprotect(__func__);
13265
13266 return ret;
13267}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013268
13269/**
13270 * __wlan_hdd_cfg80211_del_station() - delete station v2
13271 * @wiphy: Pointer to wiphy
13272 * @param: Pointer to delete station parameter
13273 *
13274 * Return: 0 for success, non-zero for failure
13275 */
13276static
13277int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13278 struct net_device *dev,
13279 struct tagCsrDelStaParams *pDelStaParams)
13280{
13281 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13282 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013283 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013284 hdd_hostapd_state_t *hapd_state;
13285 int status;
13286 uint8_t staId;
13287 uint8_t *mac;
13288
13289 ENTER();
13290
Anurag Chouhan6d760662016-02-20 16:05:43 +053013291 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013292 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013293 return -EINVAL;
13294 }
13295
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013296 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013297 TRACE_CODE_HDD_CFG80211_DEL_STA,
13298 pAdapter->sessionId, pAdapter->device_mode));
13299
13300 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13301 status = wlan_hdd_validate_context(pHddCtx);
13302
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013303 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013304 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013305
13306 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13307
Krunal Sonib4326f22016-03-10 13:05:51 -080013308 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13309 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013310
13311 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13312 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013313 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013314 return 0;
13315 }
13316
Anurag Chouhanc5548422016-02-24 18:33:27 +053013317 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013318 uint16_t i;
13319 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13320 if ((pAdapter->aStaInfo[i].isUsed) &&
13321 (!pAdapter->aStaInfo[i].
13322 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013323 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013324 mac,
13325 pAdapter->aStaInfo[i].
13326 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013327 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013328 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13329 hdd_ipa_wlan_evt(pAdapter,
13330 pAdapter->
13331 aStaInfo[i].
13332 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013333 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013334 mac);
13335 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013336 hdd_notice("Delete STA with MAC::"
13337 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013338 MAC_ADDR_ARRAY(mac));
13339
13340 if (pHddCtx->dev_dfs_cac_status ==
13341 DFS_CAC_IN_PROGRESS)
13342 goto fn_end;
13343
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013344 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013345 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013346 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013347 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013348 hdd_softap_sta_deauth(pAdapter,
13349 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013350 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013351 pAdapter->aStaInfo[i].
13352 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013353 qdf_status =
13354 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(
13358 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013359 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013360 }
13361 }
13362 }
13363 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013364 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013365 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013366 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013367 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013368 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013369 hdd_notice("Skip DEL STA as this is not used::"
13370 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013371 MAC_ADDR_ARRAY(mac));
13372 return -ENOENT;
13373 }
13374
13375 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13376 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013377 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013378 }
13379
13380 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13381 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013382 hdd_notice("Skip DEL STA as deauth is in progress::"
13383 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013384 MAC_ADDR_ARRAY(mac));
13385 return -ENOENT;
13386 }
13387
13388 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13389
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013390 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013391 MAC_ADDR_ARRAY(mac));
13392
13393 /* Case: SAP in ACS selected DFS ch and client connected
13394 * Now Radar detected. Then if random channel is another
13395 * DFS ch then new CAC is initiated and no TX allowed.
13396 * So do not send any mgmt frames as it will timeout
13397 * during CAC.
13398 */
13399
13400 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13401 goto fn_end;
13402
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013403 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013404 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13405 (pAdapter), pAdapter->sessionId,
13406 (uint8_t *)&pDelStaParams->peerMacAddr,
13407 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013408 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013409 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013410 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013411 pAdapter->aStaInfo[staId].isDeauthInProgress =
13412 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013413 hdd_notice("STA removal failed for ::"
13414 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013415 MAC_ADDR_ARRAY(mac));
13416 return -ENOENT;
13417 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013418 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013419 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013420 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013421 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013422 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013423 }
13424 }
13425 }
13426
13427fn_end:
13428 EXIT();
13429 return 0;
13430}
13431
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013432#if defined(USE_CFG80211_DEL_STA_V2)
13433/**
13434 * wlan_hdd_del_station() - delete station wrapper
13435 * @adapter: pointer to the hdd adapter
13436 *
13437 * Return: None
13438 */
13439void wlan_hdd_del_station(hdd_adapter_t *adapter)
13440{
13441 struct station_del_parameters del_sta;
13442 del_sta.mac = NULL;
13443 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13444 del_sta.reason_code = eCsrForcedDeauthSta;
13445
13446 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13447 &del_sta);
13448}
13449#else
13450void wlan_hdd_del_station(hdd_adapter_t *adapter)
13451{
13452 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13453}
13454#endif
13455
13456#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013457/**
13458 * wlan_hdd_cfg80211_del_station() - delete station v2
13459 * @wiphy: Pointer to wiphy
13460 * @param: Pointer to delete station parameter
13461 *
13462 * Return: 0 for success, non-zero for failure
13463 */
13464int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13465 struct net_device *dev,
13466 struct station_del_parameters *param)
13467#else
13468/**
13469 * wlan_hdd_cfg80211_del_station() - delete station
13470 * @wiphy: Pointer to wiphy
13471 * @mac: Pointer to station mac address
13472 *
13473 * Return: 0 for success, non-zero for failure
13474 */
13475#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13476int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13477 struct net_device *dev,
13478 const uint8_t *mac)
13479#else
13480int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13481 struct net_device *dev,
13482 uint8_t *mac)
13483#endif
13484#endif
13485{
13486 int ret;
13487 struct tagCsrDelStaParams delStaParams;
13488
13489 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013490#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013491 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013492 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013493 return -EINVAL;
13494 }
13495 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13496 param->subtype, &delStaParams);
13497#else
13498 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13499 (SIR_MAC_MGMT_DEAUTH >> 4),
13500 &delStaParams);
13501#endif
13502 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13503 cds_ssr_unprotect(__func__);
13504
13505 return ret;
13506}
13507
13508/**
13509 * __wlan_hdd_cfg80211_add_station() - add station
13510 * @wiphy: Pointer to wiphy
13511 * @mac: Pointer to station mac address
13512 * @pmksa: Pointer to add station parameter
13513 *
13514 * Return: 0 for success, non-zero for failure
13515 */
13516static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13517 struct net_device *dev,
13518 const uint8_t *mac,
13519 struct station_parameters *params)
13520{
13521 int status = -EPERM;
13522#ifdef FEATURE_WLAN_TDLS
13523 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13524 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13525 u32 mask, set;
13526
13527 ENTER();
13528
Anurag Chouhan6d760662016-02-20 16:05:43 +053013529 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013530 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013531 return -EINVAL;
13532 }
13533
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013534 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013535 TRACE_CODE_HDD_CFG80211_ADD_STA,
13536 pAdapter->sessionId, params->listen_interval));
13537
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013538 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013539 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013540
13541 mask = params->sta_flags_mask;
13542
13543 set = params->sta_flags_set;
13544
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013545 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013546 MAC_ADDR_ARRAY(mac));
13547
13548 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13549 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13550 status =
13551 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13552 }
13553 }
13554#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013555 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013556 return status;
13557}
13558
13559/**
13560 * wlan_hdd_cfg80211_add_station() - add station
13561 * @wiphy: Pointer to wiphy
13562 * @mac: Pointer to station mac address
13563 * @pmksa: Pointer to add station parameter
13564 *
13565 * Return: 0 for success, non-zero for failure
13566 */
13567#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13568static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13569 struct net_device *dev,
13570 const uint8_t *mac,
13571 struct station_parameters *params)
13572#else
13573static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13574 struct net_device *dev, uint8_t *mac,
13575 struct station_parameters *params)
13576#endif
13577{
13578 int ret;
13579
13580 cds_ssr_protect(__func__);
13581 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13582 cds_ssr_unprotect(__func__);
13583
13584 return ret;
13585}
13586
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013587/**
13588 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13589 * @wiphy: Pointer to wiphy
13590 * @dev: Pointer to network device
13591 * @pmksa: Pointer to set pmksa parameter
13592 *
13593 * Return: 0 for success, non-zero for failure
13594 */
13595static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13596 struct net_device *dev,
13597 struct cfg80211_pmksa *pmksa)
13598{
13599 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13600 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13601 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013602 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013603 int status;
13604 tPmkidCacheInfo pmk_id;
13605
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013606 ENTER();
13607
Anurag Chouhan6d760662016-02-20 16:05:43 +053013608 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013609 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013610 return -EINVAL;
13611 }
13612
13613 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013614 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013615 return -EINVAL;
13616 }
13617
13618 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013619 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013620 pmksa->bssid, pmksa->pmkid);
13621 return -EINVAL;
13622 }
13623
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013624 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013625 MAC_ADDR_ARRAY(pmksa->bssid));
13626
13627 status = wlan_hdd_validate_context(pHddCtx);
13628
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013629 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013630 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013631
13632 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13633
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013634 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13635 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013636
13637 /* Add to the PMKSA ID Cache in CSR */
13638 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13639 &pmk_id, 1, false);
13640
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013641 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013642 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
13643 pAdapter->sessionId, result));
13644
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013645 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013646 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013647}
13648
13649/**
13650 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13651 * @wiphy: Pointer to wiphy
13652 * @dev: Pointer to network device
13653 * @pmksa: Pointer to set pmksa parameter
13654 *
13655 * Return: 0 for success, non-zero for failure
13656 */
13657static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13658 struct net_device *dev,
13659 struct cfg80211_pmksa *pmksa)
13660{
13661 int ret;
13662
13663 cds_ssr_protect(__func__);
13664 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
13665 cds_ssr_unprotect(__func__);
13666
13667 return ret;
13668}
13669
13670/**
13671 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13672 * @wiphy: Pointer to wiphy
13673 * @dev: Pointer to network device
13674 * @pmksa: Pointer to pmksa parameter
13675 *
13676 * Return: 0 for success, non-zero for failure
13677 */
13678static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13679 struct net_device *dev,
13680 struct cfg80211_pmksa *pmksa)
13681{
13682 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13683 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13684 tHalHandle halHandle;
13685 int status = 0;
13686
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013687 ENTER();
13688
Anurag Chouhan6d760662016-02-20 16:05:43 +053013689 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013690 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013691 return -EINVAL;
13692 }
13693
13694 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013695 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013696 return -EINVAL;
13697 }
13698
13699 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013700 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013701 return -EINVAL;
13702 }
13703
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013704 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013705 MAC_ADDR_ARRAY(pmksa->bssid));
13706
13707 status = wlan_hdd_validate_context(pHddCtx);
13708
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013709 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013710 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013711
13712 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13713
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013714 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053013715 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
13716 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013717 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013718 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013719 sme_roam_del_pmkid_from_cache(halHandle,
13720 pAdapter->sessionId, pmksa->bssid,
13721 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013722 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013723 MAC_ADDR_ARRAY(pmksa->bssid));
13724 status = -EINVAL;
13725 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013726 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013727 return status;
13728}
13729
13730/**
13731 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13732 * @wiphy: Pointer to wiphy
13733 * @dev: Pointer to network device
13734 * @pmksa: Pointer to pmksa parameter
13735 *
13736 * Return: 0 for success, non-zero for failure
13737 */
13738static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13739 struct net_device *dev,
13740 struct cfg80211_pmksa *pmksa)
13741{
13742 int ret;
13743
13744 cds_ssr_protect(__func__);
13745 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
13746 cds_ssr_unprotect(__func__);
13747
13748 return ret;
13749
13750}
13751
13752/**
13753 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13754 * @wiphy: Pointer to wiphy
13755 * @dev: Pointer to network device
13756 *
13757 * Return: 0 for success, non-zero for failure
13758 */
13759static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13760 struct net_device *dev)
13761{
13762 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13763 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13764 tHalHandle halHandle;
13765 int status = 0;
13766
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013767 ENTER();
13768
Anurag Chouhan6d760662016-02-20 16:05:43 +053013769 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013770 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013771 return -EINVAL;
13772 }
13773
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013774 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013775
13776 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13777 status = wlan_hdd_validate_context(pHddCtx);
13778
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013779 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013780 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013781
13782 /* Retrieve halHandle */
13783 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13784
13785 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013786 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013787 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
13788 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013789 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013790 status = -EINVAL;
13791 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013792 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013793 return status;
13794}
13795
13796/**
13797 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13798 * @wiphy: Pointer to wiphy
13799 * @dev: Pointer to network device
13800 *
13801 * Return: 0 for success, non-zero for failure
13802 */
13803static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13804 struct net_device *dev)
13805{
13806 int ret;
13807
13808 cds_ssr_protect(__func__);
13809 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
13810 cds_ssr_unprotect(__func__);
13811
13812 return ret;
13813}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013814
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080013815#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013816/**
13817 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13818 * @wiphy: Pointer to wiphy
13819 * @dev: Pointer to network device
13820 * @ftie: Pointer to fast transition ie parameter
13821 *
13822 * Return: 0 for success, non-zero for failure
13823 */
13824static int
13825__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13826 struct net_device *dev,
13827 struct cfg80211_update_ft_ies_params *ftie)
13828{
13829 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
13830 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13831 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13832 int status;
13833
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013834 ENTER();
13835
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013836 status = wlan_hdd_validate_context(hdd_ctx);
13837 if (status)
13838 return status;
13839
Anurag Chouhan6d760662016-02-20 16:05:43 +053013840 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013841 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013842 return -EINVAL;
13843 }
13844
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013845 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013846 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
13847 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
13848 /* Added for debug on reception of Re-assoc Req. */
13849 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013850 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013851 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013852 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013853 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013854 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013855 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013856
13857 /* Pass the received FT IEs to SME */
13858 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
13859 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013860 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013861 return 0;
13862}
13863
13864/**
13865 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13866 * @wiphy: Pointer to wiphy
13867 * @dev: Pointer to network device
13868 * @ftie: Pointer to fast transition ie parameter
13869 *
13870 * Return: 0 for success, non-zero for failure
13871 */
13872static int
13873wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13874 struct net_device *dev,
13875 struct cfg80211_update_ft_ies_params *ftie)
13876{
13877 int ret;
13878
13879 cds_ssr_protect(__func__);
13880 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
13881 cds_ssr_unprotect(__func__);
13882
13883 return ret;
13884}
13885#endif
13886
13887#ifdef WLAN_FEATURE_GTK_OFFLOAD
13888/**
13889 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
13890 * @callbackContext: Callback context
13891 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
13892 *
13893 * Callback rountine called upon receiving response for get offload info
13894 *
13895 * Return: none
13896 */
13897void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
13898 tpSirGtkOffloadGetInfoRspParams
13899 pGtkOffloadGetInfoRsp)
13900{
13901 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
13902 uint8_t tempReplayCounter[8];
13903 hdd_station_ctx_t *pHddStaCtx;
13904
13905 ENTER();
13906
13907 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013908 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013909 return;
13910 }
13911
13912 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013913 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013914 return;
13915 }
13916
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013917 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013918 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013919 return;
13920 }
13921
13922 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13923 /* Update replay counter */
13924 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
13925 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13926
13927 {
13928 /* changing from little to big endian since supplicant
13929 * works on big endian format
13930 */
13931 int i;
13932 uint8_t *p =
13933 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13934
13935 for (i = 0; i < 8; i++) {
13936 tempReplayCounter[7 - i] = (uint8_t) p[i];
13937 }
13938 }
13939
13940 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080013941 cfg80211_gtk_rekey_notify(pAdapter->dev,
13942 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013943 tempReplayCounter, GFP_KERNEL);
13944}
13945
13946/**
13947 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
13948 * @wiphy: Pointer to wiphy
13949 * @dev: Pointer to network device
13950 * @data: Pointer to rekey data
13951 *
13952 * This function is used to offload GTK rekeying job to the firmware.
13953 *
13954 * Return: 0 for success, non-zero for failure
13955 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013956static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013957int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
13958 struct net_device *dev,
13959 struct cfg80211_gtk_rekey_data *data)
13960{
13961 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13962 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13963 hdd_station_ctx_t *pHddStaCtx;
13964 tHalHandle hHal;
13965 int result;
13966 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013967 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013968
13969 ENTER();
13970
Anurag Chouhan6d760662016-02-20 16:05:43 +053013971 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013972 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013973 return -EINVAL;
13974 }
13975
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013976 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013977 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
13978 pAdapter->sessionId, pAdapter->device_mode));
13979
13980 result = wlan_hdd_validate_context(pHddCtx);
13981
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013982 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013983 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013984
13985 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13986 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13987 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013988 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013989 return -EAGAIN;
13990 }
13991
13992 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
13993 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
13994 NL80211_KCK_LEN);
13995 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
13996 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053013997 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080013998 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013999 {
14000 /* changing from big to little endian since driver
14001 * works on little endian format
14002 */
14003 uint8_t *p =
14004 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14005 ullKeyReplayCounter;
14006 int i;
14007
14008 for (i = 0; i < 8; i++) {
14009 p[7 - i] = data->replay_ctr[i];
14010 }
14011 }
14012
14013 if (true == pHddCtx->hdd_wlan_suspended) {
14014 /* if wlan is suspended, enable GTK offload directly from here */
14015 memcpy(&hddGtkOffloadReqParams,
14016 &pHddStaCtx->gtkOffloadReqParams,
14017 sizeof(tSirGtkOffloadParams));
14018 status =
14019 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14020 pAdapter->sessionId);
14021
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014022 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014023 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014024 status);
14025 return -EINVAL;
14026 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014027 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014028 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014029 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014030 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014031 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014032 return result;
14033}
14034
14035/**
14036 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14037 * @wiphy: Pointer to wiphy
14038 * @dev: Pointer to network device
14039 * @data: Pointer to rekey data
14040 *
14041 * This function is used to offload GTK rekeying job to the firmware.
14042 *
14043 * Return: 0 for success, non-zero for failure
14044 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014045static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014046int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14047 struct net_device *dev,
14048 struct cfg80211_gtk_rekey_data *data)
14049{
14050 int ret;
14051
14052 cds_ssr_protect(__func__);
14053 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14054 cds_ssr_unprotect(__func__);
14055
14056 return ret;
14057}
14058#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14059
14060/**
14061 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14062 * @wiphy: Pointer to wiphy
14063 * @dev: Pointer to network device
14064 * @param: Pointer to access control parameter
14065 *
14066 * Return: 0 for success, non-zero for failure
14067 */
14068static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14069 struct net_device *dev,
14070 const struct cfg80211_acl_data *params)
14071{
14072 int i;
14073 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14074 hdd_hostapd_state_t *pHostapdState;
14075 tsap_Config_t *pConfig;
14076 v_CONTEXT_t p_cds_context = NULL;
14077 hdd_context_t *pHddCtx;
14078 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014079 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014080
14081 ENTER();
14082
Anurag Chouhan6d760662016-02-20 16:05:43 +053014083 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014084 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014085 return -EINVAL;
14086 }
14087
14088 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014089 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014090 return -EINVAL;
14091 }
14092
14093 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14094 status = wlan_hdd_validate_context(pHddCtx);
14095
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014096 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014097 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014098
14099 p_cds_context = pHddCtx->pcds_context;
14100 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14101
14102 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014103 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014104 return -EINVAL;
14105 }
14106
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014107 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014108 params->n_acl_entries);
14109
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014110 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014111 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14112 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014113 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014114 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14115
14116 /* default value */
14117 pConfig->num_accept_mac = 0;
14118 pConfig->num_deny_mac = 0;
14119
14120 /**
14121 * access control policy
14122 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14123 * listed in hostapd.deny file.
14124 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14125 * listed in hostapd.accept file.
14126 */
14127 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14128 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14129 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14130 params->acl_policy) {
14131 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14132 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014133 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014134 params->acl_policy);
14135 return -ENOTSUPP;
14136 }
14137
14138 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14139 pConfig->num_accept_mac = params->n_acl_entries;
14140 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014141 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14142 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014143 MAC_ADDR_ARRAY(
14144 params->mac_addrs[i].addr));
14145
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014146 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014147 params->mac_addrs[i].addr,
14148 sizeof(qcmacaddr));
14149 }
14150 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14151 pConfig->num_deny_mac = params->n_acl_entries;
14152 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014153 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14154 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014155 MAC_ADDR_ARRAY(
14156 params->mac_addrs[i].addr));
14157
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014158 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014159 params->mac_addrs[i].addr,
14160 sizeof(qcmacaddr));
14161 }
14162 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014163 qdf_status = wlansap_set_mac_acl(
14164 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014165 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014166 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014167 return -EINVAL;
14168 }
14169 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014170 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014171 hdd_device_mode_to_string(pAdapter->device_mode),
14172 pAdapter->device_mode);
14173 return -EINVAL;
14174 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014175 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014176 return 0;
14177}
14178
14179/**
14180 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14181 * __wlan_hdd_cfg80211_set_mac_acl
14182 * @wiphy: pointer to wiphy structure
14183 * @dev: pointer to net_device
14184 * @params: pointer to cfg80211_acl_data
14185 *
14186 * Return; 0 on success, error number otherwise
14187 */
14188static int
14189wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14190 struct net_device *dev,
14191 const struct cfg80211_acl_data *params)
14192{
14193 int ret;
14194
14195 cds_ssr_protect(__func__);
14196 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14197 cds_ssr_unprotect(__func__);
14198
14199 return ret;
14200}
14201
14202#ifdef WLAN_NL80211_TESTMODE
14203#ifdef FEATURE_WLAN_LPHB
14204/**
14205 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14206 * @pHddCtx: Pointer to hdd context
14207 * @lphbInd: Pointer to low power heart beat indication parameter
14208 *
14209 * Return: none
14210 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014211static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14212 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014213{
14214 struct sk_buff *skb;
14215
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014216 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014217
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014218 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014219 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014220
14221 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014222 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014223 return;
14224 }
14225
14226 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14227 wiphy, sizeof(tSirLPHBInd),
14228 GFP_ATOMIC);
14229 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014230 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014231 return;
14232 }
14233
14234 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014235 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014236 goto nla_put_failure;
14237 }
14238 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014239 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014240 goto nla_put_failure;
14241 }
14242 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014243 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014244 goto nla_put_failure;
14245 }
14246 cfg80211_testmode_event(skb, GFP_ATOMIC);
14247 return;
14248
14249nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014250 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014251 kfree_skb(skb);
14252
14253 return;
14254}
14255#endif /* FEATURE_WLAN_LPHB */
14256
14257/**
14258 * __wlan_hdd_cfg80211_testmode() - test mode
14259 * @wiphy: Pointer to wiphy
14260 * @data: Data pointer
14261 * @len: Data length
14262 *
14263 * Return: 0 for success, non-zero for failure
14264 */
14265static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14266 void *data, int len)
14267{
14268 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14269 int err;
14270 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14271
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014272 ENTER();
14273
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014274 err = wlan_hdd_validate_context(pHddCtx);
14275 if (err)
14276 return err;
14277
14278 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14279 len, wlan_hdd_tm_policy);
14280 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014281 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014282 return err;
14283 }
14284
14285 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014286 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014287 return -EINVAL;
14288 }
14289
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014290 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014291 TRACE_CODE_HDD_CFG80211_TESTMODE,
14292 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014293 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14294#ifdef FEATURE_WLAN_LPHB
14295 /* Low Power Heartbeat configuration request */
14296 case WLAN_HDD_TM_CMD_WLAN_HB:
14297 {
14298 int buf_len;
14299 void *buf;
14300 tSirLPHBReq *hb_params = NULL;
14301 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014302 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014303
14304 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014305 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014306 return -EINVAL;
14307 }
14308
14309 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14310 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14311
14312 hb_params_temp = (tSirLPHBReq *) buf;
14313 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14314 && (hb_params_temp->params.lphbTcpParamReq.
14315 timePeriodSec == 0))
14316 return -EINVAL;
14317
14318 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014319 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014320 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014321 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014322 return -ENOMEM;
14323 }
14324
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014325 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014326 smeStatus =
14327 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14328 hb_params,
14329 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014330 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014331 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014332 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014333 }
14334 return 0;
14335 }
14336#endif /* FEATURE_WLAN_LPHB */
14337
14338#if defined(QCA_WIFI_FTM)
14339 case WLAN_HDD_TM_CMD_WLAN_FTM:
14340 {
14341 int buf_len;
14342 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014343 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014344 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014345 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014346 return -EINVAL;
14347 }
14348
14349 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14350 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14351
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014352 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014353
14354 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14355
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014356 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014357 err = -EBUSY;
14358 break;
14359 }
14360#endif
14361
14362 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014363 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014364 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14365 return -EOPNOTSUPP;
14366 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014367 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014368 return err;
14369}
14370
14371/**
14372 * wlan_hdd_cfg80211_testmode() - test mode
14373 * @wiphy: Pointer to wiphy
14374 * @dev: Pointer to network device
14375 * @data: Data pointer
14376 * @len: Data length
14377 *
14378 * Return: 0 for success, non-zero for failure
14379 */
14380static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14381#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14382 struct wireless_dev *wdev,
14383#endif
14384 void *data, int len)
14385{
14386 int ret;
14387
14388 cds_ssr_protect(__func__);
14389 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14390 cds_ssr_unprotect(__func__);
14391
14392 return ret;
14393}
14394
14395#if defined(QCA_WIFI_FTM)
14396/**
14397 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14398 * @buf: Pointer to buffer
14399 * @buf_len: Buffer length
14400 *
14401 * Return: none
14402 */
14403void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14404{
14405 struct sk_buff *skb;
14406 hdd_context_t *hdd_ctx;
14407
14408 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014409 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014410 return;
14411 }
14412
Anurag Chouhan6d760662016-02-20 16:05:43 +053014413 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014414 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014415 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014416 return;
14417 }
14418
14419 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14420 buf_len, GFP_KERNEL);
14421 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014422 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014423 return;
14424 }
14425
14426 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14427 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14428 goto nla_put_failure;
14429
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014430 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014431
14432 cfg80211_testmode_event(skb, GFP_KERNEL);
14433 return;
14434
14435nla_put_failure:
14436 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014437 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014438}
14439#endif
14440#endif /* CONFIG_NL80211_TESTMODE */
14441
14442#ifdef QCA_HT_2040_COEX
14443/**
14444 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14445 * @wiphy: Pointer to wiphy
14446 * @dev: Pointer to network device
14447 * @chandef: Pointer to channel definition parameter
14448 *
14449 * Return: 0 for success, non-zero for failure
14450 */
14451static int
14452__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14453 struct net_device *dev,
14454 struct cfg80211_chan_def *chandef)
14455{
14456 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14457 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014458 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014459 tSmeConfigParams sme_config;
14460 bool cbModeChange;
14461
Anurag Chouhan6d760662016-02-20 16:05:43 +053014462 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014463 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014464 return -EINVAL;
14465 }
14466
14467 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14468 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014469 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014470 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014471
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014472 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014473 sme_get_config_param(pHddCtx->hHal, &sme_config);
14474 switch (chandef->width) {
14475 case NL80211_CHAN_WIDTH_20:
14476 if (sme_config.csrConfig.channelBondingMode24GHz !=
14477 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14478 sme_config.csrConfig.channelBondingMode24GHz =
14479 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14480 sme_update_config(pHddCtx->hHal, &sme_config);
14481 cbModeChange = true;
14482 }
14483 break;
14484
14485 case NL80211_CHAN_WIDTH_40:
14486 if (sme_config.csrConfig.channelBondingMode24GHz ==
14487 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14488 if (NL80211_CHAN_HT40MINUS ==
14489 cfg80211_get_chandef_type(chandef))
14490 sme_config.csrConfig.channelBondingMode24GHz =
14491 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14492 else
14493 sme_config.csrConfig.channelBondingMode24GHz =
14494 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14495 sme_update_config(pHddCtx->hHal, &sme_config);
14496 cbModeChange = true;
14497 }
14498 break;
14499
14500 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014501 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014502 return -EINVAL;
14503 }
14504
14505 if (!cbModeChange)
14506 return 0;
14507
Krunal Sonib4326f22016-03-10 13:05:51 -080014508 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014509 return 0;
14510
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014511 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014512 sme_config.csrConfig.channelBondingMode24GHz);
14513
14514 /* Change SAP ht2040 mode */
14515 status = hdd_set_sap_ht2040_mode(pAdapter,
14516 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014517 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014518 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014519 return -EINVAL;
14520 }
14521
14522 return 0;
14523}
14524
14525/**
14526 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14527 * @wiphy: Pointer to wiphy
14528 * @dev: Pointer to network device
14529 * @chandef: Pointer to channel definition parameter
14530 *
14531 * Return: 0 for success, non-zero for failure
14532 */
14533static int
14534wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14535 struct net_device *dev,
14536 struct cfg80211_chan_def *chandef)
14537{
14538 int ret;
14539
14540 cds_ssr_protect(__func__);
14541 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14542 cds_ssr_unprotect(__func__);
14543
14544 return ret;
14545}
14546#endif
14547
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014548#ifdef CHANNEL_SWITCH_SUPPORTED
14549/**
14550 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14551 * channel in SAP/GO
14552 * @wiphy: wiphy pointer
14553 * @dev: dev pointer.
14554 * @csa_params: Change channel params
14555 *
14556 * This function is called to switch channel in SAP/GO
14557 *
14558 * Return: 0 if success else return non zero
14559 */
14560static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14561 struct net_device *dev,
14562 struct cfg80211_csa_settings *csa_params)
14563{
14564 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14565 hdd_context_t *hdd_ctx;
14566 uint8_t channel;
14567 uint16_t freq;
14568 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014569 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014570
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014571 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014572 csa_params->chandef.chan->center_freq);
14573
14574 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14575 ret = wlan_hdd_validate_context(hdd_ctx);
14576
14577 if (0 != ret)
14578 return ret;
14579
Krunal Sonib4326f22016-03-10 13:05:51 -080014580 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14581 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014582 return -ENOTSUPP;
14583
14584 freq = csa_params->chandef.chan->center_freq;
14585 channel = cds_freq_to_chan(freq);
14586
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014587 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14588
14589 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014590 return ret;
14591}
14592
14593/**
14594 * wlan_hdd_cfg80211_channel_switch()- function to switch
14595 * channel in SAP/GO
14596 * @wiphy: wiphy pointer
14597 * @dev: dev pointer.
14598 * @csa_params: Change channel params
14599 *
14600 * This function is called to switch channel in SAP/GO
14601 *
14602 * Return: 0 if success else return non zero
14603 */
14604static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14605 struct net_device *dev,
14606 struct cfg80211_csa_settings *csa_params)
14607{
14608 int ret;
14609
14610 cds_ssr_protect(__func__);
14611 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14612 cds_ssr_unprotect(__func__);
14613 return ret;
14614}
14615#endif
14616
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014617/**
14618 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14619 * translation from NL to policy manager type
14620 * @type: Generic connection mode type defined in NL
14621 *
14622 *
14623 * This function provides the type translation
14624 *
14625 * Return: cds_con_mode enum
14626 */
14627enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
14628 enum nl80211_iftype type)
14629{
14630 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
14631 switch (type) {
14632 case NL80211_IFTYPE_STATION:
14633 mode = CDS_STA_MODE;
14634 break;
14635 case NL80211_IFTYPE_P2P_CLIENT:
14636 mode = CDS_P2P_CLIENT_MODE;
14637 break;
14638 case NL80211_IFTYPE_P2P_GO:
14639 mode = CDS_P2P_GO_MODE;
14640 break;
14641 case NL80211_IFTYPE_AP:
14642 mode = CDS_SAP_MODE;
14643 break;
14644 case NL80211_IFTYPE_ADHOC:
14645 mode = CDS_IBSS_MODE;
14646 break;
14647 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014648 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014649 type);
14650 }
14651 return mode;
14652}
14653
14654/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014655 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14656 * @wiphy: Handle to struct wiphy to get handle to module context.
14657 * @chandef: Contains information about the capture channel to be set.
14658 *
14659 * This interface is called if and only if monitor mode interface alone is
14660 * active.
14661 *
14662 * Return: 0 success or error code on failure.
14663 */
14664static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14665 struct cfg80211_chan_def *chandef)
14666{
14667 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14668 hdd_adapter_t *adapter;
14669 hdd_station_ctx_t *sta_ctx;
14670 struct hdd_mon_set_ch_info *ch_info;
14671 QDF_STATUS status;
14672 tHalHandle hal_hdl;
14673 struct qdf_mac_addr bssid;
14674 tCsrRoamProfile roam_profile;
14675 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014676 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014677 int ret;
14678 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
14679
14680 ENTER();
14681
14682 ret = wlan_hdd_validate_context(hdd_ctx);
14683 if (ret)
14684 return ret;
14685
14686 hal_hdl = hdd_ctx->hHal;
14687
14688 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
14689 if (!adapter)
14690 return -EIO;
14691
14692 hdd_info("%s: set monitor mode Channel %d and freq %d",
14693 adapter->dev->name, chan_num, chandef->chan->center_freq);
14694
14695 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14696 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014697 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
14698 roam_profile.ChannelInfo.numOfChannels = 1;
14699 roam_profile.phyMode = ch_info->phy_mode;
14700 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014701 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014702
14703 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
14704 QDF_MAC_ADDR_SIZE);
14705
14706 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014707 /*
14708 * CDS api expects secondary channel for calculating
14709 * the channel params
14710 */
14711 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
14712 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
14713 if (chan_num >= 1 && chan_num <= 5)
14714 sec_ch = chan_num + 4;
14715 else if (chan_num >= 6 && chan_num <= 13)
14716 sec_ch = chan_num - 4;
14717 }
14718 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014719 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
14720 &roam_profile);
14721 if (status) {
14722 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
14723 status);
14724 ret = qdf_status_to_os_return(status);
14725 return ret;
14726 }
14727 EXIT();
14728 return 0;
14729}
14730
14731/**
14732 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14733 * @wiphy: Handle to struct wiphy to get handle to module context.
14734 * @chandef: Contains information about the capture channel to be set.
14735 *
14736 * This interface is called if and only if monitor mode interface alone is
14737 * active.
14738 *
14739 * Return: 0 success or error code on failure.
14740 */
14741static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14742 struct cfg80211_chan_def *chandef)
14743{
14744 int ret;
14745
14746 cds_ssr_protect(__func__);
14747 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
14748 cds_ssr_unprotect(__func__);
14749 return ret;
14750}
14751
14752/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014753 * struct cfg80211_ops - cfg80211_ops
14754 *
14755 * @add_virtual_intf: Add virtual interface
14756 * @del_virtual_intf: Delete virtual interface
14757 * @change_virtual_intf: Change virtual interface
14758 * @change_station: Change station
14759 * @add_beacon: Add beacon in sap mode
14760 * @del_beacon: Delete beacon in sap mode
14761 * @set_beacon: Set beacon in sap mode
14762 * @start_ap: Start ap
14763 * @change_beacon: Change beacon
14764 * @stop_ap: Stop ap
14765 * @change_bss: Change bss
14766 * @add_key: Add key
14767 * @get_key: Get key
14768 * @del_key: Delete key
14769 * @set_default_key: Set default key
14770 * @set_channel: Set channel
14771 * @scan: Scan
14772 * @connect: Connect
14773 * @disconnect: Disconnect
14774 * @join_ibss = Join ibss
14775 * @leave_ibss = Leave ibss
14776 * @set_wiphy_params = Set wiphy params
14777 * @set_tx_power = Set tx power
14778 * @get_tx_power = get tx power
14779 * @remain_on_channel = Remain on channel
14780 * @cancel_remain_on_channel = Cancel remain on channel
14781 * @mgmt_tx = Tx management frame
14782 * @mgmt_tx_cancel_wait = Cancel management tx wait
14783 * @set_default_mgmt_key = Set default management key
14784 * @set_txq_params = Set tx queue parameters
14785 * @get_station = Get station
14786 * @set_power_mgmt = Set power management
14787 * @del_station = Delete station
14788 * @add_station = Add station
14789 * @set_pmksa = Set pmksa
14790 * @del_pmksa = Delete pmksa
14791 * @flush_pmksa = Flush pmksa
14792 * @update_ft_ies = Update FT IEs
14793 * @tdls_mgmt = Tdls management
14794 * @tdls_oper = Tdls operation
14795 * @set_rekey_data = Set rekey data
14796 * @sched_scan_start = Scheduled scan start
14797 * @sched_scan_stop = Scheduled scan stop
14798 * @resume = Resume wlan
14799 * @suspend = Suspend wlan
14800 * @set_mac_acl = Set mac acl
14801 * @testmode_cmd = Test mode command
14802 * @set_ap_chanwidth = Set AP channel bandwidth
14803 * @dump_survey = Dump survey
14804 * @key_mgmt_set_pmk = Set pmk key management
14805 */
14806static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
14807 .add_virtual_intf = wlan_hdd_add_virtual_intf,
14808 .del_virtual_intf = wlan_hdd_del_virtual_intf,
14809 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
14810 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014811 .start_ap = wlan_hdd_cfg80211_start_ap,
14812 .change_beacon = wlan_hdd_cfg80211_change_beacon,
14813 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014814 .change_bss = wlan_hdd_cfg80211_change_bss,
14815 .add_key = wlan_hdd_cfg80211_add_key,
14816 .get_key = wlan_hdd_cfg80211_get_key,
14817 .del_key = wlan_hdd_cfg80211_del_key,
14818 .set_default_key = wlan_hdd_cfg80211_set_default_key,
14819 .scan = wlan_hdd_cfg80211_scan,
14820 .connect = wlan_hdd_cfg80211_connect,
14821 .disconnect = wlan_hdd_cfg80211_disconnect,
14822 .join_ibss = wlan_hdd_cfg80211_join_ibss,
14823 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
14824 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
14825 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
14826 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
14827 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
14828 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
14829 .mgmt_tx = wlan_hdd_mgmt_tx,
14830 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
14831 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
14832 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053014833 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014834 .get_station = wlan_hdd_cfg80211_get_station,
14835 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
14836 .del_station = wlan_hdd_cfg80211_del_station,
14837 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014838 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
14839 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
14840 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014841#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014842 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
14843#endif
14844#ifdef FEATURE_WLAN_TDLS
14845 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
14846 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
14847#endif
14848#ifdef WLAN_FEATURE_GTK_OFFLOAD
14849 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
14850#endif /* WLAN_FEATURE_GTK_OFFLOAD */
14851#ifdef FEATURE_WLAN_SCAN_PNO
14852 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
14853 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
14854#endif /*FEATURE_WLAN_SCAN_PNO */
14855 .resume = wlan_hdd_cfg80211_resume_wlan,
14856 .suspend = wlan_hdd_cfg80211_suspend_wlan,
14857 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
14858#ifdef WLAN_NL80211_TESTMODE
14859 .testmode_cmd = wlan_hdd_cfg80211_testmode,
14860#endif
14861#ifdef QCA_HT_2040_COEX
14862 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
14863#endif
14864 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014865#ifdef CHANNEL_SWITCH_SUPPORTED
14866 .channel_switch = wlan_hdd_cfg80211_channel_switch,
14867#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014868 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053014869#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
14870 defined(CFG80211_ABORT_SCAN)
14871 .abort_scan = wlan_hdd_cfg80211_abort_scan,
14872#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014873};