blob: c534a7dd8e39eed1df763d5343d39156e14c2885 [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"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800101
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800102#define g_mode_rates_size (12)
103#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800104#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
105 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
106
107/*
108 * Android CTS verifier needs atleast this much wait time (in msec)
109 */
110#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
111
112/*
113 * Refer @tCfgProtection structure for definition of the bit map.
114 * below value is obtained by setting the following bit-fields.
115 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
116 */
117#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
118
119#define HDD2GHZCHAN(freq, chan, flag) { \
120 .band = IEEE80211_BAND_2GHZ, \
121 .center_freq = (freq), \
122 .hw_value = (chan), \
123 .flags = (flag), \
124 .max_antenna_gain = 0, \
125 .max_power = 30, \
126}
127
128#define HDD5GHZCHAN(freq, chan, flag) { \
129 .band = IEEE80211_BAND_5GHZ, \
130 .center_freq = (freq), \
131 .hw_value = (chan), \
132 .flags = (flag), \
133 .max_antenna_gain = 0, \
134 .max_power = 30, \
135}
136
137#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
138 { \
139 .bitrate = rate, \
140 .hw_value = rate_id, \
141 .flags = flag, \
142 }
143
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800144#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
145#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800146
147#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148
Agrawal Ashish65634612016-08-18 13:24:32 +0530149#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
150 mode <= DFS_MODE_DEPRIORITIZE))
151#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
152 || (channel >= 36 && channel <= 184))
153
Peng Xu4d67c8f2015-10-16 16:02:26 -0700154#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530155#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700156
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157static const u32 hdd_cipher_suites[] = {
158 WLAN_CIPHER_SUITE_WEP40,
159 WLAN_CIPHER_SUITE_WEP104,
160 WLAN_CIPHER_SUITE_TKIP,
161#ifdef FEATURE_WLAN_ESE
162#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
163#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
164 WLAN_CIPHER_SUITE_BTK,
165 WLAN_CIPHER_SUITE_KRK,
166 WLAN_CIPHER_SUITE_CCMP,
167#else
168 WLAN_CIPHER_SUITE_CCMP,
169#endif
170#ifdef FEATURE_WLAN_WAPI
171 WLAN_CIPHER_SUITE_SMS4,
172#endif
173#ifdef WLAN_FEATURE_11W
174 WLAN_CIPHER_SUITE_AES_CMAC,
175#endif
176};
177
Abhishek Singhf512bf32016-05-04 16:47:46 +0530178static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800179 HDD2GHZCHAN(2412, 1, 0),
180 HDD2GHZCHAN(2417, 2, 0),
181 HDD2GHZCHAN(2422, 3, 0),
182 HDD2GHZCHAN(2427, 4, 0),
183 HDD2GHZCHAN(2432, 5, 0),
184 HDD2GHZCHAN(2437, 6, 0),
185 HDD2GHZCHAN(2442, 7, 0),
186 HDD2GHZCHAN(2447, 8, 0),
187 HDD2GHZCHAN(2452, 9, 0),
188 HDD2GHZCHAN(2457, 10, 0),
189 HDD2GHZCHAN(2462, 11, 0),
190 HDD2GHZCHAN(2467, 12, 0),
191 HDD2GHZCHAN(2472, 13, 0),
192 HDD2GHZCHAN(2484, 14, 0),
193};
194
Abhishek Singhf512bf32016-05-04 16:47:46 +0530195static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800196 HDD5GHZCHAN(5180, 36, 0),
197 HDD5GHZCHAN(5200, 40, 0),
198 HDD5GHZCHAN(5220, 44, 0),
199 HDD5GHZCHAN(5240, 48, 0),
200 HDD5GHZCHAN(5260, 52, 0),
201 HDD5GHZCHAN(5280, 56, 0),
202 HDD5GHZCHAN(5300, 60, 0),
203 HDD5GHZCHAN(5320, 64, 0),
204 HDD5GHZCHAN(5500, 100, 0),
205 HDD5GHZCHAN(5520, 104, 0),
206 HDD5GHZCHAN(5540, 108, 0),
207 HDD5GHZCHAN(5560, 112, 0),
208 HDD5GHZCHAN(5580, 116, 0),
209 HDD5GHZCHAN(5600, 120, 0),
210 HDD5GHZCHAN(5620, 124, 0),
211 HDD5GHZCHAN(5640, 128, 0),
212 HDD5GHZCHAN(5660, 132, 0),
213 HDD5GHZCHAN(5680, 136, 0),
214 HDD5GHZCHAN(5700, 140, 0),
215 HDD5GHZCHAN(5720, 144, 0),
216 HDD5GHZCHAN(5745, 149, 0),
217 HDD5GHZCHAN(5765, 153, 0),
218 HDD5GHZCHAN(5785, 157, 0),
219 HDD5GHZCHAN(5805, 161, 0),
220 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800221 HDD5GHZCHAN(5852, 170, 0),
222 HDD5GHZCHAN(5855, 171, 0),
223 HDD5GHZCHAN(5860, 172, 0),
224 HDD5GHZCHAN(5865, 173, 0),
225 HDD5GHZCHAN(5870, 174, 0),
226 HDD5GHZCHAN(5875, 175, 0),
227 HDD5GHZCHAN(5880, 176, 0),
228 HDD5GHZCHAN(5885, 177, 0),
229 HDD5GHZCHAN(5890, 178, 0),
230 HDD5GHZCHAN(5895, 179, 0),
231 HDD5GHZCHAN(5900, 180, 0),
232 HDD5GHZCHAN(5905, 181, 0),
233 HDD5GHZCHAN(5910, 182, 0),
234 HDD5GHZCHAN(5915, 183, 0),
235 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800236};
237
238static struct ieee80211_rate g_mode_rates[] = {
239 HDD_G_MODE_RATETAB(10, 0x1, 0),
240 HDD_G_MODE_RATETAB(20, 0x2, 0),
241 HDD_G_MODE_RATETAB(55, 0x4, 0),
242 HDD_G_MODE_RATETAB(110, 0x8, 0),
243 HDD_G_MODE_RATETAB(60, 0x10, 0),
244 HDD_G_MODE_RATETAB(90, 0x20, 0),
245 HDD_G_MODE_RATETAB(120, 0x40, 0),
246 HDD_G_MODE_RATETAB(180, 0x80, 0),
247 HDD_G_MODE_RATETAB(240, 0x100, 0),
248 HDD_G_MODE_RATETAB(360, 0x200, 0),
249 HDD_G_MODE_RATETAB(480, 0x400, 0),
250 HDD_G_MODE_RATETAB(540, 0x800, 0),
251};
252
253static struct ieee80211_rate a_mode_rates[] = {
254 HDD_G_MODE_RATETAB(60, 0x10, 0),
255 HDD_G_MODE_RATETAB(90, 0x20, 0),
256 HDD_G_MODE_RATETAB(120, 0x40, 0),
257 HDD_G_MODE_RATETAB(180, 0x80, 0),
258 HDD_G_MODE_RATETAB(240, 0x100, 0),
259 HDD_G_MODE_RATETAB(360, 0x200, 0),
260 HDD_G_MODE_RATETAB(480, 0x400, 0),
261 HDD_G_MODE_RATETAB(540, 0x800, 0),
262};
263
264static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530265 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800266 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
267 .band = IEEE80211_BAND_2GHZ,
268 .bitrates = g_mode_rates,
269 .n_bitrates = g_mode_rates_size,
270 .ht_cap.ht_supported = 1,
271 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
272 | IEEE80211_HT_CAP_GRN_FLD
273 | IEEE80211_HT_CAP_DSSSCCK40
274 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
275 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
276 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
277 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
278 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
279 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
280 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
281};
282
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800283static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530284 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800285 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
286 .band = IEEE80211_BAND_5GHZ,
287 .bitrates = a_mode_rates,
288 .n_bitrates = a_mode_rates_size,
289 .ht_cap.ht_supported = 1,
290 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
291 | IEEE80211_HT_CAP_GRN_FLD
292 | IEEE80211_HT_CAP_DSSSCCK40
293 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
294 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
295 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
296 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
297 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
298 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
299 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
300 .vht_cap.vht_supported = 1,
301};
302
303/* This structure contain information what kind of frame are expected in
304 TX/RX direction for each kind of interface */
305static const struct ieee80211_txrx_stypes
306 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
307 [NL80211_IFTYPE_STATION] = {
308 .tx = 0xffff,
309 .rx = BIT(SIR_MAC_MGMT_ACTION) |
310 BIT(SIR_MAC_MGMT_PROBE_REQ),
311 },
312 [NL80211_IFTYPE_AP] = {
313 .tx = 0xffff,
314 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
315 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
316 BIT(SIR_MAC_MGMT_PROBE_REQ) |
317 BIT(SIR_MAC_MGMT_DISASSOC) |
318 BIT(SIR_MAC_MGMT_AUTH) |
319 BIT(SIR_MAC_MGMT_DEAUTH) |
320 BIT(SIR_MAC_MGMT_ACTION),
321 },
322 [NL80211_IFTYPE_ADHOC] = {
323 .tx = 0xffff,
324 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
325 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
326 BIT(SIR_MAC_MGMT_PROBE_REQ) |
327 BIT(SIR_MAC_MGMT_DISASSOC) |
328 BIT(SIR_MAC_MGMT_AUTH) |
329 BIT(SIR_MAC_MGMT_DEAUTH) |
330 BIT(SIR_MAC_MGMT_ACTION),
331 },
332 [NL80211_IFTYPE_P2P_CLIENT] = {
333 .tx = 0xffff,
334 .rx = BIT(SIR_MAC_MGMT_ACTION) |
335 BIT(SIR_MAC_MGMT_PROBE_REQ),
336 },
337 [NL80211_IFTYPE_P2P_GO] = {
338 /* This is also same as for SoftAP */
339 .tx = 0xffff,
340 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
341 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
342 BIT(SIR_MAC_MGMT_PROBE_REQ) |
343 BIT(SIR_MAC_MGMT_DISASSOC) |
344 BIT(SIR_MAC_MGMT_AUTH) |
345 BIT(SIR_MAC_MGMT_DEAUTH) |
346 BIT(SIR_MAC_MGMT_ACTION),
347 },
348};
349
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800350/* Interface limits and combinations registered by the driver */
351
352/* STA ( + STA ) combination */
353static const struct ieee80211_iface_limit
354 wlan_hdd_sta_iface_limit[] = {
355 {
356 .max = 3, /* p2p0 is a STA as well */
357 .types = BIT(NL80211_IFTYPE_STATION),
358 },
359};
360
361/* ADHOC (IBSS) limit */
362static const struct ieee80211_iface_limit
363 wlan_hdd_adhoc_iface_limit[] = {
364 {
365 .max = 1,
366 .types = BIT(NL80211_IFTYPE_STATION),
367 },
368 {
369 .max = 1,
370 .types = BIT(NL80211_IFTYPE_ADHOC),
371 },
372};
373
374/* AP ( + AP ) combination */
375static const struct ieee80211_iface_limit
376 wlan_hdd_ap_iface_limit[] = {
377 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530378 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800379 .types = BIT(NL80211_IFTYPE_AP),
380 },
381};
382
383/* P2P limit */
384static const struct ieee80211_iface_limit
385 wlan_hdd_p2p_iface_limit[] = {
386 {
387 .max = 1,
388 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
389 },
390 {
391 .max = 1,
392 .types = BIT(NL80211_IFTYPE_P2P_GO),
393 },
394};
395
396static const struct ieee80211_iface_limit
397 wlan_hdd_sta_ap_iface_limit[] = {
398 {
399 /* We need 1 extra STA interface for OBSS scan when SAP starts
400 * with HT40 in STA+SAP concurrency mode
401 */
402 .max = (1 + SAP_MAX_OBSS_STA_CNT),
403 .types = BIT(NL80211_IFTYPE_STATION),
404 },
405 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530406 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800407 .types = BIT(NL80211_IFTYPE_AP),
408 },
409};
410
411/* STA + P2P combination */
412static const struct ieee80211_iface_limit
413 wlan_hdd_sta_p2p_iface_limit[] = {
414 {
415 /* One reserved for dedicated P2PDEV usage */
416 .max = 2,
417 .types = BIT(NL80211_IFTYPE_STATION)
418 },
419 {
420 /* Support for two identical (GO + GO or CLI + CLI)
421 * or dissimilar (GO + CLI) P2P interfaces
422 */
423 .max = 2,
424 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
425 },
426};
427
428/* STA + AP + P2PGO combination */
429static const struct ieee80211_iface_limit
430wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
431 /* Support for AP+P2PGO interfaces */
432 {
433 .max = 2,
434 .types = BIT(NL80211_IFTYPE_STATION)
435 },
436 {
437 .max = 1,
438 .types = BIT(NL80211_IFTYPE_P2P_GO)
439 },
440 {
441 .max = 1,
442 .types = BIT(NL80211_IFTYPE_AP)
443 }
444};
445
446/* SAP + P2P combination */
447static const struct ieee80211_iface_limit
448wlan_hdd_sap_p2p_iface_limit[] = {
449 {
450 /* 1 dedicated for p2p0 which is a STA type */
451 .max = 1,
452 .types = BIT(NL80211_IFTYPE_STATION)
453 },
454 {
455 /* The p2p interface in SAP+P2P can be GO/CLI.
456 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
457 */
458 .max = 1,
459 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
460 },
461 {
462 /* SAP+GO to support only one SAP interface */
463 .max = 1,
464 .types = BIT(NL80211_IFTYPE_AP)
465 }
466};
467
468/* P2P + P2P combination */
469static const struct ieee80211_iface_limit
470wlan_hdd_p2p_p2p_iface_limit[] = {
471 {
472 /* 1 dedicated for p2p0 which is a STA type */
473 .max = 1,
474 .types = BIT(NL80211_IFTYPE_STATION)
475 },
476 {
477 /* The p2p interface in P2P+P2P can be GO/CLI.
478 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
479 */
480 .max = 2,
481 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
482 },
483};
484
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700485static const struct ieee80211_iface_limit
486 wlan_hdd_mon_iface_limit[] = {
487 {
488 .max = 3, /* Monitor interface */
489 .types = BIT(NL80211_IFTYPE_MONITOR),
490 },
491};
492
493static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800494 wlan_hdd_iface_combination[] = {
495 /* STA */
496 {
497 .limits = wlan_hdd_sta_iface_limit,
498 .num_different_channels = 2,
499 .max_interfaces = 3,
500 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
501 },
502 /* ADHOC */
503 {
504 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700505 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800506 .max_interfaces = 2,
507 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
508 },
509 /* AP */
510 {
511 .limits = wlan_hdd_ap_iface_limit,
512 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530513 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800514 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
515 },
516 /* P2P */
517 {
518 .limits = wlan_hdd_p2p_iface_limit,
519 .num_different_channels = 2,
520 .max_interfaces = 2,
521 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
522 },
523 /* STA + AP */
524 {
525 .limits = wlan_hdd_sta_ap_iface_limit,
526 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530527 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
529 .beacon_int_infra_match = true,
530 },
531 /* STA + P2P */
532 {
533 .limits = wlan_hdd_sta_p2p_iface_limit,
534 .num_different_channels = 2,
535 /* one interface reserved for P2PDEV dedicated usage */
536 .max_interfaces = 4,
537 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
538 .beacon_int_infra_match = true,
539 },
540 /* STA + P2P GO + SAP */
541 {
542 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
543 /* we can allow 3 channels for three different persona
544 * but due to firmware limitation, allow max 2 concrnt channels.
545 */
546 .num_different_channels = 2,
547 /* one interface reserved for P2PDEV dedicated usage */
548 .max_interfaces = 4,
549 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
550 .beacon_int_infra_match = true,
551 },
552 /* SAP + P2P */
553 {
554 .limits = wlan_hdd_sap_p2p_iface_limit,
555 .num_different_channels = 2,
556 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
557 .max_interfaces = 3,
558 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
559 .beacon_int_infra_match = true,
560 },
561 /* P2P + P2P */
562 {
563 .limits = wlan_hdd_p2p_p2p_iface_limit,
564 .num_different_channels = 2,
565 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
566 .max_interfaces = 3,
567 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
568 .beacon_int_infra_match = true,
569 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530570 /* Monitor */
571 {
572 .limits = wlan_hdd_mon_iface_limit,
573 .max_interfaces = 3,
574 .num_different_channels = 2,
575 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
576 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800577};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578
579static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530580struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581
582#ifdef WLAN_NL80211_TESTMODE
583enum wlan_hdd_tm_attr {
584 WLAN_HDD_TM_ATTR_INVALID = 0,
585 WLAN_HDD_TM_ATTR_CMD = 1,
586 WLAN_HDD_TM_ATTR_DATA = 2,
587 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
588 WLAN_HDD_TM_ATTR_TYPE = 4,
589 /* keep last */
590 WLAN_HDD_TM_ATTR_AFTER_LAST,
591 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
592};
593
594enum wlan_hdd_tm_cmd {
595 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
596 WLAN_HDD_TM_CMD_WLAN_HB = 1,
597};
598
599#define WLAN_HDD_TM_DATA_MAX_LEN 5000
600
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530601enum wlan_hdd_vendor_ie_access_policy {
602 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
603 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
604};
605
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800606static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
607 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
608 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
609 .len = WLAN_HDD_TM_DATA_MAX_LEN},
610};
611#endif /* WLAN_NL80211_TESTMODE */
612
613#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
614static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
615 .flags = WIPHY_WOWLAN_MAGIC_PKT,
616 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
617 .pattern_min_len = 1,
618 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
619};
620#endif
621
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800622/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530623 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
624 * @flags: Pointer to the flags to Add channel switch flag.
625 *
626 * This Function adds Channel Switch support flag, if channel switch is
627 * supported by kernel.
628 * Return: void.
629 */
630#ifdef CHANNEL_SWITCH_SUPPORTED
631static inline void hdd_add_channel_switch_support(uint32_t *flags)
632{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800633 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530634 return;
635}
636#else
637static inline void hdd_add_channel_switch_support(uint32_t *flags)
638{
639 return;
640}
641#endif
642
Manikandan Mohan22b83722015-12-15 15:03:23 -0800643#ifdef FEATURE_WLAN_TDLS
644
645/* TDLS capabilities params */
646#define PARAM_MAX_TDLS_SESSION \
647 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
648#define PARAM_TDLS_FEATURE_SUPPORT \
649 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
650
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530651/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800652 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
653 * @wiphy: WIPHY structure pointer
654 * @wdev: Wireless device structure pointer
655 * @data: Pointer to the data received
656 * @data_len: Length of the data received
657 *
658 * This function provides TDLS capabilities
659 *
660 * Return: 0 on success and errno on failure
661 */
662static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
663 struct wireless_dev *wdev,
664 const void *data,
665 int data_len)
666{
667 int status;
668 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
669 struct sk_buff *skb;
670 uint32_t set = 0;
671
Jeff Johnson1f61b612016-02-12 16:28:33 -0800672 ENTER_DEV(wdev->netdev);
673
Anurag Chouhan6d760662016-02-20 16:05:43 +0530674 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800675 hdd_err("Command not allowed in FTM mode");
676 return -EPERM;
677 }
678
679 status = wlan_hdd_validate_context(hdd_ctx);
680 if (status)
681 return status;
682
683 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
684 NLMSG_HDRLEN);
685 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700686 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 goto fail;
688 }
689
690 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700691 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800692 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
693 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700694 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800695 goto fail;
696 }
697 } else {
698 set = set | WIFI_TDLS_SUPPORT;
699 set = set | (hdd_ctx->config->fTDLSExternalControl ?
700 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
701 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
702 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700703 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800704 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
705 hdd_ctx->max_num_tdls_sta) ||
706 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
707 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700708 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800709 goto fail;
710 }
711 }
712 return cfg80211_vendor_cmd_reply(skb);
713fail:
714 if (skb)
715 kfree_skb(skb);
716 return -EINVAL;
717}
718
719/**
720 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
721 * @wiphy: WIPHY structure pointer
722 * @wdev: Wireless device structure pointer
723 * @data: Pointer to the data received
724 * @data_len: Length of the data received
725 *
726 * This function provides TDLS capabilities
727 *
728 * Return: 0 on success and errno on failure
729 */
730static int
731wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
732 struct wireless_dev *wdev,
733 const void *data,
734 int data_len)
735{
736 int ret;
737
738 cds_ssr_protect(__func__);
739 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
740 data, data_len);
741 cds_ssr_unprotect(__func__);
742
743 return ret;
744}
745#endif
746
747#ifdef QCA_HT_2040_COEX
748static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
749#endif
750
751#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
752/*
753 * FUNCTION: wlan_hdd_send_avoid_freq_event
754 * This is called when wlan driver needs to send vendor specific
755 * avoid frequency range event to userspace
756 */
757int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
758 tHddAvoidFreqList *pAvoidFreqList)
759{
760 struct sk_buff *vendor_event;
761
762 ENTER();
763
764 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700765 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800766 return -EINVAL;
767 }
768
769 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700770 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800771 return -EINVAL;
772 }
773
774 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
775 NULL,
776 sizeof(tHddAvoidFreqList),
777 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
778 GFP_KERNEL);
779 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700780 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800781 return -EINVAL;
782 }
783
784 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
785 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
786
787 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
788
789 EXIT();
790 return 0;
791}
792#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
793
794/* vendor specific events */
795static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
796#ifdef FEATURE_WLAN_CH_AVOID
797 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
798 .vendor_id =
799 QCA_NL80211_VENDOR_ID,
800 .subcmd =
801 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
802 },
803#endif /* FEATURE_WLAN_CH_AVOID */
804
805#ifdef WLAN_FEATURE_NAN
806 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
807 .vendor_id =
808 QCA_NL80211_VENDOR_ID,
809 .subcmd =
810 QCA_NL80211_VENDOR_SUBCMD_NAN
811 },
812#endif
813
814#ifdef WLAN_FEATURE_STATS_EXT
815 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
816 .vendor_id =
817 QCA_NL80211_VENDOR_ID,
818 .subcmd =
819 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
820 },
821#endif /* WLAN_FEATURE_STATS_EXT */
822#ifdef FEATURE_WLAN_EXTSCAN
823 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
824 .vendor_id =
825 QCA_NL80211_VENDOR_ID,
826 .subcmd =
827 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
828 },
829 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
830 .vendor_id =
831 QCA_NL80211_VENDOR_ID,
832 .subcmd =
833 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
834 },
835 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
836 .
837 vendor_id
838 =
839 QCA_NL80211_VENDOR_ID,
840 .subcmd =
841 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
842 },
843 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
844 .
845 vendor_id
846 =
847 QCA_NL80211_VENDOR_ID,
848 .
849 subcmd =
850 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
851 },
852 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
853 .
854 vendor_id
855 =
856 QCA_NL80211_VENDOR_ID,
857 .
858 subcmd
859 =
860 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
861 },
862 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
863 .
864 vendor_id
865 =
866 QCA_NL80211_VENDOR_ID,
867 .subcmd =
868 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
869 },
870 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
871 .vendor_id =
872 QCA_NL80211_VENDOR_ID,
873 .subcmd =
874 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
875 },
876 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
877 .
878 vendor_id
879 =
880 QCA_NL80211_VENDOR_ID,
881 .subcmd =
882 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
883 },
884 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
885 .
886 vendor_id
887 =
888 QCA_NL80211_VENDOR_ID,
889 .subcmd =
890 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
891 },
892 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
893 .
894 vendor_id
895 =
896 QCA_NL80211_VENDOR_ID,
897 .
898 subcmd
899 =
900 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
901 },
902 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
903 .
904 vendor_id
905 =
906 QCA_NL80211_VENDOR_ID,
907 .
908 subcmd =
909 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
910 },
911 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
912 .
913 vendor_id
914 =
915 QCA_NL80211_VENDOR_ID,
916 .
917 subcmd
918 =
919 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
920 },
921 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
922 .
923 vendor_id
924 =
925 QCA_NL80211_VENDOR_ID,
926 .
927 subcmd
928 =
929 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
930 },
931 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
932 .vendor_id = QCA_NL80211_VENDOR_ID,
933 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
934 },
935 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
936 .vendor_id = QCA_NL80211_VENDOR_ID,
937 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
938 },
939#endif /* FEATURE_WLAN_EXTSCAN */
940
941#ifdef WLAN_FEATURE_LINK_LAYER_STATS
942 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
943 .vendor_id =
944 QCA_NL80211_VENDOR_ID,
945 .subcmd =
946 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
947 },
948 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
949 .vendor_id =
950 QCA_NL80211_VENDOR_ID,
951 .subcmd =
952 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
953 },
954 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
955 .vendor_id =
956 QCA_NL80211_VENDOR_ID,
957 .subcmd =
958 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
959 },
960 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
961 .vendor_id =
962 QCA_NL80211_VENDOR_ID,
963 .subcmd =
964 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
965 },
966 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
967 .vendor_id =
968 QCA_NL80211_VENDOR_ID,
969 .subcmd =
970 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
971 },
972 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
973 .vendor_id =
974 QCA_NL80211_VENDOR_ID,
975 .subcmd =
976 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
977 },
978#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
979 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
980 .vendor_id =
981 QCA_NL80211_VENDOR_ID,
982 .subcmd =
983 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
984 },
985 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
986 .vendor_id = QCA_NL80211_VENDOR_ID,
987 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
988 },
989#ifdef WLAN_FEATURE_ROAM_OFFLOAD
990 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
991 .vendor_id =
992 QCA_NL80211_VENDOR_ID,
993 .subcmd =
994 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
995 },
996#endif
997 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
998 .vendor_id =
999 QCA_NL80211_VENDOR_ID,
1000 .subcmd =
1001 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1002 },
1003 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1004 .vendor_id =
1005 QCA_NL80211_VENDOR_ID,
1006 .subcmd =
1007 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1008 },
1009 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1010 .vendor_id =
1011 QCA_NL80211_VENDOR_ID,
1012 .subcmd =
1013 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1014 },
1015 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1016 .vendor_id =
1017 QCA_NL80211_VENDOR_ID,
1018 .subcmd =
1019 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1020 },
1021 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1022 .vendor_id =
1023 QCA_NL80211_VENDOR_ID,
1024 .subcmd =
1025 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1026 },
1027#ifdef FEATURE_WLAN_EXTSCAN
1028 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1029 .vendor_id = QCA_NL80211_VENDOR_ID,
1030 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1031 },
1032 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1033 .vendor_id = QCA_NL80211_VENDOR_ID,
1034 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1035 },
1036 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1037 .vendor_id = QCA_NL80211_VENDOR_ID,
1038 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1039 },
1040 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1041 .vendor_id = QCA_NL80211_VENDOR_ID,
1042 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1043 },
1044 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1045 .vendor_id = QCA_NL80211_VENDOR_ID,
1046 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1047 },
1048#endif /* FEATURE_WLAN_EXTSCAN */
1049 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1050 .vendor_id = QCA_NL80211_VENDOR_ID,
1051 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1052 },
1053#ifdef WLAN_FEATURE_MEMDUMP
1054 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1055 .vendor_id = QCA_NL80211_VENDOR_ID,
1056 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1057 },
1058#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001059#ifdef WLAN_FEATURE_TSF
1060 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1061 .vendor_id = QCA_NL80211_VENDOR_ID,
1062 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1063 },
1064#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001065 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1066 .vendor_id = QCA_NL80211_VENDOR_ID,
1067 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1068 },
1069 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1070 .vendor_id = QCA_NL80211_VENDOR_ID,
1071 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1072 },
1073 /* OCB events */
1074 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1075 .vendor_id = QCA_NL80211_VENDOR_ID,
1076 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1077 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001078#ifdef FEATURE_LFR_SUBNET_DETECTION
1079 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1080 .vendor_id = QCA_NL80211_VENDOR_ID,
1081 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1082 },
1083#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001084
1085#ifdef WLAN_FEATURE_NAN_DATAPATH
1086 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1087 .vendor_id = QCA_NL80211_VENDOR_ID,
1088 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1089 },
1090#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001091
1092 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1093 .vendor_id = QCA_NL80211_VENDOR_ID,
1094 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1095 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301096 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1097 .vendor_id = QCA_NL80211_VENDOR_ID,
1098 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1099 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001100};
1101
1102/**
1103 * __is_driver_dfs_capable() - get driver DFS capability
1104 * @wiphy: pointer to wireless wiphy structure.
1105 * @wdev: pointer to wireless_dev structure.
1106 * @data: Pointer to the data to be passed via vendor interface
1107 * @data_len:Length of the data to be passed
1108 *
1109 * This function is called by userspace to indicate whether or not
1110 * the driver supports DFS offload.
1111 *
1112 * Return: 0 on success, negative errno on failure
1113 */
1114static int __is_driver_dfs_capable(struct wiphy *wiphy,
1115 struct wireless_dev *wdev,
1116 const void *data,
1117 int data_len)
1118{
1119 u32 dfs_capability = 0;
1120 struct sk_buff *temp_skbuff;
1121 int ret_val;
1122 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1123
Jeff Johnson1f61b612016-02-12 16:28:33 -08001124 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001125
1126 ret_val = wlan_hdd_validate_context(hdd_ctx);
1127 if (ret_val)
1128 return ret_val;
1129
Anurag Chouhan6d760662016-02-20 16:05:43 +05301130 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001131 hdd_err("Command not allowed in FTM mode");
1132 return -EPERM;
1133 }
1134
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001135 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136
1137 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1138 NLMSG_HDRLEN);
1139
1140 if (temp_skbuff != NULL) {
1141 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1142 dfs_capability);
1143 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001144 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001145 kfree_skb(temp_skbuff);
1146
1147 return ret_val;
1148 }
1149
1150 return cfg80211_vendor_cmd_reply(temp_skbuff);
1151 }
1152
Jeff Johnson020db452016-06-29 14:37:26 -07001153 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154 return -ENOMEM;
1155}
1156
1157/**
1158 * is_driver_dfs_capable() - get driver DFS capability
1159 * @wiphy: pointer to wireless wiphy structure.
1160 * @wdev: pointer to wireless_dev structure.
1161 * @data: Pointer to the data to be passed via vendor interface
1162 * @data_len:Length of the data to be passed
1163 *
1164 * This function is called by userspace to indicate whether or not
1165 * the driver supports DFS offload. This is an SSR-protected
1166 * wrapper function.
1167 *
1168 * Return: 0 on success, negative errno on failure
1169 */
1170static int is_driver_dfs_capable(struct wiphy *wiphy,
1171 struct wireless_dev *wdev,
1172 const void *data,
1173 int data_len)
1174{
1175 int ret;
1176
1177 cds_ssr_protect(__func__);
1178 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1179 cds_ssr_unprotect(__func__);
1180
1181 return ret;
1182}
1183
1184/**
1185 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1186 *
1187 * @adapter: SAP adapter pointer
1188 *
1189 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1190 * radio. So in case of DFS MCC scenario override current SAP given config
1191 * to follow concurrent SAP DFS config
1192 *
1193 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1194 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001195int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1196{
1197 hdd_adapter_t *con_sap_adapter;
1198 tsap_Config_t *sap_config, *con_sap_config;
1199 int con_ch;
1200
1201 /*
1202 * Check if AP+AP case, once primary AP chooses a DFS
1203 * channel secondary AP should always follow primary APs channel
1204 */
1205 if (!cds_concurrent_beaconing_sessions_running())
1206 return 0;
1207
1208 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1209 if (!con_sap_adapter)
1210 return 0;
1211
1212 sap_config = &adapter->sessionCtx.ap.sapConfig;
1213 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1214 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1215
1216 if (!CDS_IS_DFS_CH(con_ch))
1217 return 0;
1218
Jeff Johnson020db452016-06-29 14:37:26 -07001219 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001220 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001221 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001222 sap_config->channel = con_ch;
1223
1224 if (con_sap_config->acs_cfg.acs_mode == true) {
1225 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1226 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001227 hdd_err("Primary AP channel config error");
1228 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001229 con_ch, con_sap_config->acs_cfg.pri_ch,
1230 con_sap_config->acs_cfg.ht_sec_ch);
1231 return -EINVAL;
1232 }
1233 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1234 * MCC restriction. So free ch list allocated in do_acs
1235 * func for Sec AP and realloc for Pri AP ch list size
1236 */
1237 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301238 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301240 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001241 &con_sap_config->acs_cfg,
1242 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301243 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001244 sizeof(uint8_t) *
1245 con_sap_config->acs_cfg.ch_list_count);
1246 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001247 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248 return -ENOMEM;
1249 }
1250
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301251 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001252 con_sap_config->acs_cfg.ch_list,
1253 con_sap_config->acs_cfg.ch_list_count);
1254
1255 } else {
1256 sap_config->acs_cfg.pri_ch = con_ch;
1257 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1258 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1259 }
1260
1261 return con_ch;
1262}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001263
1264/**
1265 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1266 * @sap_cfg: pointer to SAP config struct
1267 *
1268 * This function sets the default ACS start and end channel for the given band
1269 * and also parses the given ACS channel list.
1270 *
1271 * Return: None
1272 */
1273
1274static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1275 bool vht_enabled)
1276{
1277 int i;
1278 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1279 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001280 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1281 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1283 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001284 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1285 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001286 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1287 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001288 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1289 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001290 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1291 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001292 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1293 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001294 }
1295
1296 if (ht_enabled)
1297 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1298
1299 if (vht_enabled)
1300 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1301
1302
1303 /* Parse ACS Chan list from hostapd */
1304 if (!sap_cfg->acs_cfg.ch_list)
1305 return;
1306
1307 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1308 sap_cfg->acs_cfg.end_ch =
1309 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1310 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301311 /* avoid channel as start channel */
1312 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1313 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001314 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1315 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1316 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1317 }
1318}
1319
1320
1321static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1322
1323/**
1324 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1325 * @adapter: pointer to SAP adapter struct
1326 *
1327 * This function starts the ACS procedure if there are no
1328 * constraints like MBSSID DFS restrictions.
1329 *
1330 * Return: Status of ACS Start procedure
1331 */
1332
1333static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1334{
1335
1336 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1337 tsap_Config_t *sap_config;
1338 tpWLAN_SAPEventCB acs_event_callback;
1339 int status;
1340
1341 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301342 if (hdd_ctx->acs_policy.acs_channel)
1343 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1344 else
1345 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001346
1347 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1348 if (status < 0) {
1349 return status;
1350 } else {
1351 if (status > 0) {
1352 /*notify hostapd about channel override */
1353 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1354 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1355 return 0;
1356 }
1357 }
1358 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1359 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001360 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361 return -EINVAL;
1362 }
1363
1364 acs_event_callback = hdd_hostapd_sap_event_cb;
1365
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301366 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301367 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001368 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001369 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 acs_event_callback, sap_config, adapter->dev);
1372
1373
1374 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001375 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 return -EINVAL;
1377 }
1378 sap_config->acs_cfg.acs_mode = true;
1379 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1380
1381 return 0;
1382}
1383
1384/**
1385 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1386 * @wiphy: Linux wiphy struct pointer
1387 * @wdev: Linux wireless device struct pointer
1388 * @data: ACS information from hostapd
1389 * @data_len: ACS information length
1390 *
1391 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1392 * and starts ACS procedure.
1393 *
1394 * Return: ACS procedure start status
1395 */
1396
1397static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1398 struct wireless_dev *wdev,
1399 const void *data, int data_len)
1400{
1401 struct net_device *ndev = wdev->netdev;
1402 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1403 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1404 tsap_Config_t *sap_config;
1405 struct sk_buff *temp_skbuff;
1406 int status = -EINVAL, i = 0;
1407 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1408 bool ht_enabled, ht40_enabled, vht_enabled;
1409 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301410 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001411
1412 /* ***Note*** Donot set SME config related to ACS operation here because
1413 * ACS operation is not synchronouse and ACS for Second AP may come when
1414 * ACS operation for first AP is going on. So only do_acs is split to
1415 * seperate start_acs routine. Also SME-PMAC struct that is used to
1416 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1417 * config shall be set only from start_acs.
1418 */
1419
1420 /* nla_policy Policy template. Policy not applied as some attributes are
1421 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1422 *
1423 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1424 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1425 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1426 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1427 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1428 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1429 */
1430
Jeff Johnson1f61b612016-02-12 16:28:33 -08001431 ENTER_DEV(ndev);
1432
Anurag Chouhan6d760662016-02-20 16:05:43 +05301433 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001434 hdd_err("Command not allowed in FTM mode");
1435 return -EPERM;
1436 }
1437
1438 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001439 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001440 return -EPERM;
1441 }
1442
1443 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301444 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001445 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301446
Naveen Rawat64e477e2016-05-20 10:34:56 -07001447 if (cds_is_sub_20_mhz_enabled()) {
1448 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1449 status = -EINVAL;
1450 goto out;
1451 }
1452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001453 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301454 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001455
1456 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1457 NULL);
1458 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001459 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001460 goto out;
1461 }
1462
1463 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001464 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001465 goto out;
1466 }
1467 sap_config->acs_cfg.hw_mode = nla_get_u8(
1468 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1469
1470 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1471 ht_enabled =
1472 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1473 else
1474 ht_enabled = 0;
1475
1476 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1477 ht40_enabled =
1478 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1479 else
1480 ht40_enabled = 0;
1481
1482 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1483 vht_enabled =
1484 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1485 else
1486 vht_enabled = 0;
1487
1488 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1489 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1490 } else {
1491 if (ht_enabled && ht40_enabled)
1492 ch_width = 40;
1493 else
1494 ch_width = 20;
1495 }
1496 if (ch_width == 80)
1497 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1498 else if (ch_width == 40)
1499 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1500 else
1501 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1502
1503 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1504 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1505 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1506 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1507 * since it contains the frequency values of the channels in
1508 * the channel list.
1509 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1510 * is present
1511 */
1512 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1513 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1514 sap_config->acs_cfg.ch_list_count = nla_len(
1515 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1516 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301517 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001518 sizeof(uint8_t) *
1519 sap_config->acs_cfg.ch_list_count);
1520 if (sap_config->acs_cfg.ch_list == NULL)
1521 goto out;
1522
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301523 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001524 sap_config->acs_cfg.ch_list_count);
1525 }
1526 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1527 uint32_t *freq =
1528 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1529 sap_config->acs_cfg.ch_list_count = nla_len(
1530 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1531 sizeof(uint32_t);
1532 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301533 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001534 sap_config->acs_cfg.ch_list_count);
1535 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001536 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001537 status = -ENOMEM;
1538 goto out;
1539 }
1540
1541 /* convert frequency to channel */
1542 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1543 sap_config->acs_cfg.ch_list[i] =
1544 ieee80211_frequency_to_channel(freq[i]);
1545 }
1546 }
1547
1548 hdd_debug("get pcl for DO_ACS vendor command");
1549
1550 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001551 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301552 sap_config->acs_cfg.pcl_channels,
1553 &sap_config->acs_cfg.pcl_ch_count,
1554 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301555 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001556 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001557
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558 /* ACS override for android */
1559 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled) {
Jeff Johnson020db452016-06-29 14:37:26 -07001560 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001561 vht_enabled = 1;
1562 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1563 sap_config->acs_cfg.ch_width =
1564 hdd_ctx->config->vhtChannelWidth;
1565 /* No VHT80 in 2.4G so perform ACS accordingly */
1566 if (sap_config->acs_cfg.end_ch <= 14 &&
1567 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1568 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1569 }
1570
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301571 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1572
Jeff Johnson020db452016-06-29 14:37:26 -07001573 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 -08001574 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1575 ch_width, ht_enabled, vht_enabled,
1576 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1577
1578 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001579 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001580 sap_config->acs_cfg.ch_list_count);
1581 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001582 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001583 }
1584 sap_config->acs_cfg.acs_mode = true;
1585 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001586 /* ***Note*** Completion variable usage is not allowed
1587 * here since ACS scan operation may take max 2.2 sec
1588 * for 5G band:
1589 * 9 Active channel X 40 ms active scan time +
1590 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001591 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1592 * for this long. So we split up the scanning part.
1593 */
1594 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001595 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001596 status = 0;
1597 } else {
1598 status = wlan_hdd_cfg80211_start_acs(adapter);
1599 }
1600
1601out:
1602 if (0 == status) {
1603 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1604 NLMSG_HDRLEN);
1605 if (temp_skbuff != NULL)
1606 return cfg80211_vendor_cmd_reply(temp_skbuff);
1607 }
1608
1609 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1610
1611 return status;
1612}
1613
1614 /**
1615 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1616 * @wiphy: Linux wiphy struct pointer
1617 * @wdev: Linux wireless device struct pointer
1618 * @data: ACS information from hostapd
1619 * @data_len: ACS information len
1620 *
1621 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1622 * and starts ACS procedure.
1623 *
1624 * Return: ACS procedure start status
1625 */
1626
1627static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1628 struct wireless_dev *wdev,
1629 const void *data, int data_len)
1630{
1631 int ret;
1632
1633 cds_ssr_protect(__func__);
1634 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1635 cds_ssr_unprotect(__func__);
1636
1637 return ret;
1638}
1639
1640/**
1641 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1642 * @work: Linux workqueue struct pointer for ACS work
1643 *
1644 * This function starts the ACS procedure which was marked pending when an ACS
1645 * procedure was in progress for a concurrent SAP interface.
1646 *
1647 * Return: None
1648 */
1649
1650static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1651{
1652 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1653 acs_pending_work.work);
1654 wlan_hdd_cfg80211_start_acs(adapter);
1655}
1656
1657/**
1658 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1659 * @adapter: Pointer to SAP adapter struct
1660 * @pri_channel: SAP ACS procedure selected Primary channel
1661 * @sec_channel: SAP ACS procedure selected secondary channel
1662 *
1663 * This is a callback function from SAP module on ACS procedure is completed.
1664 * This function send the ACS selected channel information to hostapd
1665 *
1666 * Return: None
1667 */
1668
1669void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1670{
1671 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1672 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1673 struct sk_buff *vendor_event;
1674 int ret_val;
1675 hdd_adapter_t *con_sap_adapter;
1676 uint16_t ch_width;
1677
1678 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001679 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001680 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1681 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1682 GFP_KERNEL);
1683
1684 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001685 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001686 return;
1687 }
1688
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001689 ret_val = nla_put_u8(vendor_event,
1690 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1691 sap_cfg->acs_cfg.pri_ch);
1692 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001693 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001694 kfree_skb(vendor_event);
1695 return;
1696 }
1697
1698 ret_val = nla_put_u8(vendor_event,
1699 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1700 sap_cfg->acs_cfg.ht_sec_ch);
1701 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001702 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001703 kfree_skb(vendor_event);
1704 return;
1705 }
1706
1707 ret_val = nla_put_u8(vendor_event,
1708 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1709 sap_cfg->acs_cfg.vht_seg0_center_ch);
1710 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001711 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001712 kfree_skb(vendor_event);
1713 return;
1714 }
1715
1716 ret_val = nla_put_u8(vendor_event,
1717 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1718 sap_cfg->acs_cfg.vht_seg1_center_ch);
1719 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001720 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001721 kfree_skb(vendor_event);
1722 return;
1723 }
1724
1725 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1726 ch_width = 80;
1727 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1728 ch_width = 40;
1729 else
1730 ch_width = 20;
1731
1732 ret_val = nla_put_u16(vendor_event,
1733 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1734 ch_width);
1735 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001736 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001737 kfree_skb(vendor_event);
1738 return;
1739 }
1740 if (sap_cfg->acs_cfg.pri_ch > 14)
1741 ret_val = nla_put_u8(vendor_event,
1742 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1743 QCA_ACS_MODE_IEEE80211A);
1744 else
1745 ret_val = nla_put_u8(vendor_event,
1746 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1747 QCA_ACS_MODE_IEEE80211G);
1748
1749 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001750 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001751 kfree_skb(vendor_event);
1752 return;
1753 }
1754
Jeff Johnson46b40792016-06-29 14:03:14 -07001755 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 -08001756 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1757 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1758 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1759
1760 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1761 /* ***Note*** As already mentioned Completion variable usage is not
1762 * allowed here since ACS scan operation may take max 2.2 sec.
1763 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1764 * operation.
1765 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1766 * when Primary AP ACS is complete and secondary AP ACS is started here
1767 * immediately, Primary AP start_bss may come inbetween ACS operation
1768 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1769 * delay. This path and below constraint will be removed on sessionizing
1770 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1771 * As per design constraint user space control application must take
1772 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1773 * this code path. Sec AP hostapd should be started after Primary AP
1774 * start beaconing which can be confirmed by getchannel iwpriv command
1775 */
1776
1777 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1778 if (con_sap_adapter &&
1779 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001780 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1781 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001782 /* Lets give 500ms for OBSS + START_BSS to complete */
1783 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1784 msecs_to_jiffies(500));
1785 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1786 }
1787
1788 return;
1789}
1790
1791static int
1792__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1793 struct wireless_dev *wdev,
1794 const void *data,
1795 int data_len)
1796{
1797 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1798 struct sk_buff *skb = NULL;
1799 uint32_t fset = 0;
1800 int ret;
1801
Jeff Johnson1f61b612016-02-12 16:28:33 -08001802 ENTER_DEV(wdev->netdev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301803
Anurag Chouhan6d760662016-02-20 16:05:43 +05301804 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001805 hdd_err("Command not allowed in FTM mode");
1806 return -EPERM;
1807 }
1808
1809 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301810 if (ret)
1811 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001812
1813 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001814 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001815 fset |= WIFI_FEATURE_INFRA;
1816 }
1817 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001818 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001819 fset |= WIFI_FEATURE_INFRA_5G;
1820 }
1821#ifdef WLAN_FEATURE_P2P
1822 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1823 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001824 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001825 fset |= WIFI_FEATURE_P2P;
1826 }
1827#endif
1828 fset |= WIFI_FEATURE_SOFT_AP;
1829
1830 /* HOTSPOT is a supplicant feature, enable it by default */
1831 fset |= WIFI_FEATURE_HOTSPOT;
1832
1833#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301834 if (pHddCtx->config->extscan_enabled &&
1835 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001836 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001837 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1838 }
1839#endif
1840 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001841 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001842 fset |= WIFI_FEATURE_NAN;
1843 }
1844 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001845 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001846 fset |= WIFI_FEATURE_D2D_RTT;
1847 fset |= WIFI_FEATURE_D2AP_RTT;
1848 }
1849#ifdef FEATURE_WLAN_SCAN_PNO
1850 if (pHddCtx->config->configPNOScanSupport &&
1851 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001852 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001853 fset |= WIFI_FEATURE_PNO;
1854 }
1855#endif
1856 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1857#ifdef FEATURE_WLAN_TDLS
1858 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1859 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001860 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001861 fset |= WIFI_FEATURE_TDLS;
1862 }
1863 if (sme_is_feature_supported_by_fw(TDLS) &&
1864 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1865 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001866 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001867 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1868 }
1869#endif
1870#ifdef WLAN_AP_STA_CONCURRENCY
1871 fset |= WIFI_FEATURE_AP_STA;
1872#endif
1873 fset |= WIFI_FEATURE_RSSI_MONITOR;
1874
1875 if (hdd_link_layer_stats_supported())
1876 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1877
1878 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1879 NLMSG_HDRLEN);
1880 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001881 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001882 return -EINVAL;
1883 }
Jeff Johnson020db452016-06-29 14:37:26 -07001884 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001886 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001887 goto nla_put_failure;
1888 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301889 ret = cfg80211_vendor_cmd_reply(skb);
1890 EXIT();
1891 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 |
2070 WIFI_FEATURE_P2P;
2071 /* Add more feature combinations here */
2072
2073 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
2074 hdd_info("Number of feature sets:%d", feature_sets);
2075 hdd_info("Feature set matrix");
2076 for (i = 0; i < feature_sets; i++)
2077 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2078
2079 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2080 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2081 if (!reply_skb) {
2082 hdd_err("Feature set matrix: buffer alloc fail");
2083 return -ENOMEM;
2084 }
2085
2086 if (nla_put_u32(reply_skb,
2087 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2088 feature_sets) ||
2089 nla_put(reply_skb,
2090 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2091 sizeof(u32) * feature_sets,
2092 feature_set_matrix)) {
2093 hdd_err("nla put fail");
2094 kfree_skb(reply_skb);
2095 return -EINVAL;
2096 }
2097 return cfg80211_vendor_cmd_reply(reply_skb);
2098}
2099
2100/**
2101 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2102 * @wiphy: pointer to wireless wiphy structure.
2103 * @wdev: pointer to wireless_dev structure.
2104 * @data: Pointer to the data to be passed via vendor interface
2105 * @data_len:Length of the data to be passed
2106 *
2107 * Retrieves the concurrency feature set matrix
2108 *
2109 * Return: 0 on success, negative errno on failure
2110 */
2111static int
2112wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2113 struct wireless_dev *wdev,
2114 const void *data,
2115 int data_len)
2116{
2117 int ret;
2118
2119 cds_ssr_protect(__func__);
2120 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2121 data, data_len);
2122 cds_ssr_unprotect(__func__);
2123
2124 return ret;
2125}
2126
2127/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002128 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2129 * @feature_flags: pointer to the byte array of features.
2130 * @feature: Feature to be turned ON in the byte array.
2131 *
2132 * Return: None
2133 *
2134 * This is called to turn ON or SET the feature flag for the requested feature.
2135 **/
2136#define NUM_BITS_IN_BYTE 8
2137void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags, uint8_t feature)
2138{
2139 uint32_t index;
2140 uint8_t bit_mask;
2141
2142 index = feature / NUM_BITS_IN_BYTE;
2143 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2144 feature_flags[index] |= bit_mask;
2145}
2146
2147/**
2148 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2149 * @wiphy: pointer to wireless wiphy structure.
2150 * @wdev: pointer to wireless_dev structure.
2151 * @data: Pointer to the data to be passed via vendor interface
2152 * @data_len:Length of the data to be passed
2153 *
2154 * This is called when wlan driver needs to send supported feature set to
2155 * supplicant upon a request/query from the supplicant.
2156 *
2157 * Return: Return the Success or Failure code.
2158 **/
2159#define MAX_CONCURRENT_CHAN_ON_24G 2
2160#define MAX_CONCURRENT_CHAN_ON_5G 2
2161static int
2162__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2163 struct wireless_dev *wdev,
2164 const void *data, int data_len)
2165{
2166 struct sk_buff *skb = NULL;
2167 uint32_t dbs_capability = 0;
2168 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302169 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002170 int ret_val;
2171
2172 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2173 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2174
Jeff Johnson1f61b612016-02-12 16:28:33 -08002175 ENTER_DEV(wdev->netdev);
2176
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002177 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2178 if (ret_val)
2179 return ret_val;
2180
Anurag Chouhan6d760662016-02-20 16:05:43 +05302181 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002182 hdd_err("Command not allowed in FTM mode");
2183 return -EPERM;
2184 }
2185
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002186 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002187 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002188 wlan_hdd_cfg80211_set_feature(feature_flags,
2189 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2190 }
2191
2192 wlan_hdd_cfg80211_set_feature(feature_flags,
2193 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2194 if (wma_is_scan_simultaneous_capable())
2195 wlan_hdd_cfg80211_set_feature(feature_flags,
2196 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002197
2198 if (wma_is_p2p_lo_capable())
2199 wlan_hdd_cfg80211_set_feature(feature_flags,
2200 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2201
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002202 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2203 NLMSG_HDRLEN);
2204
2205 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002206 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002207 return -ENOMEM;
2208 }
2209
2210 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2211 sizeof(feature_flags), feature_flags))
2212 goto nla_put_failure;
2213
2214 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302215 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002216 if (one_by_one_dbs)
2217 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2218
2219 if (two_by_two_dbs)
2220 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2221
2222 if (!one_by_one_dbs && !two_by_two_dbs)
2223 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2224 } else {
2225 hdd_err("wma_get_dbs_hw_mode failed");
2226 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2227 }
2228
2229 hdd_info("dbs_capability is %d", dbs_capability);
2230
2231 if (nla_put_u32(skb,
2232 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2233 MAX_CONCURRENT_CHAN_ON_24G))
2234 goto nla_put_failure;
2235
2236 if (nla_put_u32(skb,
2237 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2238 MAX_CONCURRENT_CHAN_ON_5G))
2239 goto nla_put_failure;
2240
2241 return cfg80211_vendor_cmd_reply(skb);
2242
2243nla_put_failure:
2244 kfree_skb(skb);
2245 return -EINVAL;
2246}
2247
2248/**
2249 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2250 * @wiphy: pointer to wireless wiphy structure.
2251 * @wdev: pointer to wireless_dev structure.
2252 * @data: Pointer to the data to be passed via vendor interface
2253 * @data_len:Length of the data to be passed
2254 *
2255 * This is called when wlan driver needs to send supported feature set to
2256 * supplicant upon a request/query from the supplicant.
2257 *
2258 * Return: Return the Success or Failure code.
2259 */
2260static int
2261wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2262 struct wireless_dev *wdev,
2263 const void *data, int data_len)
2264{
2265 int ret;
2266
2267 cds_ssr_protect(__func__);
2268 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2269 data, data_len);
2270 cds_ssr_unprotect(__func__);
2271
2272 return ret;
2273}
2274
2275
2276/**
2277 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2278 * @wiphy: The wiphy structure
2279 * @wdev: The wireless device
2280 * @data: Data passed by framework
2281 * @data_len: Parameters to be configured passed as data
2282 *
2283 * The roaming related parameters are configured by the framework
2284 * using this interface.
2285 *
2286 * Return: Return either success or failure code.
2287 */
2288static int
2289__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2290 struct wireless_dev *wdev, const void *data, int data_len)
2291{
2292 struct net_device *dev = wdev->netdev;
2293 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2294 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2295 uint8_t session_id;
2296 struct roam_ext_params roam_params;
2297 uint32_t cmd_type, req_id;
2298 struct nlattr *curr_attr;
2299 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2300 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2301 int rem, i;
2302 uint32_t buf_len = 0;
2303 int ret;
2304
Jeff Johnson1f61b612016-02-12 16:28:33 -08002305 ENTER_DEV(dev);
2306
Anurag Chouhan6d760662016-02-20 16:05:43 +05302307 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002308 hdd_err("Command not allowed in FTM mode");
2309 return -EPERM;
2310 }
2311
2312 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302313 if (ret)
2314 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002315
2316 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2317 data, data_len,
2318 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002319 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002320 return -EINVAL;
2321 }
2322 /* Parse and fetch Command Type*/
2323 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002324 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002325 goto fail;
2326 }
2327 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302328 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002329 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2330 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002331 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002332 goto fail;
2333 }
2334 req_id = nla_get_u32(
2335 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002336 hdd_debug("Req Id (%d)", req_id);
2337 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002338 switch (cmd_type) {
2339 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2340 i = 0;
2341 nla_for_each_nested(curr_attr,
2342 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2343 rem) {
2344 if (nla_parse(tb2,
2345 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2346 nla_data(curr_attr), nla_len(curr_attr),
2347 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002348 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002349 goto fail;
2350 }
2351 /* Parse and Fetch allowed SSID list*/
2352 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002353 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002354 goto fail;
2355 }
2356 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2357 /*
2358 * Upper Layers include a null termination character.
2359 * Check for the actual permissible length of SSID and
2360 * also ensure not to copy the NULL termination
2361 * character to the driver buffer.
2362 */
2363 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2364 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2365 nla_memcpy(
2366 roam_params.ssid_allowed_list[i].ssId,
2367 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2368 buf_len - 1);
2369 roam_params.ssid_allowed_list[i].length =
2370 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002371 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002372 roam_params.ssid_allowed_list[i].length,
2373 roam_params.ssid_allowed_list[i].ssId,
2374 roam_params.ssid_allowed_list[i].length);
2375 i++;
2376 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002377 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 }
2379 }
2380 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002381 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382 roam_params.num_ssid_allowed_list);
2383 sme_update_roam_params(pHddCtx->hHal, session_id,
2384 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2385 break;
2386 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2387 /* Parse and fetch 5G Boost Threshold */
2388 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002389 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002390 goto fail;
2391 }
2392 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2393 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002394 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002395 roam_params.raise_rssi_thresh_5g);
2396 /* Parse and fetch 5G Penalty Threshold */
2397 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002398 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002399 goto fail;
2400 }
2401 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2402 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002403 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002404 roam_params.drop_rssi_thresh_5g);
2405 /* Parse and fetch 5G Boost Factor */
2406 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002407 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002408 goto fail;
2409 }
2410 roam_params.raise_factor_5g = nla_get_u32(
2411 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002412 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002413 roam_params.raise_factor_5g);
2414 /* Parse and fetch 5G Penalty factor */
2415 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002416 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002417 goto fail;
2418 }
2419 roam_params.drop_factor_5g = nla_get_u32(
2420 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002421 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002422 roam_params.drop_factor_5g);
2423 /* Parse and fetch 5G Max Boost */
2424 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002425 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002426 goto fail;
2427 }
2428 roam_params.max_raise_rssi_5g = nla_get_u32(
2429 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002430 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002431 roam_params.max_raise_rssi_5g);
2432 /* Parse and fetch Rssi Diff */
2433 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002434 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435 goto fail;
2436 }
2437 roam_params.rssi_diff = nla_get_s32(
2438 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002439 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440 roam_params.rssi_diff);
2441 /* Parse and fetch Alert Rssi Threshold */
2442 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002443 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002444 goto fail;
2445 }
2446 roam_params.alert_rssi_threshold = nla_get_u32(
2447 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002448 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449 roam_params.alert_rssi_threshold);
2450 sme_update_roam_params(pHddCtx->hHal, session_id,
2451 roam_params,
2452 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2453 break;
2454 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2455 /* Parse and fetch Activate Good Rssi Roam */
2456 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002457 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458 goto fail;
2459 }
2460 roam_params.good_rssi_roam = nla_get_s32(
2461 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002462 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 roam_params.good_rssi_roam);
2464 sme_update_roam_params(pHddCtx->hHal, session_id,
2465 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2466 break;
2467 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2468 /* Parse and fetch number of preferred BSSID */
2469 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002470 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002471 goto fail;
2472 }
2473 roam_params.num_bssid_favored = nla_get_u32(
2474 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002475 hdd_debug("Num of Preferred BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476 roam_params.num_bssid_favored);
2477 i = 0;
2478 nla_for_each_nested(curr_attr,
2479 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2480 rem) {
2481 if (nla_parse(tb2,
2482 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2483 nla_data(curr_attr), nla_len(curr_attr),
2484 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002485 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002486 goto fail;
2487 }
2488 /* Parse and fetch MAC address */
2489 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002490 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002491 goto fail;
2492 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002493 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002494 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302495 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002496 hdd_debug(MAC_ADDRESS_STR,
2497 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002498 /* Parse and fetch preference factor*/
2499 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002500 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002501 goto fail;
2502 }
2503 roam_params.bssid_favored_factor[i] = nla_get_u32(
2504 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002505 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002506 roam_params.bssid_favored_factor[i]);
2507 i++;
2508 }
2509 sme_update_roam_params(pHddCtx->hHal, session_id,
2510 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2511 break;
2512 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2513 /* Parse and fetch number of blacklist BSSID */
2514 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002515 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002516 goto fail;
2517 }
2518 roam_params.num_bssid_avoid_list = nla_get_u32(
2519 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002520 hdd_debug("Num of blacklist BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002521 roam_params.num_bssid_avoid_list);
2522 i = 0;
2523 nla_for_each_nested(curr_attr,
2524 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2525 rem) {
2526 if (nla_parse(tb2,
2527 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2528 nla_data(curr_attr), nla_len(curr_attr),
2529 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002530 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002531 goto fail;
2532 }
2533 /* Parse and fetch MAC address */
2534 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002535 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536 goto fail;
2537 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002538 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302540 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002541 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002543 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 i++;
2545 }
2546 sme_update_roam_params(pHddCtx->hHal, session_id,
2547 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2548 break;
2549 }
2550 return 0;
2551fail:
2552 return -EINVAL;
2553}
2554
2555/**
2556 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2557 * @wiphy: pointer to wireless wiphy structure.
2558 * @wdev: pointer to wireless_dev structure.
2559 * @data: Pointer to the data to be passed via vendor interface
2560 * @data_len:Length of the data to be passed
2561 *
2562 * Return: Return the Success or Failure code.
2563 */
2564static int
2565wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2566 struct wireless_dev *wdev,
2567 const void *data,
2568 int data_len)
2569{
2570 int ret;
2571
2572 cds_ssr_protect(__func__);
2573 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2574 data, data_len);
2575 cds_ssr_unprotect(__func__);
2576
2577 return ret;
2578}
2579
2580static const struct nla_policy
2581wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2582 +1] = {
2583 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2584};
2585
2586/**
2587 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2588 * @hdd_ctx: HDD context
2589 * @device_mode: device mode
2590 * Return: bool
2591 */
2592static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002593 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002594{
2595 hdd_adapter_t *adapter;
2596 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2597 hdd_ap_ctx_t *ap_ctx;
2598 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302599 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002600
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302601 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002602 &adapter_node);
2603
2604 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302605 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002606 adapter = adapter_node->pAdapter;
2607
2608 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002609 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002610 ap_ctx =
2611 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2612
2613 /*
2614 * if there is SAP already running on DFS channel,
2615 * do not disable scan on dfs channels. Note that
2616 * with SAP on DFS, there cannot be conurrency on
2617 * single radio. But then we can have multiple
2618 * radios !!
2619 */
2620 if (CHANNEL_STATE_DFS ==
2621 cds_get_channel_state(
2622 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002623 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002624 return true;
2625 }
2626 }
2627
2628 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002629 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002630 sta_ctx =
2631 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2632
2633 /*
2634 * if STA is already connected on DFS channel,
2635 * do not disable scan on dfs channels
2636 */
2637 if (hdd_conn_is_connected(sta_ctx) &&
2638 (CHANNEL_STATE_DFS ==
2639 cds_get_channel_state(
2640 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002641 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002642 return true;
2643 }
2644 }
2645
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302646 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002647 adapter_node,
2648 &next);
2649 adapter_node = next;
2650 }
2651
2652 return false;
2653}
2654
2655/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002656 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2657 * @hdd_ctx: HDD context within host driver
2658 * @adapter: Adapter pointer
2659 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2660 *
2661 * Loops through devices to see who is operating on DFS channels
2662 * and then disables/enables DFS channels by calling SME API.
2663 * Fails the disable request if any device is active on a DFS channel.
2664 *
2665 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002666 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002667
2668int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2669 hdd_adapter_t *adapter,
2670 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002672 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302673 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675
2676 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2677 if (no_dfs_flag) {
2678 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002679 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680
2681 if (true == status)
2682 return -EOPNOTSUPP;
2683
2684 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002685 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002686
2687 if (true == status)
2688 return -EOPNOTSUPP;
2689 }
2690
2691 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2692
2693 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2694
2695 /*
2696 * call the SME API to tunnel down the new channel list
2697 * to the firmware
2698 */
2699 status = sme_handle_dfs_chan_scan(
2700 h_hal, hdd_ctx->config->enableDFSChnlScan);
2701
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302702 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703 ret_val = 0;
2704
2705 /*
2706 * Clear the SME scan cache also. Note that the
2707 * clearing of scan results is independent of session;
2708 * so no need to iterate over
2709 * all sessions
2710 */
2711 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302712 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002713 ret_val = -EPERM;
2714 }
2715
2716 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002717 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002718 ret_val = 0;
2719 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002720 return ret_val;
2721}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002722
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002723/**
2724 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2725 * @wiphy: corestack handler
2726 * @wdev: wireless device
2727 * @data: data
2728 * @data_len: data length
2729 * Return: success(0) or reason code for failure
2730 */
2731static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2732 struct wireless_dev *wdev,
2733 const void *data,
2734 int data_len)
2735{
2736 struct net_device *dev = wdev->netdev;
2737 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2738 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2739 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2740 int ret_val;
2741 uint32_t no_dfs_flag = 0;
2742
Jeff Johnson1f61b612016-02-12 16:28:33 -08002743 ENTER_DEV(dev);
2744
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002745 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302746 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002747 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002748
2749 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2750 data, data_len,
2751 wlan_hdd_set_no_dfs_flag_config_policy)) {
2752 hdd_err("invalid attr");
2753 return -EINVAL;
2754 }
2755
2756 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2757 hdd_err("attr dfs flag failed");
2758 return -EINVAL;
2759 }
2760
2761 no_dfs_flag = nla_get_u32(
2762 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2763
Jeff Johnson020db452016-06-29 14:37:26 -07002764 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002765
2766 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002767 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002768 return -EINVAL;
2769 }
2770
2771 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2772 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002773 return ret_val;
2774}
2775
2776/**
2777 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2778 *
2779 * @wiphy: wiphy device pointer
2780 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002781 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002782 * @data_len: Buffer length
2783 *
2784 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2785 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2786 *
2787 * Return: EOK or other error codes.
2788 */
2789
2790static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2791 struct wireless_dev *wdev,
2792 const void *data,
2793 int data_len)
2794{
2795 int ret;
2796
2797 cds_ssr_protect(__func__);
2798 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2799 data, data_len);
2800 cds_ssr_unprotect(__func__);
2801
2802 return ret;
2803}
2804
Manikandan Mohan80dea792016-04-28 16:36:48 -07002805static const struct nla_policy
2806wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2807 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2808};
2809
2810/**
2811 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2812 * @wiphy: wiphy device pointer
2813 * @wdev: wireless device pointer
2814 * @data: Vendor command data buffer
2815 * @data_len: Buffer length
2816 *
2817 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2818 * setup WISA Mode features.
2819 *
2820 * Return: Success(0) or reason code for failure
2821 */
2822static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2823 struct wireless_dev *wdev, const void *data, int data_len)
2824{
2825 struct net_device *dev = wdev->netdev;
2826 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2827 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2828 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2829 struct sir_wisa_params wisa;
2830 int ret_val;
2831 QDF_STATUS status;
2832 bool wisa_mode;
2833
2834 ENTER_DEV(dev);
2835 ret_val = wlan_hdd_validate_context(hdd_ctx);
2836 if (ret_val)
2837 goto err;
2838
2839 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2840 hdd_err("Command not allowed in FTM mode");
2841 return -EPERM;
2842 }
2843
2844 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2845 wlan_hdd_wisa_cmd_policy)) {
2846 hdd_err("Invalid WISA cmd attributes");
2847 ret_val = -EINVAL;
2848 goto err;
2849 }
2850 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2851 hdd_err("Invalid WISA mode");
2852 ret_val = -EINVAL;
2853 goto err;
2854 }
2855
2856 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2857 hdd_info("WISA Mode: %d", wisa_mode);
2858 wisa.mode = wisa_mode;
2859 wisa.vdev_id = adapter->sessionId;
2860 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002861 if (!QDF_IS_STATUS_SUCCESS(status)) {
2862 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002863 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002864 }
2865 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
2866 ol_txrx_set_wisa_mode(ol_txrx_get_vdev_from_vdev_id(
2867 adapter->sessionId), wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002868err:
2869 EXIT();
2870 return ret_val;
2871}
2872
2873/**
2874 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2875 * @wiphy: corestack handler
2876 * @wdev: wireless device
2877 * @data: data
2878 * @data_len: data length
2879 *
2880 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2881 * setup WISA mode features.
2882 *
2883 * Return: Success(0) or reason code for failure
2884 */
2885static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2886 struct wireless_dev *wdev,
2887 const void *data,
2888 int data_len)
2889{
2890 int ret;
2891
2892 cds_ssr_protect(__func__);
2893 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2894 cds_ssr_unprotect(__func__);
2895
2896 return ret;
2897}
2898
Anurag Chouhan96919482016-07-13 16:36:57 +05302899/*
2900 * define short names for the global vendor params
2901 * used by __wlan_hdd_cfg80211_get_station_cmd()
2902 */
2903#define STATION_INVALID \
2904 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2905#define STATION_INFO \
2906 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2907#define STATION_ASSOC_FAIL_REASON \
2908 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2909#define STATION_MAX \
2910 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2911
2912static const struct nla_policy
2913hdd_get_station_policy[STATION_MAX + 1] = {
2914 [STATION_INFO] = {.type = NLA_FLAG},
2915 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2916};
2917
2918/**
2919 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2920 * @hdd_ctx: HDD context within host driver
2921 * @wdev: wireless device
2922 *
2923 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
2924 * Validate cmd attributes and send the station info to upper layers.
2925 *
2926 * Return: Success(0) or reason code for failure
2927 */
2928static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
2929 hdd_adapter_t *adapter)
2930{
2931 struct sk_buff *skb = NULL;
2932 uint32_t nl_buf_len;
2933 hdd_station_ctx_t *hdd_sta_ctx;
2934
2935 nl_buf_len = NLMSG_HDRLEN;
2936 nl_buf_len += sizeof(uint32_t);
2937 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
2938
2939 if (!skb) {
2940 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
2941 return -ENOMEM;
2942 }
2943
2944 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2945
2946 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
2947 hdd_sta_ctx->conn_info.assoc_status_code)) {
2948 hdd_err("put fail");
2949 goto fail;
2950 }
2951 return cfg80211_vendor_cmd_reply(skb);
2952fail:
2953 if (skb)
2954 kfree_skb(skb);
2955 return -EINVAL;
2956}
2957
2958/**
2959 * hdd_map_auth_type() - transform auth type specific to
2960 * vendor command
2961 * @auth_type: csr auth type
2962 *
2963 * Return: Success(0) or reason code for failure
2964 */
2965static int hdd_convert_auth_type(uint32_t auth_type)
2966{
2967 uint32_t ret_val;
2968
2969 switch (auth_type) {
2970 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
2971 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
2972 break;
2973 case eCSR_AUTH_TYPE_SHARED_KEY:
2974 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
2975 break;
2976 case eCSR_AUTH_TYPE_WPA:
2977 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
2978 break;
2979 case eCSR_AUTH_TYPE_WPA_PSK:
2980 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
2981 break;
2982 case eCSR_AUTH_TYPE_AUTOSWITCH:
2983 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
2984 break;
2985 case eCSR_AUTH_TYPE_WPA_NONE:
2986 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
2987 break;
2988 case eCSR_AUTH_TYPE_RSN:
2989 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
2990 break;
2991 case eCSR_AUTH_TYPE_RSN_PSK:
2992 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
2993 break;
2994 case eCSR_AUTH_TYPE_FT_RSN:
2995 ret_val = QCA_WLAN_AUTH_TYPE_FT;
2996 break;
2997 case eCSR_AUTH_TYPE_FT_RSN_PSK:
2998 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
2999 break;
3000 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3001 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3002 break;
3003 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3004 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3005 break;
3006 case eCSR_AUTH_TYPE_CCKM_WPA:
3007 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3008 break;
3009 case eCSR_AUTH_TYPE_CCKM_RSN:
3010 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3011 break;
3012 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3013 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3014 break;
3015 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3016 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3017 break;
3018 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3019 case eCSR_AUTH_TYPE_FAILED:
3020 case eCSR_AUTH_TYPE_NONE:
3021 default:
3022 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3023 break;
3024 }
3025 return ret_val;
3026}
3027
3028/**
3029 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3030 * vendor command
3031 * @dot11mode: dot11mode
3032 *
3033 * Return: Success(0) or reason code for failure
3034 */
3035static int hdd_convert_dot11mode(uint32_t dot11mode)
3036{
3037 uint32_t ret_val;
3038
3039 switch (dot11mode) {
3040 case eCSR_CFG_DOT11_MODE_11A:
3041 ret_val = QCA_WLAN_802_11_MODE_11A;
3042 break;
3043 case eCSR_CFG_DOT11_MODE_11B:
3044 ret_val = QCA_WLAN_802_11_MODE_11B;
3045 break;
3046 case eCSR_CFG_DOT11_MODE_11G:
3047 ret_val = QCA_WLAN_802_11_MODE_11G;
3048 break;
3049 case eCSR_CFG_DOT11_MODE_11N:
3050 ret_val = QCA_WLAN_802_11_MODE_11N;
3051 break;
3052 case eCSR_CFG_DOT11_MODE_11AC:
3053 ret_val = QCA_WLAN_802_11_MODE_11AC;
3054 break;
3055 case eCSR_CFG_DOT11_MODE_AUTO:
3056 case eCSR_CFG_DOT11_MODE_ABG:
3057 default:
3058 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3059 }
3060 return ret_val;
3061}
3062
3063/**
3064 * hdd_add_tx_bitrate() - add tx bitrate attribute
3065 * @skb: pointer to sk buff
3066 * @hdd_sta_ctx: pointer to hdd station context
3067 * @idx: attribute index
3068 *
3069 * Return: Success(0) or reason code for failure
3070 */
3071static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3072 hdd_station_ctx_t *hdd_sta_ctx,
3073 int idx)
3074{
3075 struct nlattr *nla_attr;
3076 uint32_t bitrate, bitrate_compat;
3077
3078 nla_attr = nla_nest_start(skb, idx);
3079 if (!nla_attr)
3080 goto fail;
3081 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3082 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3083
3084 /* report 16-bit bitrate only if we can */
3085 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3086 if (bitrate > 0 &&
3087 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3088 hdd_err("put fail");
3089 goto fail;
3090 }
3091 if (bitrate_compat > 0 &&
3092 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3093 hdd_err("put fail");
3094 goto fail;
3095 }
3096 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3097 hdd_sta_ctx->conn_info.txrate.nss)) {
3098 hdd_err("put fail");
3099 goto fail;
3100 }
3101 nla_nest_end(skb, nla_attr);
3102 return 0;
3103fail:
3104 return -EINVAL;
3105}
3106
3107/**
3108 * hdd_add_sta_info() - add station info attribute
3109 * @skb: pointer to sk buff
3110 * @hdd_sta_ctx: pointer to hdd station context
3111 * @idx: attribute index
3112 *
3113 * Return: Success(0) or reason code for failure
3114 */
3115static int32_t hdd_add_sta_info(struct sk_buff *skb,
3116 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3117{
3118 struct nlattr *nla_attr;
3119
3120 nla_attr = nla_nest_start(skb, idx);
3121 if (!nla_attr)
3122 goto fail;
3123 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3124 (hdd_sta_ctx->conn_info.signal + 100))) {
3125 hdd_err("put fail");
3126 goto fail;
3127 }
3128 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3129 goto fail;
3130 nla_nest_end(skb, nla_attr);
3131 return 0;
3132fail:
3133 return -EINVAL;
3134}
3135
3136/**
3137 * hdd_add_survey_info() - add survey info attribute
3138 * @skb: pointer to sk buff
3139 * @hdd_sta_ctx: pointer to hdd station context
3140 * @idx: attribute index
3141 *
3142 * Return: Success(0) or reason code for failure
3143 */
3144static int32_t hdd_add_survey_info(struct sk_buff *skb,
3145 hdd_station_ctx_t *hdd_sta_ctx,
3146 int idx)
3147{
3148 struct nlattr *nla_attr;
3149
3150 nla_attr = nla_nest_start(skb, idx);
3151 if (!nla_attr)
3152 goto fail;
3153 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3154 hdd_sta_ctx->conn_info.freq) ||
3155 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3156 (hdd_sta_ctx->conn_info.noise + 100))) {
3157 hdd_err("put fail");
3158 goto fail;
3159 }
3160 nla_nest_end(skb, nla_attr);
3161 return 0;
3162fail:
3163 return -EINVAL;
3164}
3165
3166/**
3167 * hdd_add_link_standard_info() - add link info attribute
3168 * @skb: pointer to sk buff
3169 * @hdd_sta_ctx: pointer to hdd station context
3170 * @idx: attribute index
3171 *
3172 * Return: Success(0) or reason code for failure
3173 */
3174static int32_t
3175hdd_add_link_standard_info(struct sk_buff *skb,
3176 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3177{
3178 struct nlattr *nla_attr;
3179
3180 nla_attr = nla_nest_start(skb, idx);
3181 if (!nla_attr)
3182 goto fail;
3183 if (nla_put(skb,
3184 NL80211_ATTR_SSID,
3185 hdd_sta_ctx->conn_info.SSID.SSID.length,
3186 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3187 hdd_err("put fail");
3188 goto fail;
3189 }
3190 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3191 goto fail;
3192 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3193 goto fail;
3194 nla_nest_end(skb, nla_attr);
3195 return 0;
3196fail:
3197 return -EINVAL;
3198}
3199
3200/**
3201 * hdd_add_ap_standard_info() - add ap info attribute
3202 * @skb: pointer to sk buff
3203 * @hdd_sta_ctx: pointer to hdd station context
3204 * @idx: attribute index
3205 *
3206 * Return: Success(0) or reason code for failure
3207 */
3208static int32_t
3209hdd_add_ap_standard_info(struct sk_buff *skb,
3210 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3211{
3212 struct nlattr *nla_attr;
3213
3214 nla_attr = nla_nest_start(skb, idx);
3215 if (!nla_attr)
3216 goto fail;
3217 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3218 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3219 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3220 &hdd_sta_ctx->conn_info.vht_caps)) {
3221 hdd_err("put fail");
3222 goto fail;
3223 }
3224 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3225 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3226 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3227 &hdd_sta_ctx->conn_info.ht_caps)) {
3228 hdd_err("put fail");
3229 goto fail;
3230 }
3231 nla_nest_end(skb, nla_attr);
3232 return 0;
3233fail:
3234 return -EINVAL;
3235}
3236
3237/**
3238 * hdd_get_station_info() - send BSS information to supplicant
3239 * @hdd_ctx: pointer to hdd context
3240 * @adapter: pointer to adapter
3241 *
3242 * Return: 0 if success else error status
3243 */
3244static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3245 hdd_adapter_t *adapter)
3246{
3247 struct sk_buff *skb = NULL;
3248 uint8_t *tmp_hs20 = NULL;
3249 uint32_t nl_buf_len;
3250 hdd_station_ctx_t *hdd_sta_ctx;
3251
3252 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3253
3254 nl_buf_len = NLMSG_HDRLEN;
3255 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3256 sizeof(hdd_sta_ctx->conn_info.freq) +
3257 sizeof(hdd_sta_ctx->conn_info.noise) +
3258 sizeof(hdd_sta_ctx->conn_info.signal) +
3259 (sizeof(uint32_t) * 2) +
3260 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3261 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3262 sizeof(hdd_sta_ctx->conn_info.authType) +
3263 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3264 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3265 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3266 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3267 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3268 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3269 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3270 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3271 1);
3272 }
3273 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3274 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3275 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3276 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3277
3278
3279 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3280 if (!skb) {
3281 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3282 return -ENOMEM;
3283 }
3284
3285 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3286 LINK_INFO_STANDARD_NL80211_ATTR)) {
3287 hdd_err("put fail");
3288 goto fail;
3289 }
3290 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3291 AP_INFO_STANDARD_NL80211_ATTR)) {
3292 hdd_err("put fail");
3293 goto fail;
3294 }
3295 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3296 hdd_sta_ctx->conn_info.roam_count) ||
3297 nla_put_u32(skb, INFO_AKM,
3298 hdd_convert_auth_type(
3299 hdd_sta_ctx->conn_info.authType)) ||
3300 nla_put_u32(skb, WLAN802_11_MODE,
3301 hdd_convert_dot11mode(
3302 hdd_sta_ctx->conn_info.dot11Mode))) {
3303 hdd_err("put fail");
3304 goto fail;
3305 }
3306 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3307 if (nla_put(skb, HT_OPERATION,
3308 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3309 &hdd_sta_ctx->conn_info.ht_operation)) {
3310 hdd_err("put fail");
3311 goto fail;
3312 }
3313 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3314 if (nla_put(skb, VHT_OPERATION,
3315 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3316 &hdd_sta_ctx->conn_info.vht_operation)) {
3317 hdd_err("put fail");
3318 goto fail;
3319 }
3320 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3321 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3322 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3323 tmp_hs20 + 1)) {
3324 hdd_err("put fail");
3325 goto fail;
3326 }
3327
3328 return cfg80211_vendor_cmd_reply(skb);
3329fail:
3330 if (skb)
3331 kfree_skb(skb);
3332 return -EINVAL;
3333}
3334
3335/**
3336 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3337 * @wiphy: corestack handler
3338 * @wdev: wireless device
3339 * @data: data
3340 * @data_len: data length
3341 *
3342 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3343 * Validate cmd attributes and send the station info to upper layers.
3344 *
3345 * Return: Success(0) or reason code for failure
3346 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303347static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303348__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3349 struct wireless_dev *wdev,
3350 const void *data,
3351 int data_len)
3352{
3353 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3354 struct net_device *dev = wdev->netdev;
3355 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3356 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3357 int32_t status;
3358
3359 ENTER_DEV(dev);
3360 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3361 hdd_err("Command not allowed in FTM mode");
3362 status = -EPERM;
3363 goto out;
3364 }
3365
3366 status = wlan_hdd_validate_context(hdd_ctx);
3367 if (0 != status)
3368 goto out;
3369
3370
3371 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3372 data, data_len, NULL);
3373 if (status) {
3374 hdd_err("Invalid ATTR");
3375 goto out;
3376 }
3377
3378 /* Parse and fetch Command Type*/
3379 if (tb[STATION_INFO]) {
3380 status = hdd_get_station_info(hdd_ctx, adapter);
3381 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3382 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3383 } else {
3384 hdd_err("get station info cmd type failed");
3385 status = -EINVAL;
3386 goto out;
3387 }
3388 EXIT();
3389out:
3390 return status;
3391}
3392
3393/**
3394 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3395 * @wiphy: corestack handler
3396 * @wdev: wireless device
3397 * @data: data
3398 * @data_len: data length
3399 *
3400 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3401 * Validate cmd attributes and send the station info to upper layers.
3402 *
3403 * Return: Success(0) or reason code for failure
3404 */
3405static int32_t
3406hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3407 struct wireless_dev *wdev,
3408 const void *data,
3409 int data_len)
3410{
3411 int ret;
3412
3413 cds_ssr_protect(__func__);
3414 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3415 cds_ssr_unprotect(__func__);
3416
3417 return ret;
3418}
3419
3420/*
3421 * undef short names defined for get station command
3422 * used by __wlan_hdd_cfg80211_get_station_cmd()
3423 */
3424#undef STATION_INVALID
3425#undef STATION_INFO
3426#undef STATION_ASSOC_FAIL_REASON
3427#undef STATION_MAX
3428
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003429#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3430/**
3431 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3432 * @wiphy: pointer to wireless wiphy structure.
3433 * @wdev: pointer to wireless_dev structure.
3434 * @data: Pointer to the Key data
3435 * @data_len:Length of the data passed
3436 *
3437 * This is called when wlan driver needs to save the keys received via
3438 * vendor specific command.
3439 *
3440 * Return: Return the Success or Failure code.
3441 */
3442static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3443 struct wireless_dev *wdev,
3444 const void *data, int data_len)
3445{
3446 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3447 struct net_device *dev = wdev->netdev;
3448 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3449 hdd_context_t *hdd_ctx_ptr;
3450 int status;
3451
Jeff Johnson1f61b612016-02-12 16:28:33 -08003452 ENTER_DEV(dev);
3453
Anurag Chouhan6d760662016-02-20 16:05:43 +05303454 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003455 hdd_err("Command not allowed in FTM mode");
3456 return -EPERM;
3457 }
3458
3459 if ((data == NULL) || (data_len == 0) ||
3460 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003461 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003462 return -EINVAL;
3463 }
3464
3465 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3466 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003467 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003468 return -EINVAL;
3469 }
3470
3471 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303472 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003473 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003474 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3475 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003476 true,
3477 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303478 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3479 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003480 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3481 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3482 return 0;
3483}
3484
3485/**
3486 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3487 * @wiphy: pointer to wireless wiphy structure.
3488 * @wdev: pointer to wireless_dev structure.
3489 * @data: Pointer to the Key data
3490 * @data_len:Length of the data passed
3491 *
3492 * This is called when wlan driver needs to save the keys received via
3493 * vendor specific command.
3494 *
3495 * Return: Return the Success or Failure code.
3496 */
3497static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3498 struct wireless_dev *wdev,
3499 const void *data, int data_len)
3500{
3501 int ret;
3502
3503 cds_ssr_protect(__func__);
3504 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3505 cds_ssr_unprotect(__func__);
3506
3507 return ret;
3508}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003509#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003510
3511static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3512 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3513 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3514 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003515 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003516};
3517
3518/**
3519 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3520 * @wiphy: pointer to wireless wiphy structure.
3521 * @wdev: pointer to wireless_dev structure.
3522 * @data: Pointer to the data to be passed via vendor interface
3523 * @data_len:Length of the data to be passed
3524 *
3525 * This is called when wlan driver needs to send wifi driver related info
3526 * (driver/fw version) to the user space application upon request.
3527 *
3528 * Return: Return the Success or Failure code.
3529 */
3530static int
3531__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3532 struct wireless_dev *wdev,
3533 const void *data, int data_len)
3534{
3535 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3536 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003537 tSirVersionString driver_version;
3538 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003539 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003540 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003541 struct sk_buff *reply_skb;
3542 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003543
Jeff Johnson1f61b612016-02-12 16:28:33 -08003544 ENTER_DEV(wdev->netdev);
3545
Anurag Chouhan6d760662016-02-20 16:05:43 +05303546 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003547 hdd_err("Command not allowed in FTM mode");
3548 return -EPERM;
3549 }
3550
3551 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303552 if (status)
3553 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003554
3555 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3556 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003557 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003558 return -EINVAL;
3559 }
3560
3561 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003562 hdd_err("Rcvd req for Driver version");
3563 strlcpy(driver_version, QWLAN_VERSIONSTR,
3564 sizeof(driver_version));
3565 skb_len += strlen(driver_version) + 1;
3566 count++;
3567 }
3568
3569 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3570 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003571 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3572 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003573 snprintf(firmware_version, sizeof(firmware_version),
3574 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3575 skb_len += strlen(firmware_version) + 1;
3576 count++;
3577 }
3578
3579 if (count == 0) {
3580 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003581 return -EINVAL;
3582 }
3583
Ryan Hsu7ac88852016-04-28 10:20:34 -07003584 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3585 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3586
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003587 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003588 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003589 return -ENOMEM;
3590 }
3591
Ryan Hsu7ac88852016-04-28 10:20:34 -07003592 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3593 if (nla_put_string(reply_skb,
3594 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3595 driver_version))
3596 goto error_nla_fail;
3597 }
3598
3599 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3600 if (nla_put_string(reply_skb,
3601 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3602 firmware_version))
3603 goto error_nla_fail;
3604 }
3605
3606 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3607 if (nla_put_u32(reply_skb,
3608 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3609 hdd_ctx->radio_index))
3610 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003611 }
3612
3613 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003614
3615error_nla_fail:
3616 hdd_err("nla put fail");
3617 kfree_skb(reply_skb);
3618 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003619}
3620
3621/**
3622 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3623 * @wiphy: pointer to wireless wiphy structure.
3624 * @wdev: pointer to wireless_dev structure.
3625 * @data: Pointer to the data to be passed via vendor interface
3626 * @data_len:Length of the data to be passed
3627 *
3628 * This is called when wlan driver needs to send wifi driver related info
3629 * (driver/fw version) to the user space application upon request.
3630 *
3631 * Return: Return the Success or Failure code.
3632 */
3633static int
3634wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3635 struct wireless_dev *wdev,
3636 const void *data, int data_len)
3637{
3638 int ret;
3639
3640 cds_ssr_protect(__func__);
3641 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3642 cds_ssr_unprotect(__func__);
3643
3644 return ret;
3645}
3646
3647/**
3648 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3649 * @wiphy: pointer to wireless wiphy structure.
3650 * @wdev: pointer to wireless_dev structure.
3651 * @data: Pointer to the data to be passed via vendor interface
3652 * @data_len:Length of the data to be passed
3653 *
3654 * This is called by userspace to know the supported logger features
3655 *
3656 * Return: Return the Success or Failure code.
3657 */
3658static int
3659__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3660 struct wireless_dev *wdev,
3661 const void *data, int data_len)
3662{
3663 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3664 int status;
3665 uint32_t features;
3666 struct sk_buff *reply_skb = NULL;
3667
Jeff Johnson1f61b612016-02-12 16:28:33 -08003668 ENTER_DEV(wdev->netdev);
3669
Anurag Chouhan6d760662016-02-20 16:05:43 +05303670 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003671 hdd_err("Command not allowed in FTM mode");
3672 return -EPERM;
3673 }
3674
3675 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303676 if (status)
3677 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003678
3679 features = 0;
3680
3681 if (hdd_is_memdump_supported())
3682 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3683 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3684 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3685 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3686
3687 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3688 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3689 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003690 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003691 return -ENOMEM;
3692 }
3693
Jeff Johnson020db452016-06-29 14:37:26 -07003694 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003695 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3696 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003697 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698 kfree_skb(reply_skb);
3699 return -EINVAL;
3700 }
3701
3702 return cfg80211_vendor_cmd_reply(reply_skb);
3703}
3704
3705/**
3706 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3707 * @wiphy: pointer to wireless wiphy structure.
3708 * @wdev: pointer to wireless_dev structure.
3709 * @data: Pointer to the data to be passed via vendor interface
3710 * @data_len:Length of the data to be passed
3711 *
3712 * This is called by userspace to know the supported logger features
3713 *
3714 * Return: Return the Success or Failure code.
3715 */
3716static int
3717wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3718 struct wireless_dev *wdev,
3719 const void *data, int data_len)
3720{
3721 int ret;
3722
3723 cds_ssr_protect(__func__);
3724 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3725 data, data_len);
3726 cds_ssr_unprotect(__func__);
3727
3728 return ret;
3729}
3730
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003731#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003732/**
3733 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3734 * @hdd_ctx_ptr: pointer to HDD Context.
3735 * @bssid: pointer to bssid of roamed AP.
3736 * @req_rsn_ie: Pointer to request RSN IE
3737 * @req_rsn_len: Length of the request RSN IE
3738 * @rsp_rsn_ie: Pointer to response RSN IE
3739 * @rsp_rsn_len: Length of the response RSN IE
3740 * @roam_info_ptr: Pointer to the roaming related information
3741 *
3742 * This is called when wlan driver needs to send the roaming and
3743 * authorization information after roaming.
3744 *
3745 * The information that would be sent is the request RSN IE, response
3746 * RSN IE and BSSID of the newly roamed AP.
3747 *
3748 * If the Authorized status is authenticated, then additional parameters
3749 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3750 * supplicant.
3751 *
3752 * The supplicant upon receiving this event would ignore the legacy
3753 * cfg80211_roamed call and use the entire information from this event.
3754 * The cfg80211_roamed should still co-exist since the kernel will
3755 * make use of the parameters even if the supplicant ignores it.
3756 *
3757 * Return: Return the Success or Failure code.
3758 */
3759int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3760 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3761 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3762{
3763 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003764 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003765 ENTER();
3766
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303767 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003768 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003769
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003770 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003771 !roam_info_ptr->roamSynchInProgress)
3772 return 0;
3773
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003774 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3775 NULL,
3776 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3777 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3778 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003779 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003780 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3781 GFP_KERNEL);
3782
3783 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003784 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003785 return -EINVAL;
3786 }
3787
3788 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3789 ETH_ALEN, bssid) ||
3790 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3791 req_rsn_len, req_rsn_ie) ||
3792 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3793 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003794 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003795 goto nla_put_failure;
3796 }
Jeff Johnson020db452016-06-29 14:37:26 -07003797 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003798 if (roam_info_ptr->synchAuthStatus ==
3799 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003800 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003801 if (nla_put_u8(skb,
3802 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3803 hdd_err("nla put fail");
3804 goto nla_put_failure;
3805 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003806 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3807 /* if FT or CCKM connection: dont send replay counter */
3808 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3809 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3810 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3811 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3812 nla_put(skb,
3813 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3814 SIR_REPLAY_CTR_LEN,
3815 roam_info_ptr->replay_ctr)) {
3816 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003817 hdd_err("failed to send replay counter.");
3818 goto nla_put_failure;
3819 }
3820 if (nla_put(skb,
3821 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3822 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3823 nla_put(skb,
3824 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3825 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3826 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003827 goto nla_put_failure;
3828 }
3829 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003830 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003831 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3832 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003833 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003834 goto nla_put_failure;
3835 }
3836 }
3837
Jeff Johnson020db452016-06-29 14:37:26 -07003838 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003839 roam_info_ptr->subnet_change_status);
3840
3841 /*
3842 * Add subnet change status if subnet has changed
3843 * 0 = unchanged
3844 * 1 = changed
3845 * 2 = unknown
3846 */
3847 if (roam_info_ptr->subnet_change_status) {
3848 if (nla_put_u8(skb,
3849 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3850 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003851 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003852 goto nla_put_failure;
3853 }
3854 }
3855
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003856 cfg80211_vendor_event(skb, GFP_KERNEL);
3857 return 0;
3858
3859nla_put_failure:
3860 kfree_skb(skb);
3861 return -EINVAL;
3862}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003863#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003864
3865static const struct nla_policy
3866wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3867
3868 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3869 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3870 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303871 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003872};
3873
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003874/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303875 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3876 *
3877 * @adapter: Pointer to HDD adapter
3878 * @ie_data: Pointer to Scan IEs buffer
3879 * @ie_len: Length of Scan IEs
3880 *
3881 * Return: 0 on success; error number otherwise
3882 */
3883static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3884 uint8_t *ie_data, uint8_t ie_len)
3885{
3886 hdd_scaninfo_t *scan_info = NULL;
3887 scan_info = &adapter->scan_info;
3888
3889 if (scan_info->default_scan_ies) {
3890 qdf_mem_free(scan_info->default_scan_ies);
3891 scan_info->default_scan_ies = NULL;
3892 }
3893
3894 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3895 if (!scan_info->default_scan_ies)
3896 return -ENOMEM;
3897
3898 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3899 scan_info->default_scan_ies_len = ie_len;
3900 return 0;
3901}
3902
3903/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003904 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3905 * vendor command
3906 *
3907 * @wiphy: wiphy device pointer
3908 * @wdev: wireless device pointer
3909 * @data: Vendor command data buffer
3910 * @data_len: Buffer length
3911 *
3912 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3913 *
3914 * Return: Error code.
3915 */
3916static int
3917__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3918 struct wireless_dev *wdev,
3919 const void *data,
3920 int data_len)
3921{
3922 struct net_device *dev = wdev->netdev;
3923 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3924 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3925 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3926 int ret_val = 0;
3927 u32 modulated_dtim;
3928 u16 stats_avg_factor;
3929 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303930 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003931 u32 ftm_capab;
Kapil Gupta6213c012016-09-02 19:39:09 +05303932 uint8_t qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303933 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303934 int attr_len;
3935 int access_policy = 0;
3936 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3937 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303938 uint16_t scan_ie_len = 0;
3939 uint8_t *scan_ie;
3940
Jeff Johnson1f61b612016-02-12 16:28:33 -08003941 ENTER_DEV(dev);
3942
Anurag Chouhan6d760662016-02-20 16:05:43 +05303943 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003944 hdd_err("Command not allowed in FTM mode");
3945 return -EPERM;
3946 }
3947
3948 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303949 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003950 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003951
3952 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3953 data, data_len,
3954 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07003955 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003956 return -EINVAL;
3957 }
3958
Krunal Sonie3531942016-04-12 17:43:53 -07003959 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
3960 ftm_capab = nla_get_u32(tb[
3961 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
3962 hdd_ctx->config->fine_time_meas_cap =
3963 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
3964 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05303965 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07003966 hdd_ctx->config->fine_time_meas_cap);
3967 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
3968 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
3969 hdd_ctx->config->fine_time_meas_cap);
3970 }
3971
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003972 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
3973 modulated_dtim = nla_get_u32(
3974 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
3975
3976 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
3977 adapter->sessionId,
3978 modulated_dtim);
3979
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303980 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003981 ret_val = -EPERM;
3982 }
3983
Kapil Gupta6213c012016-09-02 19:39:09 +05303984 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
3985 qpower = nla_get_u8(
3986 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
3987 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
3988 ret_val = -EINVAL;
3989 }
3990
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003991 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
3992 stats_avg_factor = nla_get_u16(
3993 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
3994 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
3995 adapter->sessionId,
3996 stats_avg_factor);
3997
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303998 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003999 ret_val = -EPERM;
4000 }
4001
4002
4003 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4004 guard_time = nla_get_u32(
4005 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4006 status = sme_configure_guard_time(hdd_ctx->hHal,
4007 adapter->sessionId,
4008 guard_time);
4009
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304010 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004011 ret_val = -EPERM;
4012 }
4013
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304014 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4015 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4016 attr_len = nla_len(
4017 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4018 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4019 hdd_info("Invalid value. attr_len %d",
4020 attr_len);
4021 return -EINVAL;
4022 }
4023
4024 nla_memcpy(&vendor_ie,
4025 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4026 attr_len);
4027 vendor_ie_present = true;
4028 hdd_info("Access policy vendor ie present.attr_len %d",
4029 attr_len);
4030 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4031 &vendor_ie[0], attr_len);
4032 }
4033
4034 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4035 access_policy = (int) nla_get_u32(
4036 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4037 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4038 (access_policy >
4039 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4040 hdd_info("Invalid value. access_policy %d",
4041 access_policy);
4042 return -EINVAL;
4043 }
4044 access_policy_present = true;
4045 hdd_info("Access policy present. access_policy %d",
4046 access_policy);
4047 }
4048
4049 if (vendor_ie_present && access_policy_present) {
4050 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4051 access_policy =
4052 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
4053 } else {
4054 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
4055 }
4056
4057 hdd_info("calling sme_update_access_policy_vendor_ie");
4058 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4059 adapter->sessionId, &vendor_ie[0],
4060 access_policy);
4061 if (QDF_STATUS_SUCCESS != status) {
4062 hdd_info("Failed to set vendor ie and access policy.");
4063 return -EINVAL;
4064 }
4065 }
4066
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304067 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4068 set_value = nla_get_u8(
4069 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4070 hdd_info("set_value: %d", set_value);
4071 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4072 }
4073
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304074 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4075 scan_ie_len = nla_len(
4076 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4077 hdd_info("Received default scan IE of len %d session %d device mode %d",
4078 scan_ie_len, adapter->sessionId,
4079 adapter->device_mode);
4080 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4081 scan_ie = (uint8_t *) nla_data(tb
4082 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304083
4084 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4085 scan_ie_len))
4086 hdd_err("Failed to save default scan IEs");
4087
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304088 if (adapter->device_mode == QDF_STA_MODE) {
4089 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4090 adapter->sessionId, scan_ie,
4091 scan_ie_len);
4092 if (QDF_STATUS_SUCCESS != status)
4093 ret_val = -EPERM;
4094 }
4095 } else
4096 ret_val = -EPERM;
4097 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004098 return ret_val;
4099}
4100
4101/**
4102 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4103 * vendor command
4104 *
4105 * @wiphy: wiphy device pointer
4106 * @wdev: wireless device pointer
4107 * @data: Vendor command data buffer
4108 * @data_len: Buffer length
4109 *
4110 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4111 *
4112 * Return: EOK or other error codes.
4113 */
4114static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4115 struct wireless_dev *wdev,
4116 const void *data,
4117 int data_len)
4118{
4119 int ret;
4120
4121 cds_ssr_protect(__func__);
4122 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4123 data, data_len);
4124 cds_ssr_unprotect(__func__);
4125
4126 return ret;
4127}
4128
4129static const struct
4130nla_policy
4131qca_wlan_vendor_wifi_logger_start_policy
4132[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4133 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4134 = {.type = NLA_U32 },
4135 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4136 = {.type = NLA_U32 },
4137 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4138 = {.type = NLA_U32 },
4139};
4140
4141/**
4142 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4143 * or disable the collection of packet statistics from the firmware
4144 * @wiphy: WIPHY structure pointer
4145 * @wdev: Wireless device structure pointer
4146 * @data: Pointer to the data received
4147 * @data_len: Length of the data received
4148 *
4149 * This function enables or disables the collection of packet statistics from
4150 * the firmware
4151 *
4152 * Return: 0 on success and errno on failure
4153 */
4154static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4155 struct wireless_dev *wdev,
4156 const void *data,
4157 int data_len)
4158{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304159 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004160 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4161 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4162 struct sir_wifi_start_log start_log;
4163
Jeff Johnson1f61b612016-02-12 16:28:33 -08004164 ENTER_DEV(wdev->netdev);
4165
Anurag Chouhan6d760662016-02-20 16:05:43 +05304166 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004167 hdd_err("Command not allowed in FTM mode");
4168 return -EPERM;
4169 }
4170
4171 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304172 if (status)
4173 return status;
4174
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004175
4176 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4177 data, data_len,
4178 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004179 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180 return -EINVAL;
4181 }
4182
4183 /* Parse and fetch ring id */
4184 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004185 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004186 return -EINVAL;
4187 }
4188 start_log.ring_id = nla_get_u32(
4189 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004190 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004191
4192 /* Parse and fetch verbose level */
4193 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004194 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004195 return -EINVAL;
4196 }
4197 start_log.verbose_level = nla_get_u32(
4198 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004199 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004200
4201 /* Parse and fetch flag */
4202 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004203 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004204 return -EINVAL;
4205 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304206 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304208 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004209
4210 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4211
4212 if (start_log.ring_id == RING_ID_WAKELOCK) {
4213 /* Start/stop wakelock events */
4214 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4215 cds_set_wakelock_logging(true);
4216 else
4217 cds_set_wakelock_logging(false);
4218 return 0;
4219 }
4220
4221 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304222 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004223 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004224 status);
4225 return -EINVAL;
4226 }
4227 return 0;
4228}
4229
4230/**
4231 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4232 * or disable the collection of packet statistics from the firmware
4233 * @wiphy: WIPHY structure pointer
4234 * @wdev: Wireless device structure pointer
4235 * @data: Pointer to the data received
4236 * @data_len: Length of the data received
4237 *
4238 * This function is used to enable or disable the collection of packet
4239 * statistics from the firmware
4240 *
4241 * Return: 0 on success and errno on failure
4242 */
4243static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4244 struct wireless_dev *wdev,
4245 const void *data,
4246 int data_len)
4247{
4248 int ret = 0;
4249
4250 cds_ssr_protect(__func__);
4251 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4252 wdev, data, data_len);
4253 cds_ssr_unprotect(__func__);
4254
4255 return ret;
4256}
4257
4258static const struct
4259nla_policy
4260qca_wlan_vendor_wifi_logger_get_ring_data_policy
4261[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4262 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4263 = {.type = NLA_U32 },
4264};
4265
4266/**
4267 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4268 * @wiphy: WIPHY structure pointer
4269 * @wdev: Wireless device structure pointer
4270 * @data: Pointer to the data received
4271 * @data_len: Length of the data received
4272 *
4273 * This function is used to flush or retrieve the per packet statistics from
4274 * the driver
4275 *
4276 * Return: 0 on success and errno on failure
4277 */
4278static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4279 struct wireless_dev *wdev,
4280 const void *data,
4281 int data_len)
4282{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304283 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004284 uint32_t ring_id;
4285 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4286 struct nlattr *tb
4287 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4288
Jeff Johnson1f61b612016-02-12 16:28:33 -08004289 ENTER_DEV(wdev->netdev);
4290
Anurag Chouhan6d760662016-02-20 16:05:43 +05304291 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004292 hdd_err("Command not allowed in FTM mode");
4293 return -EPERM;
4294 }
4295
4296 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304297 if (status)
4298 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004299
4300 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4301 data, data_len,
4302 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004303 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004304 return -EINVAL;
4305 }
4306
4307 /* Parse and fetch ring id */
4308 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004309 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004310 return -EINVAL;
4311 }
4312
4313 ring_id = nla_get_u32(
4314 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4315
4316 if (ring_id == RING_ID_PER_PACKET_STATS) {
4317 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004318 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304319 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4320 /*
4321 * As part of DRIVER ring ID, flush both driver and fw logs.
4322 * For other Ring ID's driver doesn't have any rings to flush
4323 */
4324 hdd_notice("Bug report triggered by framework");
4325
4326 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4327 WLAN_LOG_INDICATOR_FRAMEWORK,
4328 WLAN_LOG_REASON_CODE_UNUSED,
4329 true, false);
4330 if (QDF_STATUS_SUCCESS != status) {
4331 hdd_err("Failed to trigger bug report");
4332 return -EINVAL;
4333 }
4334 } else {
4335 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4336 WLAN_LOG_INDICATOR_FRAMEWORK,
4337 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004338 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004339 return 0;
4340}
4341
4342/**
4343 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4344 * @wiphy: WIPHY structure pointer
4345 * @wdev: Wireless device structure pointer
4346 * @data: Pointer to the data received
4347 * @data_len: Length of the data received
4348 *
4349 * This function is used to flush or retrieve the per packet statistics from
4350 * the driver
4351 *
4352 * Return: 0 on success and errno on failure
4353 */
4354static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4355 struct wireless_dev *wdev,
4356 const void *data,
4357 int data_len)
4358{
4359 int ret = 0;
4360
4361 cds_ssr_protect(__func__);
4362 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4363 wdev, data, data_len);
4364 cds_ssr_unprotect(__func__);
4365
4366 return ret;
4367}
4368
4369#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4370/**
4371 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4372 * @hdd_ctx: HDD context
4373 * @request_id: [input] request id
4374 * @pattern_id: [output] pattern id
4375 *
4376 * This function loops through request id to pattern id array
4377 * if the slot is available, store the request id and return pattern id
4378 * if entry exists, return the pattern id
4379 *
4380 * Return: 0 on success and errno on failure
4381 */
4382static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4383 uint32_t request_id,
4384 uint8_t *pattern_id)
4385{
4386 uint32_t i;
4387
4388 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4389 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4390 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4391 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4392 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4393 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4394 return 0;
4395 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4396 request_id) {
4397 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4398 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4399 return 0;
4400 }
4401 }
4402 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4403 return -EINVAL;
4404}
4405
4406/**
4407 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4408 * @hdd_ctx: HDD context
4409 * @request_id: [input] request id
4410 * @pattern_id: [output] pattern id
4411 *
4412 * This function loops through request id to pattern id array
4413 * reset request id to 0 (slot available again) and
4414 * return pattern id
4415 *
4416 * Return: 0 on success and errno on failure
4417 */
4418static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4419 uint32_t request_id,
4420 uint8_t *pattern_id)
4421{
4422 uint32_t i;
4423
4424 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4425 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4426 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4427 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4428 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4429 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4430 return 0;
4431 }
4432 }
4433 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4434 return -EINVAL;
4435}
4436
4437
4438/*
4439 * define short names for the global vendor params
4440 * used by __wlan_hdd_cfg80211_offloaded_packets()
4441 */
4442#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4443#define PARAM_REQUEST_ID \
4444 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4445#define PARAM_CONTROL \
4446 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4447#define PARAM_IP_PACKET \
4448 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4449#define PARAM_SRC_MAC_ADDR \
4450 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4451#define PARAM_DST_MAC_ADDR \
4452 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4453#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4454
4455/**
4456 * wlan_hdd_add_tx_ptrn() - add tx pattern
4457 * @adapter: adapter pointer
4458 * @hdd_ctx: hdd context
4459 * @tb: nl attributes
4460 *
4461 * This function reads the NL attributes and forms a AddTxPtrn message
4462 * posts it to SME.
4463 *
4464 */
4465static int
4466wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4467 struct nlattr **tb)
4468{
4469 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304470 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004471 uint32_t request_id, ret, len;
4472 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304473 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004474 uint16_t eth_type = htons(ETH_P_IP);
4475
4476 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004477 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004478 return -ENOTSUPP;
4479 }
4480
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304481 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004482 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004483 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004484 return -ENOMEM;
4485 }
4486
4487 /* Parse and fetch request Id */
4488 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004489 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490 goto fail;
4491 }
4492
4493 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4494 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004495 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004496 return -EINVAL;
4497 }
Jeff Johnson77848112016-06-29 14:52:06 -07004498 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499
4500 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004501 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004502 goto fail;
4503 }
4504 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004505 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004506 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004507 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004508 goto fail;
4509 }
4510
4511 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004512 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004513 goto fail;
4514 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004515 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304516 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004517 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004518 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004519
Anurag Chouhanc5548422016-02-24 18:33:27 +05304520 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004521 &adapter->macAddressCurrent)) {
4522 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004523 goto fail;
4524 }
4525
4526 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004527 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528 goto fail;
4529 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304530 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004531 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004532 MAC_ADDR_ARRAY(dst_addr.bytes));
4533
4534 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004535 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004536 goto fail;
4537 }
4538 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004539 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004540
4541 if (add_req->ucPtrnSize < 0 ||
4542 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4543 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004544 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004545 add_req->ucPtrnSize);
4546 goto fail;
4547 }
4548
4549 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304550 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304551 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304552 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304553 QDF_MAC_ADDR_SIZE);
4554 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304555 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004556 len += 2;
4557
4558 /*
4559 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4560 * ------------------------------------------------------------
4561 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4562 * ------------------------------------------------------------
4563 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304564 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004565 nla_data(tb[PARAM_IP_PACKET]),
4566 add_req->ucPtrnSize);
4567 add_req->ucPtrnSize += len;
4568
4569 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4570 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004571 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004572 goto fail;
4573 }
4574 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004575 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004576
4577 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304578 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004579 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004580 goto fail;
4581 }
4582
4583 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304584 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004585 return 0;
4586
4587fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304588 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004589 return -EINVAL;
4590}
4591
4592/**
4593 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4594 * @adapter: adapter pointer
4595 * @hdd_ctx: hdd context
4596 * @tb: nl attributes
4597 *
4598 * This function reads the NL attributes and forms a DelTxPtrn message
4599 * posts it to SME.
4600 *
4601 */
4602static int
4603wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4604 struct nlattr **tb)
4605{
4606 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304607 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004608 uint32_t request_id, ret;
4609 uint8_t pattern_id = 0;
4610
4611 /* Parse and fetch request Id */
4612 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004613 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004614 return -EINVAL;
4615 }
4616 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4617 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004618 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004619 return -EINVAL;
4620 }
4621
4622 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4623 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004624 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004625 return -EINVAL;
4626 }
4627
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304628 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004629 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004630 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004631 return -ENOMEM;
4632 }
4633
Anurag Chouhanc5548422016-02-24 18:33:27 +05304634 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004635 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004636 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004637 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004638 request_id, del_req->ucPtrnId);
4639
4640 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304641 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004642 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004643 goto fail;
4644 }
4645
4646 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304647 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004648 return 0;
4649
4650fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304651 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004652 return -EINVAL;
4653}
4654
4655
4656/**
4657 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4658 * @wiphy: Pointer to wireless phy
4659 * @wdev: Pointer to wireless device
4660 * @data: Pointer to data
4661 * @data_len: Data length
4662 *
4663 * Return: 0 on success, negative errno on failure
4664 */
4665static int
4666__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4667 struct wireless_dev *wdev,
4668 const void *data,
4669 int data_len)
4670{
4671 struct net_device *dev = wdev->netdev;
4672 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4673 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4674 struct nlattr *tb[PARAM_MAX + 1];
4675 uint8_t control;
4676 int ret;
4677 static const struct nla_policy policy[PARAM_MAX + 1] = {
4678 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4679 [PARAM_CONTROL] = { .type = NLA_U32 },
4680 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304681 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004682 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304683 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004684 [PARAM_PERIOD] = { .type = NLA_U32 },
4685 };
4686
Jeff Johnson1f61b612016-02-12 16:28:33 -08004687 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004688
Anurag Chouhan6d760662016-02-20 16:05:43 +05304689 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690 hdd_err("Command not allowed in FTM mode");
4691 return -EPERM;
4692 }
4693
4694 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304695 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004696 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697
4698 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004699 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004700 return -ENOTSUPP;
4701 }
4702
4703 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004704 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004705 return -EINVAL;
4706 }
4707
4708 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004709 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004710 return -EINVAL;
4711 }
4712 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004713 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004714
4715 if (control == WLAN_START_OFFLOADED_PACKETS)
4716 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4717 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4718 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4719 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004720 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004721 return -EINVAL;
4722 }
4723}
4724
4725/*
4726 * done with short names for the global vendor params
4727 * used by __wlan_hdd_cfg80211_offloaded_packets()
4728 */
4729#undef PARAM_MAX
4730#undef PARAM_REQUEST_ID
4731#undef PARAM_CONTROL
4732#undef PARAM_IP_PACKET
4733#undef PARAM_SRC_MAC_ADDR
4734#undef PARAM_DST_MAC_ADDR
4735#undef PARAM_PERIOD
4736
4737/**
4738 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4739 * @wiphy: wiphy structure pointer
4740 * @wdev: Wireless device structure pointer
4741 * @data: Pointer to the data received
4742 * @data_len: Length of @data
4743 *
4744 * Return: 0 on success; errno on failure
4745 */
4746static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4747 struct wireless_dev *wdev,
4748 const void *data,
4749 int data_len)
4750{
4751 int ret = 0;
4752
4753 cds_ssr_protect(__func__);
4754 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4755 wdev, data, data_len);
4756 cds_ssr_unprotect(__func__);
4757
4758 return ret;
4759}
4760#endif
4761
4762/*
4763 * define short names for the global vendor params
4764 * used by __wlan_hdd_cfg80211_monitor_rssi()
4765 */
4766#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4767#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4768#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4769#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4770#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4771
4772/**
4773 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4774 * @wiphy: Pointer to wireless phy
4775 * @wdev: Pointer to wireless device
4776 * @data: Pointer to data
4777 * @data_len: Data length
4778 *
4779 * Return: 0 on success, negative errno on failure
4780 */
4781static int
4782__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4783 struct wireless_dev *wdev,
4784 const void *data,
4785 int data_len)
4786{
4787 struct net_device *dev = wdev->netdev;
4788 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4789 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4790 struct nlattr *tb[PARAM_MAX + 1];
4791 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304792 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004793 int ret;
4794 uint32_t control;
4795 static const struct nla_policy policy[PARAM_MAX + 1] = {
4796 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4797 [PARAM_CONTROL] = { .type = NLA_U32 },
4798 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4799 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4800 };
4801
Jeff Johnson1f61b612016-02-12 16:28:33 -08004802 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004803
4804 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304805 if (ret)
4806 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004807
4808 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004809 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004810 return -ENOTSUPP;
4811 }
4812
4813 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004814 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004815 return -EINVAL;
4816 }
4817
4818 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004819 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004820 return -EINVAL;
4821 }
4822
4823 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004824 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004825 return -EINVAL;
4826 }
4827
4828 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4829 req.session_id = adapter->sessionId;
4830 control = nla_get_u32(tb[PARAM_CONTROL]);
4831
4832 if (control == QCA_WLAN_RSSI_MONITORING_START) {
4833 req.control = true;
4834 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004835 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004836 return -EINVAL;
4837 }
4838
4839 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004840 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004841 return -EINVAL;
4842 }
4843
4844 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
4845 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
4846
4847 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004848 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849 req.min_rssi, req.max_rssi);
4850 return -EINVAL;
4851 }
Jeff Johnson77848112016-06-29 14:52:06 -07004852 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004853 req.min_rssi, req.max_rssi);
4854
4855 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
4856 req.control = false;
4857 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004858 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004859 return -EINVAL;
4860 }
Jeff Johnson77848112016-06-29 14:52:06 -07004861 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004862 req.request_id, req.session_id, req.control);
4863
4864 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304865 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004866 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004867 return -EINVAL;
4868 }
4869
4870 return 0;
4871}
4872
4873/*
4874 * done with short names for the global vendor params
4875 * used by __wlan_hdd_cfg80211_monitor_rssi()
4876 */
4877#undef PARAM_MAX
4878#undef PARAM_CONTROL
4879#undef PARAM_REQUEST_ID
4880#undef PARAM_MAX_RSSI
4881#undef PARAM_MIN_RSSI
4882
4883/**
4884 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
4885 * @wiphy: wiphy structure pointer
4886 * @wdev: Wireless device structure pointer
4887 * @data: Pointer to the data received
4888 * @data_len: Length of @data
4889 *
4890 * Return: 0 on success; errno on failure
4891 */
4892static int
4893wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
4894 const void *data, int data_len)
4895{
4896 int ret;
4897
4898 cds_ssr_protect(__func__);
4899 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
4900 cds_ssr_unprotect(__func__);
4901
4902 return ret;
4903}
4904
4905/**
4906 * hdd_rssi_threshold_breached() - rssi breached NL event
4907 * @hddctx: HDD context
4908 * @data: rssi breached event data
4909 *
4910 * This function reads the rssi breached event %data and fill in the skb with
4911 * NL attributes and send up the NL event.
4912 *
4913 * Return: none
4914 */
4915void hdd_rssi_threshold_breached(void *hddctx,
4916 struct rssi_breach_event *data)
4917{
4918 hdd_context_t *hdd_ctx = hddctx;
4919 struct sk_buff *skb;
4920
4921 ENTER();
4922
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304923 if (wlan_hdd_validate_context(hdd_ctx))
4924 return;
4925 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07004926 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004927 return;
4928 }
4929
4930 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4931 NULL,
4932 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
4933 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
4934 GFP_KERNEL);
4935
4936 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07004937 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004938 return;
4939 }
4940
Jeff Johnson77848112016-06-29 14:52:06 -07004941 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004942 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07004943 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004944 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
4945
4946 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
4947 data->request_id) ||
4948 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
4949 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
4950 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
4951 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004952 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004953 goto fail;
4954 }
4955
4956 cfg80211_vendor_event(skb, GFP_KERNEL);
4957 return;
4958
4959fail:
4960 kfree_skb(skb);
4961 return;
4962}
4963
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05304964static const struct nla_policy
4965ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
4966 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
4967};
4968
4969/**
4970 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
4971 * @wiphy: Pointer to wireless phy
4972 * @wdev: Pointer to wireless device
4973 * @data: Pointer to data
4974 * @data_len: Length of @data
4975 *
4976 * Return: 0 on success, negative errno on failure
4977 */
4978static int
4979__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
4980 struct wireless_dev *wdev,
4981 const void *data, int data_len)
4982{
4983 int status;
4984 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
4985 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07004986 struct net_device *dev = wdev->netdev;
4987 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05304988
4989 ENTER_DEV(wdev->netdev);
4990
4991 status = wlan_hdd_validate_context(pHddCtx);
4992 if (0 != status)
4993 return status;
4994 if (!pHddCtx->config->fhostNSOffload) {
4995 hdd_err("ND Offload not supported");
4996 return -EINVAL;
4997 }
4998
4999 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5000 (struct nlattr *)data,
5001 data_len, ns_offload_set_policy)) {
5002 hdd_err("nla_parse failed");
5003 return -EINVAL;
5004 }
5005
5006 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5007 hdd_err("ND Offload flag attribute not present");
5008 return -EINVAL;
5009 }
5010
5011 pHddCtx->ns_offload_enable =
5012 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5013
Dustin Brownd8279d22016-09-07 14:52:57 -07005014 /* update ns offload in case it is already enabled/disabled */
5015 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5016
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305017 return 0;
5018}
5019
5020/**
5021 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5022 * @wiphy: pointer to wireless wiphy structure.
5023 * @wdev: pointer to wireless_dev structure.
5024 * @data: Pointer to the data to be passed via vendor interface
5025 * @data_len:Length of the data to be passed
5026 *
5027 * Return: Return the Success or Failure code.
5028 */
5029static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5030 struct wireless_dev *wdev,
5031 const void *data, int data_len)
5032{
5033 int ret;
5034
5035 cds_ssr_protect(__func__);
5036 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5037 cds_ssr_unprotect(__func__);
5038
5039 return ret;
5040}
5041
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005042/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5043 * @wiphy: Pointer to wireless phy
5044 * @wdev: Pointer to wireless device
5045 * @data: Pointer to data
5046 * @data_len: Data length
5047 *
5048 * This function return the preferred frequency list generated by the policy
5049 * manager.
5050 *
5051 * Return: success or failure code
5052 */
5053static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5054 struct wireless_dev
5055 *wdev, const void *data,
5056 int data_len)
5057{
5058 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5059 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305060 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305061 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005062 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305063 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005064 enum cds_con_mode intf_mode;
5065 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5066 struct sk_buff *reply_skb;
5067
Jeff Johnson1f61b612016-02-12 16:28:33 -08005068 ENTER_DEV(wdev->netdev);
5069
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005070 ret = wlan_hdd_validate_context(hdd_ctx);
5071 if (ret)
5072 return -EINVAL;
5073
5074 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5075 data, data_len, NULL)) {
5076 hdd_err("Invalid ATTR");
5077 return -EINVAL;
5078 }
5079
5080 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5081 hdd_err("attr interface type failed");
5082 return -EINVAL;
5083 }
5084
5085 intf_mode = nla_get_u32(tb
5086 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5087
5088 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5089 hdd_err("Invalid interface type");
5090 return -EINVAL;
5091 }
5092
5093 hdd_debug("Userspace requested pref freq list");
5094
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305095 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5096 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305097 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005098 hdd_err("Get pcl failed");
5099 return -EINVAL;
5100 }
5101
5102 /* convert channel number to frequency */
5103 for (i = 0; i < pcl_len; i++) {
5104 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5105 freq_list[i] =
5106 ieee80211_channel_to_frequency(pcl[i],
5107 IEEE80211_BAND_2GHZ);
5108 else
5109 freq_list[i] =
5110 ieee80211_channel_to_frequency(pcl[i],
5111 IEEE80211_BAND_5GHZ);
5112 }
5113
5114 /* send the freq_list back to supplicant */
5115 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5116 sizeof(u32) *
5117 pcl_len +
5118 NLMSG_HDRLEN);
5119
5120 if (!reply_skb) {
5121 hdd_err("Allocate reply_skb failed");
5122 return -EINVAL;
5123 }
5124
5125 if (nla_put_u32(reply_skb,
5126 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5127 intf_mode) ||
5128 nla_put(reply_skb,
5129 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5130 sizeof(uint32_t) * pcl_len,
5131 freq_list)) {
5132 hdd_err("nla put fail");
5133 kfree_skb(reply_skb);
5134 return -EINVAL;
5135 }
5136
5137 return cfg80211_vendor_cmd_reply(reply_skb);
5138}
5139
5140/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5141 * @wiphy: Pointer to wireless phy
5142 * @wdev: Pointer to wireless device
5143 * @data: Pointer to data
5144 * @data_len: Data length
5145 *
5146 * This function return the preferred frequency list generated by the policy
5147 * manager.
5148 *
5149 * Return: success or failure code
5150 */
5151static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5152 struct wireless_dev
5153 *wdev, const void *data,
5154 int data_len)
5155{
5156 int ret = 0;
5157
5158 cds_ssr_protect(__func__);
5159 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5160 data, data_len);
5161 cds_ssr_unprotect(__func__);
5162
5163 return ret;
5164}
5165
5166/**
5167 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5168 * @wiphy: Pointer to wireless phy
5169 * @wdev: Pointer to wireless device
5170 * @data: Pointer to data
5171 * @data_len: Data length
5172 *
5173 * Return: 0 on success, negative errno on failure
5174 */
5175static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5176 struct wireless_dev *wdev,
5177 const void *data,
5178 int data_len)
5179{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305180 struct net_device *ndev = wdev->netdev;
5181 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005182 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5183 int ret = 0;
5184 enum cds_con_mode intf_mode;
5185 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5186 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005187
Jeff Johnson1f61b612016-02-12 16:28:33 -08005188 ENTER_DEV(ndev);
5189
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005190 ret = wlan_hdd_validate_context(hdd_ctx);
5191 if (ret)
5192 return ret;
5193
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005194 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5195 data, data_len, NULL)) {
5196 hdd_err("Invalid ATTR");
5197 return -EINVAL;
5198 }
5199
5200 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5201 hdd_err("attr interface type failed");
5202 return -EINVAL;
5203 }
5204
5205 intf_mode = nla_get_u32(tb
5206 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5207
5208 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5209 hdd_err("Invalid interface type");
5210 return -EINVAL;
5211 }
5212
5213 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5214 hdd_err("attr probable freq failed");
5215 return -EINVAL;
5216 }
5217
5218 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5219 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5220
5221 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005222 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005223 channel_hint, HW_MODE_20_MHZ)) {
5224 hdd_err("Set channel hint failed due to concurrency check");
5225 return -EINVAL;
5226 }
5227
Krunal Soni09e55032016-06-07 10:06:55 -07005228 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5229 hdd_warn("Remain On Channel Pending");
5230
Krunal Soni3091bcc2016-06-23 12:28:21 -07005231 ret = qdf_reset_connection_update();
5232 if (!QDF_IS_STATUS_SUCCESS(ret))
5233 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234
Krunal Soni3091bcc2016-06-23 12:28:21 -07005235 ret = cds_current_connections_update(adapter->sessionId,
5236 channel_hint,
5237 SIR_UPDATE_REASON_SET_OPER_CHAN);
5238 if (QDF_STATUS_E_FAILURE == ret) {
5239 /* return in the failure case */
5240 hdd_err("ERROR: connections update failed!!");
5241 return -EINVAL;
5242 }
5243
5244 if (QDF_STATUS_SUCCESS == ret) {
5245 /*
5246 * Success is the only case for which we expect hw mode
5247 * change to take place, hence we need to wait.
5248 * For any other return value it should be a pass
5249 * through
5250 */
5251 ret = qdf_wait_for_connection_update();
5252 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5253 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005254 return -EINVAL;
5255 }
5256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005257 }
5258
5259 return 0;
5260}
5261
5262/**
5263 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5264 * @wiphy: Pointer to wireless phy
5265 * @wdev: Pointer to wireless device
5266 * @data: Pointer to data
5267 * @data_len: Data length
5268 *
5269 * Return: 0 on success, negative errno on failure
5270 */
5271static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5272 struct wireless_dev *wdev,
5273 const void *data,
5274 int data_len)
5275{
5276 int ret = 0;
5277
5278 cds_ssr_protect(__func__);
5279 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5280 data, data_len);
5281 cds_ssr_unprotect(__func__);
5282
5283 return ret;
5284}
5285
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305286static const struct
5287nla_policy
5288qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5289 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5290};
5291
5292/**
5293 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5294 * @wiphy: WIPHY structure pointer
5295 * @wdev: Wireless device structure pointer
5296 * @data: Pointer to the data received
5297 * @data_len: Length of the data received
5298 *
5299 * This function is used to get link properties like nss, rate flags and
5300 * operating frequency for the active connection with the given peer.
5301 *
5302 * Return: 0 on success and errno on failure
5303 */
5304static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5305 struct wireless_dev *wdev,
5306 const void *data,
5307 int data_len)
5308{
5309 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5310 struct net_device *dev = wdev->netdev;
5311 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5312 hdd_station_ctx_t *hdd_sta_ctx;
5313 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305314 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305315 uint32_t sta_id;
5316 struct sk_buff *reply_skb;
5317 uint32_t rate_flags = 0;
5318 uint8_t nss;
5319 uint8_t final_rate_flags = 0;
5320 uint32_t freq;
5321
Jeff Johnson1f61b612016-02-12 16:28:33 -08005322 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305323
Anurag Chouhan6d760662016-02-20 16:05:43 +05305324 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305325 hdd_err("Command not allowed in FTM mode");
5326 return -EPERM;
5327 }
5328
5329 if (0 != wlan_hdd_validate_context(hdd_ctx))
5330 return -EINVAL;
5331
5332 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5333 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005334 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305335 return -EINVAL;
5336 }
5337
5338 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005339 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305340 adapter->device_mode);
5341 return -EINVAL;
5342 }
5343
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305344 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305345 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005346 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305347 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5348
Krunal Sonib4326f22016-03-10 13:05:51 -08005349 if (adapter->device_mode == QDF_STA_MODE ||
5350 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305351 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5352 if ((hdd_sta_ctx->conn_info.connState !=
5353 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305354 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305355 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005356 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305357 MAC_ADDR_ARRAY(peer_mac));
5358 return -EINVAL;
5359 }
5360
5361 nss = hdd_sta_ctx->conn_info.nss;
5362 freq = cds_chan_to_freq(
5363 hdd_sta_ctx->conn_info.operationChannel);
5364 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005365 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5366 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305367
5368 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5369 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305370 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305371 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305372 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305373 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305374 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305375 break;
5376 }
5377
5378 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005379 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305380 MAC_ADDR_ARRAY(peer_mac));
5381 return -EINVAL;
5382 }
5383
5384 nss = adapter->aStaInfo[sta_id].nss;
5385 freq = cds_chan_to_freq(
5386 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5387 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5388 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005389 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305390 MAC_ADDR_ARRAY(peer_mac));
5391 return -EINVAL;
5392 }
5393
5394 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5395 if (rate_flags & eHAL_TX_RATE_VHT80) {
5396 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005397#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305398 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005399#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305400 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5401 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005402#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305403 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005404#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305405 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5406 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5407 } else if (rate_flags &
5408 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5409 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005410#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305411 if (rate_flags & eHAL_TX_RATE_HT40)
5412 final_rate_flags |=
5413 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005414#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305415 }
5416
5417 if (rate_flags & eHAL_TX_RATE_SGI) {
5418 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5419 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5420 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5421 }
5422 }
5423
5424 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5425 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5426
5427 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005428 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305429 return -EINVAL;
5430 }
5431
5432 if (nla_put_u8(reply_skb,
5433 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5434 nss) ||
5435 nla_put_u8(reply_skb,
5436 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5437 final_rate_flags) ||
5438 nla_put_u32(reply_skb,
5439 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5440 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005441 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305442 kfree_skb(reply_skb);
5443 return -EINVAL;
5444 }
5445
5446 return cfg80211_vendor_cmd_reply(reply_skb);
5447}
5448
5449/**
5450 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5451 * properties.
5452 * @wiphy: WIPHY structure pointer
5453 * @wdev: Wireless device structure pointer
5454 * @data: Pointer to the data received
5455 * @data_len: Length of the data received
5456 *
5457 * This function is used to get link properties like nss, rate flags and
5458 * operating frequency for the active connection with the given peer.
5459 *
5460 * Return: 0 on success and errno on failure
5461 */
5462static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5463 struct wireless_dev *wdev,
5464 const void *data,
5465 int data_len)
5466{
5467 int ret = 0;
5468
5469 cds_ssr_protect(__func__);
5470 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5471 wdev, data, data_len);
5472 cds_ssr_unprotect(__func__);
5473
5474 return ret;
5475}
5476
Peng Xu278d0122015-09-24 16:34:17 -07005477static const struct
5478nla_policy
5479qca_wlan_vendor_ota_test_policy
5480[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5481 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5482};
5483
5484/**
5485 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5486 * @wiphy: Pointer to wireless phy
5487 * @wdev: Pointer to wireless device
5488 * @data: Pointer to data
5489 * @data_len: Data length
5490 *
5491 * Return: 0 on success, negative errno on failure
5492 */
5493static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5494 struct wireless_dev *wdev,
5495 const void *data,
5496 int data_len)
5497{
5498 struct net_device *dev = wdev->netdev;
5499 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5500 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5501 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5502 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5503 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305504 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005505 uint32_t current_roam_state;
5506
Jeff Johnson1f61b612016-02-12 16:28:33 -08005507 ENTER_DEV(dev);
5508
Anurag Chouhan6d760662016-02-20 16:05:43 +05305509 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005510 hdd_err("Command not allowed in FTM mode");
5511 return -EPERM;
5512 }
5513
5514 if (0 != wlan_hdd_validate_context(hdd_ctx))
5515 return -EINVAL;
5516
5517 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5518 data, data_len,
5519 qca_wlan_vendor_ota_test_policy)) {
5520 hdd_err("invalid attr");
5521 return -EINVAL;
5522 }
5523
5524 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5525 hdd_err("attr ota test failed");
5526 return -EINVAL;
5527 }
5528
5529 ota_enable = nla_get_u8(
5530 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5531
5532 hdd_info(" OTA test enable = %d", ota_enable);
5533 if (ota_enable != 1) {
5534 hdd_err("Invalid value, only enable test mode is supported!");
5535 return -EINVAL;
5536 }
5537
5538 current_roam_state =
5539 sme_get_current_roam_state(hal, adapter->sessionId);
5540 status = sme_stop_roaming(hal, adapter->sessionId,
5541 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305542 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005543 hdd_err("Enable/Disable roaming failed");
5544 return -EINVAL;
5545 }
5546
5547 status = sme_ps_enable_disable(hal, adapter->sessionId,
5548 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305549 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005550 hdd_err("Enable/Disable power save failed");
5551 /* restore previous roaming setting */
5552 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5553 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5554 status = sme_start_roaming(hal, adapter->sessionId,
5555 eCsrHddIssued);
5556 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5557 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5558 status = sme_stop_roaming(hal, adapter->sessionId,
5559 eCsrHddIssued);
5560
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305561 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005562 hdd_err("Restoring roaming state failed");
5563
5564 return -EINVAL;
5565 }
5566
5567
5568 return 0;
5569}
5570
5571/**
5572 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5573 * @wiphy: Pointer to wireless phy
5574 * @wdev: Pointer to wireless device
5575 * @data: Pointer to data
5576 * @data_len: Data length
5577 *
5578 * Return: 0 on success, negative errno on failure
5579 */
5580static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5581 struct wireless_dev *wdev,
5582 const void *data,
5583 int data_len)
5584{
5585 int ret = 0;
5586
5587 cds_ssr_protect(__func__);
5588 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5589 cds_ssr_unprotect(__func__);
5590
5591 return ret;
5592}
5593
Peng Xu4d67c8f2015-10-16 16:02:26 -07005594/**
5595 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5596 * @wiphy: Pointer to wireless phy
5597 * @wdev: Pointer to wireless device
5598 * @data: Pointer to data
5599 * @data_len: Data length
5600 *
5601 * Return: 0 on success, negative errno on failure
5602 */
5603static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5604 struct wireless_dev *wdev,
5605 const void *data,
5606 int data_len)
5607{
5608 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5609 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005610 hdd_adapter_t *adapter;
5611 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005612 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5613 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005614 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005615
Jeff Johnson1f61b612016-02-12 16:28:33 -08005616 ENTER_DEV(dev);
5617
Peng Xu4d67c8f2015-10-16 16:02:26 -07005618 ret = wlan_hdd_validate_context(hdd_ctx);
5619 if (ret)
5620 return ret;
5621
5622 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5623
5624 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5625 data, data_len, NULL)) {
5626 hdd_err("Invalid ATTR");
5627 return -EINVAL;
5628 }
5629
5630 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5631 hdd_err("attr tx power scale failed");
5632 return -EINVAL;
5633 }
5634
5635 scale_value = nla_get_u8(tb
5636 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5637
5638 if (scale_value > MAX_TXPOWER_SCALE) {
5639 hdd_err("Invalid tx power scale level");
5640 return -EINVAL;
5641 }
5642
Peng Xu62c8c432016-05-09 15:23:02 -07005643 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005644
Peng Xu62c8c432016-05-09 15:23:02 -07005645 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005646 hdd_err("Set tx power scale failed");
5647 return -EINVAL;
5648 }
5649
5650 return 0;
5651}
5652
5653/**
5654 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5655 * @wiphy: Pointer to wireless phy
5656 * @wdev: Pointer to wireless device
5657 * @data: Pointer to data
5658 * @data_len: Data length
5659 *
5660 * Return: 0 on success, negative errno on failure
5661 */
5662static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5663 struct wireless_dev *wdev,
5664 const void *data,
5665 int data_len)
5666{
Peng Xu62c8c432016-05-09 15:23:02 -07005667 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005668
5669 cds_ssr_protect(__func__);
5670 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5671 data, data_len);
5672 cds_ssr_unprotect(__func__);
5673
5674 return ret;
5675}
5676
5677/**
5678 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5679 * @wiphy: Pointer to wireless phy
5680 * @wdev: Pointer to wireless device
5681 * @data: Pointer to data
5682 * @data_len: Data length
5683 *
5684 * Return: 0 on success, negative errno on failure
5685 */
5686static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5687 struct wireless_dev *wdev,
5688 const void *data,
5689 int data_len)
5690{
5691 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5692 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005693 hdd_adapter_t *adapter;
5694 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005695 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5696 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005697 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005698
Jeff Johnson1f61b612016-02-12 16:28:33 -08005699 ENTER_DEV(dev);
5700
Peng Xu4d67c8f2015-10-16 16:02:26 -07005701 ret = wlan_hdd_validate_context(hdd_ctx);
5702 if (ret)
5703 return ret;
5704
5705 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5706
5707 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5708 data, data_len, NULL)) {
5709 hdd_err("Invalid ATTR");
5710 return -EINVAL;
5711 }
5712
5713 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5714 hdd_err("attr tx power decrease db value failed");
5715 return -EINVAL;
5716 }
5717
5718 scale_value = nla_get_u8(tb
5719 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5720
Peng Xu62c8c432016-05-09 15:23:02 -07005721 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5722 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005723
Peng Xu62c8c432016-05-09 15:23:02 -07005724 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005725 hdd_err("Set tx power decrease db failed");
5726 return -EINVAL;
5727 }
5728
5729 return 0;
5730}
5731
5732/**
5733 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5734 * @wiphy: Pointer to wireless phy
5735 * @wdev: Pointer to wireless device
5736 * @data: Pointer to data
5737 * @data_len: Data length
5738 *
5739 * Return: 0 on success, negative errno on failure
5740 */
5741static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5742 struct wireless_dev *wdev,
5743 const void *data,
5744 int data_len)
5745{
Peng Xu62c8c432016-05-09 15:23:02 -07005746 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005747
5748 cds_ssr_protect(__func__);
5749 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5750 data, data_len);
5751 cds_ssr_unprotect(__func__);
5752
5753 return ret;
5754}
Peng Xu8fdaa492016-06-22 10:20:47 -07005755
5756/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305757 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5758 * @wiphy: Pointer to wireless phy
5759 * @wdev: Pointer to wireless device
5760 * @data: Pointer to data
5761 * @data_len: Data length
5762 *
5763 * Processes the conditional channel switch request and invokes the helper
5764 * APIs to process the channel switch request.
5765 *
5766 * Return: 0 on success, negative errno on failure
5767 */
5768static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5769 struct wireless_dev *wdev,
5770 const void *data,
5771 int data_len)
5772{
5773 int ret;
5774 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5775 struct net_device *dev = wdev->netdev;
5776 hdd_adapter_t *adapter;
5777 struct nlattr
5778 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5779 uint32_t freq_len, i;
5780 uint32_t *freq;
5781 uint8_t chans[QDF_MAX_NUM_CHAN];
5782
5783 ENTER_DEV(dev);
5784
5785 ret = wlan_hdd_validate_context(hdd_ctx);
5786 if (ret)
5787 return ret;
5788
5789 if (!hdd_ctx->config->enableDFSMasterCap) {
5790 hdd_err("DFS master capability is not present in the driver");
5791 return -EINVAL;
5792 }
5793
5794 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5795 hdd_err("Command not allowed in FTM mode");
5796 return -EPERM;
5797 }
5798
5799 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5800 if (adapter->device_mode != QDF_SAP_MODE) {
5801 hdd_err("Invalid device mode %d", adapter->device_mode);
5802 return -EINVAL;
5803 }
5804
5805 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
5806 data, data_len, NULL)) {
5807 hdd_err("Invalid ATTR");
5808 return -EINVAL;
5809 }
5810
5811 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
5812 hdd_err("Frequency list is missing");
5813 return -EINVAL;
5814 }
5815
5816 freq_len = nla_len(
5817 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
5818 sizeof(uint32_t);
5819
5820 if (freq_len > QDF_MAX_NUM_CHAN) {
5821 hdd_err("insufficient space to hold channels");
5822 return -ENOMEM;
5823 }
5824
5825 hdd_debug("freq_len=%d", freq_len);
5826
5827 freq = nla_data(
5828 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
5829
5830
5831 for (i = 0; i < freq_len; i++) {
5832 if (freq[i] == 0)
5833 chans[i] = 0;
5834 else
5835 chans[i] = ieee80211_frequency_to_channel(freq[i]);
5836
5837 hdd_debug("freq[%d]=%d", i, freq[i]);
5838 }
5839
5840 /*
5841 * The input frequency list from user space is designed to be a
5842 * priority based frequency list. This is only to accommodate any
5843 * future request. But, current requirement is only to perform CAC
5844 * on a single channel. So, the first entry from the list is picked.
5845 *
5846 * If channel is zero, any channel in the available outdoor regulatory
5847 * domain will be selected.
5848 */
5849 ret = wlan_hdd_request_pre_cac(chans[0]);
5850 if (ret) {
5851 hdd_err("pre cac request failed with reason:%d", ret);
5852 return ret;
5853 }
5854
5855 return 0;
5856}
5857
5858/**
Peng Xu8fdaa492016-06-22 10:20:47 -07005859 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
5860 * @wiphy: Pointer to wireless phy
5861 * @wdev: Pointer to wireless device
5862 * @data: Pointer to data
5863 * @data_len: Data length
5864 *
5865 * This function is to process the p2p listen offload start vendor
5866 * command. It parses the input parameters and invoke WMA API to
5867 * send the command to firmware.
5868 *
5869 * Return: 0 on success, negative errno on failure
5870 */
5871static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
5872 struct wireless_dev *wdev,
5873 const void *data,
5874 int data_len)
5875{
5876 int ret;
5877 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5878 struct net_device *dev = wdev->netdev;
5879 hdd_adapter_t *adapter;
5880 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
5881 struct sir_p2p_lo_start params;
5882 QDF_STATUS status;
5883
5884 ENTER_DEV(dev);
5885
5886 ret = wlan_hdd_validate_context(hdd_ctx);
5887 if (ret)
5888 return ret;
5889
5890 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5891 hdd_err("Command not allowed in FTM mode");
5892 return -EPERM;
5893 }
5894
5895 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5896 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
5897 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
5898 (adapter->device_mode != QDF_P2P_GO_MODE)) {
5899 hdd_err("Invalid device mode %d", adapter->device_mode);
5900 return -EINVAL;
5901 }
5902
5903 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
5904 data, data_len, NULL)) {
5905 hdd_err("Invalid ATTR");
5906 return -EINVAL;
5907 }
5908
5909 memset(&params, 0, sizeof(params));
5910
5911 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
5912 params.ctl_flags = 1; /* set to default value */
5913 else
5914 params.ctl_flags = nla_get_u32(tb
5915 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
5916
5917 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
5918 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
5919 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
5920 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
5921 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
5922 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
5923 hdd_err("Attribute parsing failed");
5924 return -EINVAL;
5925 }
5926
5927 params.vdev_id = adapter->sessionId;
5928 params.freq = nla_get_u32(tb
5929 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
5930 if ((params.freq != 2412) && (params.freq != 2437) &&
5931 (params.freq != 2462)) {
5932 hdd_err("Invalid listening channel: %d", params.freq);
5933 return -EINVAL;
5934 }
5935
5936 params.period = nla_get_u32(tb
5937 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
5938 if (!((params.period > 0) && (params.period < UINT_MAX))) {
5939 hdd_err("Invalid period: %d", params.period);
5940 return -EINVAL;
5941 }
5942
5943 params.interval = nla_get_u32(tb
5944 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
5945 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
5946 hdd_err("Invalid interval: %d", params.interval);
5947 return -EINVAL;
5948 }
5949
5950 params.count = nla_get_u32(tb
5951 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
5952 if (!((params.count > 0) && (params.count < UINT_MAX))) {
5953 hdd_err("Invalid count: %d", params.count);
5954 return -EINVAL;
5955 }
5956
5957 params.device_types = nla_data(tb
5958 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
5959 if (params.device_types == NULL) {
5960 hdd_err("Invalid device types");
5961 return -EINVAL;
5962 }
5963
5964 params.dev_types_len = nla_len(tb
5965 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
5966 if (params.dev_types_len < 8) {
5967 hdd_err("Invalid device type length: %d", params.dev_types_len);
5968 return -EINVAL;
5969 }
5970
5971 params.probe_resp_tmplt = nla_data(tb
5972 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
5973 if (params.probe_resp_tmplt == NULL) {
5974 hdd_err("Invalid probe response template");
5975 return -EINVAL;
5976 }
5977
5978 params.probe_resp_len = nla_len(tb
5979 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
5980 if (params.probe_resp_len == 0) {
5981 hdd_err("Invalid probe resp template length: %d",
5982 params.probe_resp_len);
5983 return -EINVAL;
5984 }
5985
5986 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
5987 params.freq, params.period, params.interval, params.count);
5988
5989 status = wma_p2p_lo_start(&params);
5990
5991 if (!QDF_IS_STATUS_SUCCESS(status)) {
5992 hdd_err("P2P LO start failed");
5993 return -EINVAL;
5994 }
5995
5996 return 0;
5997}
5998
5999
6000/**
6001 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6002 * @wiphy: Pointer to wireless phy
6003 * @wdev: Pointer to wireless device
6004 * @data: Pointer to data
6005 * @data_len: Data length
6006 *
6007 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6008 * to process p2p listen offload start vendor command.
6009 *
6010 * Return: 0 on success, negative errno on failure
6011 */
6012static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6013 struct wireless_dev *wdev,
6014 const void *data,
6015 int data_len)
6016{
6017 int ret = 0;
6018
6019 cds_ssr_protect(__func__);
6020 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6021 data, data_len);
6022 cds_ssr_unprotect(__func__);
6023
6024 return ret;
6025}
6026
6027/**
6028 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6029 * @wiphy: Pointer to wireless phy
6030 * @wdev: Pointer to wireless device
6031 * @data: Pointer to data
6032 * @data_len: Data length
6033 *
6034 * This function is to process the p2p listen offload stop vendor
6035 * command. It invokes WMA API to send command to firmware.
6036 *
6037 * Return: 0 on success, negative errno on failure
6038 */
6039static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6040 struct wireless_dev *wdev,
6041 const void *data,
6042 int data_len)
6043{
6044 QDF_STATUS status;
6045 hdd_adapter_t *adapter;
6046 struct net_device *dev = wdev->netdev;
6047
6048 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6049 hdd_err("Command not allowed in FTM mode");
6050 return -EPERM;
6051 }
6052
6053 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6054 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6055 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6056 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6057 hdd_err("Invalid device mode");
6058 return -EINVAL;
6059 }
6060
6061 status = wma_p2p_lo_stop(adapter->sessionId);
6062
6063 if (!QDF_IS_STATUS_SUCCESS(status)) {
6064 hdd_err("P2P LO stop failed");
6065 return -EINVAL;
6066 }
6067
6068 return 0;
6069}
6070
6071/**
6072 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6073 * @wiphy: Pointer to wireless phy
6074 * @wdev: Pointer to wireless device
6075 * @data: Pointer to data
6076 * @data_len: Data length
6077 *
6078 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6079 * to process p2p listen offload stop vendor command.
6080 *
6081 * Return: 0 on success, negative errno on failure
6082 */
6083static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6084 struct wireless_dev *wdev,
6085 const void *data,
6086 int data_len)
6087{
6088 int ret = 0;
6089
6090 cds_ssr_protect(__func__);
6091 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6092 data, data_len);
6093 cds_ssr_unprotect(__func__);
6094
6095 return ret;
6096}
6097
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306098/**
6099 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6100 * @wiphy: Pointer to wireless phy
6101 * @wdev: Pointer to wireless device
6102 * @data: Pointer to data
6103 * @data_len: Data length
6104 *
6105 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6106 * to process the conditional channel switch request.
6107 *
6108 * Return: 0 on success, negative errno on failure
6109 */
6110static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6111 struct wireless_dev *wdev,
6112 const void *data,
6113 int data_len)
6114{
6115 int ret;
6116
6117 cds_ssr_protect(__func__);
6118 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6119 data, data_len);
6120 cds_ssr_unprotect(__func__);
6121
6122 return ret;
6123}
6124
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306125/*
6126 * define short names for the global vendor params
6127 * used by __wlan_hdd_cfg80211_bpf_offload()
6128 */
6129#define BPF_INVALID \
6130 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6131#define BPF_SET_RESET \
6132 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6133#define BPF_VERSION \
6134 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6135#define BPF_FILTER_ID \
6136 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6137#define BPF_PACKET_SIZE \
6138 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6139#define BPF_CURRENT_OFFSET \
6140 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6141#define BPF_PROGRAM \
6142 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6143#define BPF_MAX \
6144 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006145
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306146static const struct nla_policy
6147wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6148 [BPF_SET_RESET] = {.type = NLA_U32},
6149 [BPF_VERSION] = {.type = NLA_U32},
6150 [BPF_FILTER_ID] = {.type = NLA_U32},
6151 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6152 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6153 [BPF_PROGRAM] = {.type = NLA_U8},
6154};
6155
6156/**
6157 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6158 * @hdd_context: hdd_context
6159 * @bpf_get_offload: struct for get offload
6160 *
6161 * This function receives the response/data from the lower layer and
6162 * checks to see if the thread is still waiting then post the results to
6163 * upper layer, if the request has timed out then ignore.
6164 *
6165 * Return: None
6166 */
6167void hdd_get_bpf_offload_cb(void *hdd_context,
6168 struct sir_bpf_get_offload *data)
6169{
6170 hdd_context_t *hdd_ctx = hdd_context;
6171 struct hdd_bpf_context *context;
6172
6173 ENTER();
6174
6175 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006176 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306177 data);
6178 return;
6179 }
6180
6181 spin_lock(&hdd_context_lock);
6182
6183 context = &bpf_context;
6184 /* The caller presumably timed out so there is nothing we can do */
6185 if (context->magic != BPF_CONTEXT_MAGIC) {
6186 spin_unlock(&hdd_context_lock);
6187 return;
6188 }
6189
6190 /* context is valid so caller is still waiting */
6191 /* paranoia: invalidate the magic */
6192 context->magic = 0;
6193
6194 context->capability_response = *data;
6195 complete(&context->completion);
6196
6197 spin_unlock(&hdd_context_lock);
6198
6199 return;
6200}
6201
6202/**
6203 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6204 * @hdd_context: hdd_context
6205 * @bpf_get_offload: struct for get offload
6206 *
6207 * Return: 0 on success, error number otherwise.
6208 */
6209static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6210 struct sir_bpf_get_offload *bpf_get_offload)
6211{
6212 struct sk_buff *skb;
6213 uint32_t nl_buf_len;
6214
6215 ENTER();
6216
6217 nl_buf_len = NLMSG_HDRLEN;
6218 nl_buf_len +=
6219 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6220 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6221
6222 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6223 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006224 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306225 return -ENOMEM;
6226 }
6227
Jeff Johnson77848112016-06-29 14:52:06 -07006228 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306229 bpf_get_offload->bpf_version,
6230 bpf_get_offload->max_bytes_for_bpf_inst);
6231
6232 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6233 bpf_get_offload->max_bytes_for_bpf_inst) ||
6234 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006235 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306236 goto nla_put_failure;
6237 }
6238
6239 cfg80211_vendor_cmd_reply(skb);
6240 EXIT();
6241 return 0;
6242
6243nla_put_failure:
6244 kfree_skb(skb);
6245 return -EINVAL;
6246}
6247
6248/**
6249 * hdd_get_bpf_offload - Get BPF offload Capabilities
6250 * @hdd_ctx: Hdd context
6251 *
6252 * Return: 0 on success, errno on failure
6253 */
6254static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6255{
6256 unsigned long rc;
6257 struct hdd_bpf_context *context;
6258 QDF_STATUS status;
6259 int ret;
6260
6261 ENTER();
6262
6263 spin_lock(&hdd_context_lock);
6264 context = &bpf_context;
6265 context->magic = BPF_CONTEXT_MAGIC;
6266 INIT_COMPLETION(context->completion);
6267 spin_unlock(&hdd_context_lock);
6268
6269 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6270 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006271 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306272 return -EINVAL;
6273 }
6274 /* request was sent -- wait for the response */
6275 rc = wait_for_completion_timeout(&context->completion,
6276 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6277 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006278 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306279 spin_lock(&hdd_context_lock);
6280 context->magic = 0;
6281 spin_unlock(&hdd_context_lock);
6282
6283 return -ETIMEDOUT;
6284 }
6285 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6286 &bpf_context.capability_response);
6287 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006288 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306289
6290 EXIT();
6291 return ret;
6292}
6293
6294/**
6295 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6296 * @hdd_ctx: Hdd context
6297 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306298 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306299 *
6300 * Return: 0 on success; errno on failure
6301 */
6302static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6303 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306304 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306305{
6306 struct sir_bpf_set_offload *bpf_set_offload;
6307 QDF_STATUS status;
6308 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306309 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306310
6311 ENTER();
6312
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306313 if (adapter->device_mode == QDF_STA_MODE ||
6314 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6315 if (!hdd_conn_is_connected(
6316 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6317 hdd_err("Not in Connected state!");
6318 return -ENOTSUPP;
6319 }
6320 }
6321
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306322 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6323 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006324 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306325 return -ENOMEM;
6326 }
6327 qdf_mem_zero(bpf_set_offload, sizeof(*bpf_set_offload));
6328
6329 /* Parse and fetch bpf packet size */
6330 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006331 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306332 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306333 goto fail;
6334 }
6335 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6336
6337 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006338 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306339 goto post_sme;
6340 }
6341
6342 /* Parse and fetch bpf program */
6343 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006344 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306345 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306346 goto fail;
6347 }
6348
6349 prog_len = nla_len(tb[BPF_PROGRAM]);
6350 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306351
6352 if (bpf_set_offload->program == NULL) {
6353 hdd_err("qdf_mem_malloc failed for bpf offload program");
6354 ret = -ENOMEM;
6355 goto fail;
6356 }
6357
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306358 bpf_set_offload->current_length = prog_len;
6359 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306360 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306361
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306362 hdd_info("BPF set instructions");
6363 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6364 bpf_set_offload->program, prog_len);
6365
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306366 /* Parse and fetch filter Id */
6367 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006368 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306369 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306370 goto fail;
6371 }
6372 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6373
6374 /* Parse and fetch current offset */
6375 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006376 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306377 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306378 goto fail;
6379 }
6380 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6381
6382post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006383 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 +05306384 bpf_set_offload->session_id,
6385 bpf_set_offload->version,
6386 bpf_set_offload->filter_id,
6387 bpf_set_offload->total_length,
6388 bpf_set_offload->current_length,
6389 bpf_set_offload->current_offset);
6390
6391 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6392 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006393 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306394 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306395 goto fail;
6396 }
6397 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306398
6399fail:
6400 if (bpf_set_offload->current_length)
6401 qdf_mem_free(bpf_set_offload->program);
6402 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306403 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306404}
6405
6406/**
6407 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6408 * @wiphy: wiphy structure pointer
6409 * @wdev: Wireless device structure pointer
6410 * @data: Pointer to the data received
6411 * @data_len: Length of @data
6412 *
6413 * Return: 0 on success; errno on failure
6414 */
6415static int
6416__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6417 struct wireless_dev *wdev,
6418 const void *data, int data_len)
6419{
6420 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6421 struct net_device *dev = wdev->netdev;
6422 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6423 struct nlattr *tb[BPF_MAX + 1];
6424 int ret_val, packet_filter_subcmd;
6425
6426 ENTER();
6427
6428 ret_val = wlan_hdd_validate_context(hdd_ctx);
6429 if (ret_val)
6430 return ret_val;
6431
6432 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006433 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306434 return -EINVAL;
6435 }
6436
6437 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006438 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306439 return -ENOTSUPP;
6440 }
6441
6442 if (nla_parse(tb, BPF_MAX, data, data_len,
6443 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006444 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306445 return -EINVAL;
6446 }
6447
6448 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006449 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306450 return -EINVAL;
6451 }
6452
6453 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6454
6455 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6456 return hdd_get_bpf_offload(hdd_ctx);
6457 else
6458 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306459 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306460}
6461
6462/**
6463 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6464 * @wiphy: wiphy structure pointer
6465 * @wdev: Wireless device structure pointer
6466 * @data: Pointer to the data received
6467 * @data_len: Length of @data
6468 *
6469 * Return: 0 on success; errno on failure
6470 */
6471
6472static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6473 struct wireless_dev *wdev,
6474 const void *data, int data_len)
6475{
6476 int ret;
6477
6478 cds_ssr_protect(__func__);
6479 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6480 cds_ssr_unprotect(__func__);
6481
6482 return ret;
6483}
6484
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306485/**
6486 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6487 * @pre_cac_adapter: AP adapter used for pre cac
6488 * @status: Status (true or false)
6489 * @handle: Global handle
6490 *
6491 * Sets the status of pre cac i.e., whether the pre cac is active or not
6492 *
6493 * Return: Zero on success, non-zero on failure
6494 */
6495static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6496 bool status, tHalHandle handle)
6497{
6498 QDF_STATUS ret;
6499
6500 ret = wlan_sap_set_pre_cac_status(
6501 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6502 if (QDF_IS_STATUS_ERROR(ret))
6503 return -EINVAL;
6504
6505 return 0;
6506}
6507
6508/**
6509 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6510 * @ap_adapter: AP adapter
6511 * @chan_before_pre_cac: Channel
6512 *
6513 * Saves the channel which the AP was beaconing on before moving to the pre
6514 * cac channel. If radar is detected on the pre cac channel, this saved
6515 * channel will be used for AP operations.
6516 *
6517 * Return: Zero on success, non-zero on failure
6518 */
6519static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6520 uint8_t chan_before_pre_cac)
6521{
6522 QDF_STATUS ret;
6523
6524 ret = wlan_sap_set_chan_before_pre_cac(
6525 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6526 if (QDF_IS_STATUS_ERROR(ret))
6527 return -EINVAL;
6528
6529 return 0;
6530}
6531
6532/**
6533 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6534 * @ap_adapter: AP adapter
6535 * @nol: Non-occupancy list
6536 * @nol_len: Length of NOL
6537 *
6538 * Get the NOL for SAP
6539 *
6540 * Return: Zero on success, non-zero on failure
6541 */
6542static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6543 uint32_t *nol_len)
6544{
6545 QDF_STATUS ret;
6546
6547 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6548 nol, nol_len);
6549 if (QDF_IS_STATUS_ERROR(ret))
6550 return -EINVAL;
6551
6552 return 0;
6553}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306554
6555/**
6556 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6557 * @hdd_ctx: HDD context
6558 * @ap_adapter: AP adapter
6559 * @channel: Channel requested by userspace
6560 * @pre_cac_chan: Pointer to the pre CAC channel
6561 *
6562 * Validates the channel provided by userspace. If user provided channel 0,
6563 * a valid outdoor channel must be selected from the regulatory channel.
6564 *
6565 * Return: Zero on success and non zero value on error
6566 */
6567int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6568 hdd_adapter_t *ap_adapter,
6569 uint8_t channel,
6570 uint8_t *pre_cac_chan)
6571{
6572 uint32_t i, j;
6573 QDF_STATUS status;
6574 int ret;
6575 uint8_t nol[QDF_MAX_NUM_CHAN];
6576 uint32_t nol_len = 0, weight_len = 0;
6577 bool found;
6578 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6579 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6580 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6581
6582 if (0 == channel) {
6583 /* Channel is not obtained from PCL because PCL may not have
6584 * the entire channel list. For example: if SAP is up on
6585 * channel 6 and PCL is queried for the next SAP interface,
6586 * if SCC is preferred, the PCL will contain only the channel
6587 * 6. But, we are in need of a DFS channel. So, going with the
6588 * first channel from the valid channel list.
6589 */
6590 status = cds_get_valid_chans(channel_list, &len);
6591 if (QDF_IS_STATUS_ERROR(status)) {
6592 hdd_err("Failed to get channel list");
6593 return -EINVAL;
6594 }
6595 cds_update_with_safe_channel_list(channel_list, &len,
6596 pcl_weights, weight_len);
6597 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6598 for (i = 0; i < len; i++) {
6599 found = false;
6600 for (j = 0; j < nol_len; j++) {
6601 if (channel_list[i] == nol[j]) {
6602 found = true;
6603 break;
6604 }
6605 }
6606 if (found)
6607 continue;
6608 if (CDS_IS_DFS_CH(channel_list[i])) {
6609 *pre_cac_chan = channel_list[i];
6610 break;
6611 }
6612 }
6613 if (*pre_cac_chan == 0) {
6614 hdd_err("unable to find outdoor channel");
6615 return -EINVAL;
6616 }
6617 } else {
6618 /* Only when driver selects a channel, check is done for
6619 * unnsafe and NOL channels. When user provides a fixed channel
6620 * the user is expected to take care of this.
6621 */
6622 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6623 !CDS_IS_DFS_CH(channel)) {
6624 hdd_err("Invalid channel for pre cac:%d", channel);
6625 return -EINVAL;
6626 } else {
6627 *pre_cac_chan = channel;
6628 }
6629 }
6630 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6631 return 0;
6632}
6633
6634/**
6635 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6636 * @channel: Channel option provided by userspace
6637 *
6638 * Sets the driver to the required hardware mode and start an adapater for
6639 * pre CAC which will mimic an AP.
6640 *
6641 * Return: Zero on success, non-zero value on error
6642 */
6643int wlan_hdd_request_pre_cac(uint8_t channel)
6644{
6645 uint8_t pre_cac_chan = 0;
6646 hdd_context_t *hdd_ctx;
6647 int ret;
6648 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6649 hdd_ap_ctx_t *hdd_ap_ctx;
6650 QDF_STATUS status;
6651 struct wiphy *wiphy;
6652 struct net_device *dev;
6653 struct cfg80211_chan_def chandef;
6654 enum nl80211_channel_type channel_type;
6655 uint32_t freq;
6656 struct ieee80211_channel *chan;
6657 tHalHandle handle;
6658 bool val;
6659
6660 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6661 if (0 != wlan_hdd_validate_context(hdd_ctx))
6662 return -EINVAL;
6663
6664 if (cds_get_connection_count() > 1) {
6665 hdd_err("pre cac not allowed in concurrency");
6666 return -EINVAL;
6667 }
6668
6669 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6670 if (!ap_adapter) {
6671 hdd_err("unable to get SAP adapter");
6672 return -EINVAL;
6673 }
6674
6675 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6676 if (!handle) {
6677 hdd_err("Invalid handle");
6678 return -EINVAL;
6679 }
6680
6681 val = wlan_sap_is_pre_cac_active(handle);
6682 if (val) {
6683 hdd_err("pre cac is already in progress");
6684 return -EINVAL;
6685 }
6686
6687 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6688 if (!hdd_ap_ctx) {
6689 hdd_err("SAP context is NULL");
6690 return -EINVAL;
6691 }
6692
6693 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6694 hdd_err("SAP is already on DFS channel:%d",
6695 hdd_ap_ctx->operatingChannel);
6696 return -EINVAL;
6697 }
6698
6699 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6700 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6701 hdd_ap_ctx->operatingChannel);
6702 return -EINVAL;
6703 }
6704
6705 hdd_info("channel:%d", channel);
6706
6707 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6708 &pre_cac_chan);
6709 if (ret != 0)
6710 return ret;
6711
6712 /* Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
6713 * connection update should result in DBS mode
6714 */
6715 status = cds_update_and_wait_for_connection_update(
6716 ap_adapter->sessionId,
6717 pre_cac_chan,
6718 SIR_UPDATE_REASON_PRE_CAC);
6719 if (QDF_IS_STATUS_ERROR(status)) {
6720 hdd_err("error in moving to DBS mode");
6721 return -EINVAL;
6722 }
6723
6724 hdd_debug("starting pre cac SAP adapter");
6725
6726 /* Starting a SAP adapter:
6727 * Instead of opening an adapter, we could just do a SME open session
6728 * for AP type. But, start BSS would still need an adapter.
6729 * So, this option is not taken.
6730 *
6731 * hdd open adapter is going to register this precac interface with
6732 * user space. This interface though exposed to user space will be in
6733 * DOWN state. Consideration was done to avoid this registration to the
6734 * user space. But, as part of SAP operations multiple events are sent
6735 * to user space. Some of these events received from unregistered
6736 * interface was causing crashes. So, retaining the registration.
6737 *
6738 * So, this interface would remain registered and will remain in DOWN
6739 * state for the CAC duration. We will add notes in the feature
6740 * announcement to not use this temporary interface for any activity
6741 * from user space.
6742 */
6743 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
6744 wlan_hdd_get_intf_addr(hdd_ctx),
6745 NET_NAME_UNKNOWN, true);
6746 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306747 hdd_err("error opening the pre cac adapter");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306748 return -EINVAL;
6749 }
6750
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306751 /*
6752 * This interface is internally created by the driver. So, no interface
6753 * up comes for this interface from user space and hence starting
6754 * the adapter internally.
6755 */
6756 if (hdd_start_adapter(pre_cac_adapter)) {
6757 hdd_err("error starting the pre cac adapter");
6758 goto close_pre_cac_adapter;
6759 }
6760
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306761 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6762
6763 wiphy = hdd_ctx->wiphy;
6764 dev = pre_cac_adapter->dev;
6765
6766 /* Since this is only a dummy interface lets us use the IEs from the
6767 * other active SAP interface. In regular scenarios, these IEs would
6768 * come from the user space entity
6769 */
6770 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6771 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6772 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6773 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306774 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306775 }
6776 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6777 ap_adapter->sessionCtx.ap.beacon,
6778 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6779 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6780 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6781 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6782 ap_adapter->sessionCtx.ap.sapConfig.authType;
6783
6784 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6785 * to operate on the same bandwidth as that of the 2.4GHz operations.
6786 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6787 */
6788 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6789 case CH_WIDTH_20MHZ:
6790 channel_type = NL80211_CHAN_HT20;
6791 break;
6792 case CH_WIDTH_40MHZ:
6793 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6794 ap_adapter->sessionCtx.ap.sapConfig.channel)
6795 channel_type = NL80211_CHAN_HT40PLUS;
6796 else
6797 channel_type = NL80211_CHAN_HT40MINUS;
6798 break;
6799 default:
6800 channel_type = NL80211_CHAN_NO_HT;
6801 break;
6802 }
6803
6804 freq = cds_chan_to_freq(pre_cac_chan);
6805 chan = __ieee80211_get_channel(wiphy, freq);
6806 if (!chan) {
6807 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306808 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306809 }
6810
6811 cfg80211_chandef_create(&chandef, chan, channel_type);
6812
6813 hdd_debug("orig width:%d channel_type:%d freq:%d",
6814 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
6815 channel_type, freq);
6816
6817 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
6818 if (0 != ret) {
6819 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306820 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306821 }
6822
6823 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
6824 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
6825 eHIDDEN_SSID_NOT_IN_USE, false);
6826 if (QDF_IS_STATUS_ERROR(status)) {
6827 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306828 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306829 }
6830
6831 /*
6832 * The pre cac status is set here. But, it would not be reset explicitly
6833 * anywhere, since after the pre cac success/failure, the pre cac
6834 * adapter itself would be removed.
6835 */
6836 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
6837 if (0 != ret) {
6838 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306839 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306840 }
6841
6842 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
6843 hdd_ap_ctx->operatingChannel);
6844 if (0 != ret) {
6845 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306846 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306847 }
6848
6849 ap_adapter->pre_cac_chan = pre_cac_chan;
6850
6851 return 0;
6852
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306853stop_close_pre_cac_adapter:
6854 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306855 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
6856 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306857close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306858 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
6859 return -EINVAL;
6860}
6861
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306862/**
6863 * hdd_init_bpf_completion() - Initialize the completion event for bpf
6864 *
6865 * Return: None
6866 */
6867void hdd_init_bpf_completion(void)
6868{
6869 init_completion(&bpf_context.completion);
6870}
6871
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306872static const struct nla_policy
6873wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
6874 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
6875};
6876
Agrawal Ashish65634612016-08-18 13:24:32 +05306877static const struct nla_policy
6878wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
6879 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
6880 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
6881};
6882
6883/**
6884 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
6885 * @wiphy: Pointer to wireless phy
6886 * @wdev: Pointer to wireless device
6887 * @data: Pointer to data
6888 * @data_len: Length of @data
6889 *
6890 * This function parses the incoming NL vendor command data attributes and
6891 * updates the SAP context about channel_hint and DFS mode.
6892 * If channel_hint is set, SAP will choose that channel
6893 * as operating channel.
6894 *
6895 * If DFS mode is enabled, driver will include DFS channels
6896 * in ACS else driver will skip DFS channels.
6897 *
6898 * Return: 0 on success, negative errno on failure
6899 */
6900static int
6901__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
6902 struct wireless_dev *wdev,
6903 const void *data, int data_len)
6904{
6905 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6906 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
6907 int ret;
6908 struct acs_dfs_policy *acs_policy;
6909 int mode = DFS_MODE_NONE;
6910 int channel_hint = 0;
6911
6912 ENTER_DEV(wdev->netdev);
6913
6914 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6915 hdd_err("Command not allowed in FTM mode");
6916 return -EINVAL;
6917 }
6918
6919 ret = wlan_hdd_validate_context(hdd_ctx);
6920 if (0 != ret)
6921 return ret;
6922
6923 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
6924 data, data_len,
6925 wlan_hdd_set_acs_dfs_config_policy)) {
6926 hdd_err("invalid attr");
6927 return -EINVAL;
6928 }
6929
6930 acs_policy = &hdd_ctx->acs_policy;
6931 /*
6932 * SCM sends this attribute to restrict SAP from choosing
6933 * DFS channels from ACS.
6934 */
6935 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
6936 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
6937
6938 if (!IS_DFS_MODE_VALID(mode)) {
6939 hdd_err("attr acs dfs mode is not valid");
6940 return -EINVAL;
6941 }
6942 acs_policy->acs_dfs_mode = mode;
6943
6944 /*
6945 * SCM sends this attribute to provide an active channel,
6946 * to skip redundant ACS between drivers, and save driver start up time
6947 */
6948 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
6949 channel_hint = nla_get_u8(
6950 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
6951
6952 if (!IS_CHANNEL_VALID(channel_hint)) {
6953 hdd_err("acs channel is not valid");
6954 return -EINVAL;
6955 }
6956 acs_policy->acs_channel = channel_hint;
6957
6958 return 0;
6959}
6960
6961/**
6962 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
6963 * @wiphy: wiphy structure pointer
6964 * @wdev: Wireless device structure pointer
6965 * @data: Pointer to the data received
6966 * @data_len: Length of @data
6967 *
6968 * This function parses the incoming NL vendor command data attributes and
6969 * updates the SAP context about channel_hint and DFS mode.
6970 *
6971 * Return: 0 on success; errno on failure
6972 */
6973static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
6974 struct wireless_dev *wdev,
6975 const void *data, int data_len)
6976{
6977 int ret;
6978
6979 cds_ssr_protect(__func__);
6980 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
6981 cds_ssr_unprotect(__func__);
6982
6983 return ret;
6984}
6985
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306986/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05306987 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
6988 * @mode : cfg80211 dfs mode
6989 *
6990 * Return: return csr sta roam dfs mode else return NONE
6991 */
6992static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
6993 enum dfs_mode mode)
6994{
6995 switch (mode) {
6996 case DFS_MODE_ENABLE:
6997 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
6998 break;
6999 case DFS_MODE_DISABLE:
7000 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7001 break;
7002 case DFS_MODE_DEPRIORITIZE:
7003 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7004 break;
7005 default:
7006 hdd_err("STA Roam policy dfs mode is NONE");
7007 return CSR_STA_ROAM_POLICY_NONE;
7008 }
7009}
7010
7011static const struct nla_policy
7012wlan_hdd_set_sta_roam_config_policy[
7013QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7014 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7015 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7016};
7017
7018/**
7019 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7020 * for station connection or roaming.
7021 * @wiphy: Pointer to wireless phy
7022 * @wdev: Pointer to wireless device
7023 * @data: Pointer to data
7024 * @data_len: Length of @data
7025 *
7026 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7027 * channels needs to be skipped in scanning or not.
7028 * If dfs_mode is disabled, driver will not scan DFS channels.
7029 * If skip_unsafe_channels is set, driver will skip unsafe channels
7030 * in Scanning.
7031 *
7032 * Return: 0 on success, negative errno on failure
7033 */
7034static int
7035__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7036 struct wireless_dev *wdev,
7037 const void *data, int data_len)
7038{
7039 struct net_device *dev = wdev->netdev;
7040 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7041 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7042 struct nlattr *tb[
7043 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7044 int ret;
7045 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7046 enum dfs_mode mode = DFS_MODE_NONE;
7047 bool skip_unsafe_channels = false;
7048 QDF_STATUS status;
7049
7050 ENTER_DEV(dev);
7051
7052 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7053 hdd_err("Command not allowed in FTM mode");
7054 return -EINVAL;
7055 }
7056
7057 ret = wlan_hdd_validate_context(hdd_ctx);
7058 if (0 != ret)
7059 return ret;
7060 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7061 data, data_len,
7062 wlan_hdd_set_sta_roam_config_policy)) {
7063 hdd_err("invalid attr");
7064 return -EINVAL;
7065 }
7066 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7067 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7068 if (!IS_DFS_MODE_VALID(mode)) {
7069 hdd_err("attr sta roam dfs mode policy is not valid");
7070 return -EINVAL;
7071 }
7072
7073 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7074
7075 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7076 skip_unsafe_channels = nla_get_u8(
7077 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7078
7079 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7080 skip_unsafe_channels, adapter->sessionId);
7081
7082 if (!QDF_IS_STATUS_SUCCESS(status)) {
7083 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7084 return -EINVAL;
7085 }
7086 return 0;
7087}
7088
7089/**
7090 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7091 * connection and roaming for station.
7092 * @wiphy: wiphy structure pointer
7093 * @wdev: Wireless device structure pointer
7094 * @data: Pointer to the data received
7095 * @data_len: Length of @data
7096 *
7097 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7098 * channels needs to be skipped in scanning or not.
7099 * If dfs_mode is disabled, driver will not scan DFS channels.
7100 * If skip_unsafe_channels is set, driver will skip unsafe channels
7101 * in Scanning.
7102 * Return: 0 on success; errno on failure
7103 */
7104static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7105 struct wireless_dev *wdev,
7106 const void *data, int data_len)
7107{
7108 int ret;
7109
7110 cds_ssr_protect(__func__);
7111 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7112 cds_ssr_unprotect(__func__);
7113
7114 return ret;
7115}
7116
Agrawal Ashish467dde42016-09-08 18:44:22 +05307117#ifdef FEATURE_WLAN_CH_AVOID
7118/**
7119 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7120 * is on unsafe channel.
7121 * @wiphy: wiphy structure pointer
7122 * @wdev: Wireless device structure pointer
7123 * @data: Pointer to the data received
7124 * @data_len: Length of @data
7125 *
7126 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7127 * on any of unsafe channels.
7128 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7129 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7130 *
7131 * Return: 0 on success; errno on failure
7132 */
7133static int
7134__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7135 struct wireless_dev *wdev,
7136 const void *data, int data_len)
7137{
7138 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7139 int ret;
7140 uint16_t unsafe_channel_count;
7141 int unsafe_channel_index;
7142 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7143
7144 ENTER_DEV(wdev->netdev);
7145
7146 if (!qdf_ctx) {
7147 cds_err("qdf_ctx is NULL");
7148 return -EINVAL;
7149 }
7150
7151 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7152 hdd_err("Command not allowed in FTM mode");
7153 return -EINVAL;
7154 }
7155
7156 ret = wlan_hdd_validate_context(hdd_ctx);
7157 if (0 != ret)
7158 return ret;
7159 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7160 &(hdd_ctx->unsafe_channel_count),
7161 sizeof(hdd_ctx->unsafe_channel_list));
7162
7163 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7164 (uint16_t)NUM_CHANNELS);
7165 for (unsafe_channel_index = 0;
7166 unsafe_channel_index < unsafe_channel_count;
7167 unsafe_channel_index++) {
7168 hdd_info("Channel %d is not safe",
7169 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7170 }
7171 hdd_unsafe_channel_restart_sap(hdd_ctx);
7172 return 0;
7173}
7174
7175/**
7176 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7177 * is on unsafe channel.
7178 * @wiphy: wiphy structure pointer
7179 * @wdev: Wireless device structure pointer
7180 * @data: Pointer to the data received
7181 * @data_len: Length of @data
7182 *
7183 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7184 * on any of unsafe channels.
7185 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7186 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7187 *
7188 * Return: 0 on success; errno on failure
7189 */
7190static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7191 struct wireless_dev *wdev,
7192 const void *data, int data_len)
7193{
7194 int ret;
7195
7196 cds_ssr_protect(__func__);
7197 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7198 cds_ssr_unprotect(__func__);
7199
7200 return ret;
7201}
7202
7203#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307204/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307205 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7206 * SAP is on unsafe channel.
7207 * @wiphy: wiphy structure pointer
7208 * @wdev: Wireless device structure pointer
7209 * @data: Pointer to the data received
7210 * @data_len: Length of @data
7211 *
7212 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7213 * driver.
7214 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7215 * will initiate restart of sap.
7216 *
7217 * Return: 0 on success; errno on failure
7218 */
7219static int
7220__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7221 struct wireless_dev *wdev,
7222 const void *data, int data_len)
7223{
7224 struct net_device *ndev = wdev->netdev;
7225 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7226 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7227 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7228 uint8_t config_channel = 0;
7229 hdd_ap_ctx_t *ap_ctx;
7230 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307231 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307232
7233 ENTER();
7234
7235 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007236 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307237 return -EINVAL;
7238 }
7239
7240 ret = wlan_hdd_validate_context(hdd_ctx);
7241 if (0 != ret)
7242 return -EINVAL;
7243
7244 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7245 data, data_len,
7246 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007247 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307248 return -EINVAL;
7249 }
7250
7251 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7252 if (!test_bit(SOFTAP_BSS_STARTED,
7253 &hostapd_adapter->event_flags)) {
7254 hdd_err("SAP is not started yet. Restart sap will be invalid");
7255 return -EINVAL;
7256 }
7257
7258 config_channel =
7259 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7260
7261 if (!((IS_24G_CH(config_channel)) ||
7262 (IS_5G_CH(config_channel)))) {
7263 hdd_err("Channel %d is not valid to restart SAP",
7264 config_channel);
7265 return -ENOTSUPP;
7266 }
7267
7268 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7269 ap_ctx->sapConfig.channel = config_channel;
7270 ap_ctx->sapConfig.ch_params.ch_width =
7271 ap_ctx->sapConfig.ch_width_orig;
7272
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007273 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307274 ap_ctx->sapConfig.sec_ch,
7275 &ap_ctx->sapConfig.ch_params);
7276
7277 cds_restart_sap(hostapd_adapter);
7278 }
7279
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307280 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7281 uint32_t freq_len, i;
7282 uint32_t *freq;
7283 uint8_t chans[QDF_MAX_NUM_CHAN];
7284
7285 hdd_debug("setting mandatory freq/chan list");
7286
7287 freq_len = nla_len(
7288 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7289 sizeof(uint32_t);
7290
7291 if (freq_len > QDF_MAX_NUM_CHAN) {
7292 hdd_err("insufficient space to hold channels");
7293 return -ENOMEM;
7294 }
7295
7296 freq = nla_data(
7297 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7298
7299 hdd_debug("freq_len=%d", freq_len);
7300
7301 for (i = 0; i < freq_len; i++) {
7302 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7303 hdd_debug("freq[%d]=%d", i, freq[i]);
7304 }
7305
7306 status = cds_set_sap_mandatory_channels(chans, freq_len);
7307 if (QDF_IS_STATUS_ERROR(status))
7308 return -EINVAL;
7309 }
7310
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307311 return 0;
7312}
7313
7314/**
7315 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7316 * @wiphy: wiphy structure pointer
7317 * @wdev: Wireless device structure pointer
7318 * @data: Pointer to the data received
7319 * @data_len: Length of @data
7320 *
7321 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7322 * driver.
7323 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7324 * will initiate restart of sap.
7325 *
7326 * Return: 0 on success; errno on failure
7327 */
7328static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7329 struct wireless_dev *wdev,
7330 const void *data, int data_len)
7331{
7332 int ret;
7333
7334 cds_ssr_protect(__func__);
7335 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7336 wdev, data, data_len);
7337 cds_ssr_unprotect(__func__);
7338
7339 return ret;
7340}
7341
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307342#undef BPF_INVALID
7343#undef BPF_SET_RESET
7344#undef BPF_VERSION
7345#undef BPF_ID
7346#undef BPF_PACKET_SIZE
7347#undef BPF_CURRENT_OFFSET
7348#undef BPF_PROGRAM
7349#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307350
7351/**
7352 * define short names for the global vendor params
7353 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7354 */
7355#define PARAM_TOTAL_CMD_EVENT_WAKE \
7356 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7357#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7358 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7359#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7360 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7361#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7362 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7363#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7364 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7365#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7366 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7367#define PARAM_TOTAL_RX_DATA_WAKE \
7368 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7369#define PARAM_RX_UNICAST_CNT \
7370 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7371#define PARAM_RX_MULTICAST_CNT \
7372 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7373#define PARAM_RX_BROADCAST_CNT \
7374 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7375#define PARAM_ICMP_PKT \
7376 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7377#define PARAM_ICMP6_PKT \
7378 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7379#define PARAM_ICMP6_RA \
7380 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7381#define PARAM_ICMP6_NA \
7382 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7383#define PARAM_ICMP6_NS \
7384 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7385#define PARAM_ICMP4_RX_MULTICAST_CNT \
7386 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7387#define PARAM_ICMP6_RX_MULTICAST_CNT \
7388 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7389#define PARAM_OTHER_RX_MULTICAST_CNT \
7390 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
7391
7392
7393/**
7394 * hdd_send_wakelock_stats() - API to send wakelock stats
7395 * @ctx: context to be passed to callback
7396 * @data: data passed to callback
7397 *
7398 * This function is used to send wake lock stats to HAL layer
7399 *
7400 * Return: 0 on success, error number otherwise.
7401 */
7402static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7403 const struct sir_wake_lock_stats *data)
7404{
7405 struct sk_buff *skb;
7406 uint32_t nl_buf_len;
7407 uint32_t total_rx_data_wake, rx_multicast_cnt;
7408 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307409 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307410
7411 ENTER();
7412
7413 nl_buf_len = NLMSG_HDRLEN;
7414 nl_buf_len +=
7415 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7416 (NLMSG_HDRLEN + sizeof(uint32_t));
7417
7418 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7419
7420 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007421 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307422 return -ENOMEM;
7423 }
7424
Jeff Johnson64943bd2016-08-23 13:14:06 -07007425 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307426 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007427 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307428 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007429 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307430 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007431 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307432 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007433 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307434 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007435 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307436 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007437 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307438 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007439 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7440 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307441 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307442
7443 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307444 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307445
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307446 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307447 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307448
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307449 rx_multicast_cnt =
7450 data->wow_ipv4_mcast_wake_up_count +
7451 ipv6_rx_multicast_addr_cnt;
7452
7453 total_rx_data_wake =
7454 data->wow_ucast_wake_up_count +
7455 data->wow_bcast_wake_up_count +
7456 rx_multicast_cnt;
7457
7458 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7459 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7460 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7461 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7462 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7463 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7464 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7465 total_rx_data_wake) ||
7466 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7467 data->wow_ucast_wake_up_count) ||
7468 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7469 rx_multicast_cnt) ||
7470 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7471 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307472 nla_put_u32(skb, PARAM_ICMP_PKT,
7473 data->wow_icmpv4_count) ||
7474 nla_put_u32(skb, PARAM_ICMP6_PKT,
7475 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307476 nla_put_u32(skb, PARAM_ICMP6_RA,
7477 data->wow_ipv6_mcast_ra_stats) ||
7478 nla_put_u32(skb, PARAM_ICMP6_NA,
7479 data->wow_ipv6_mcast_na_stats) ||
7480 nla_put_u32(skb, PARAM_ICMP6_NS,
7481 data->wow_ipv6_mcast_ns_stats) ||
7482 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7483 data->wow_ipv4_mcast_wake_up_count) ||
7484 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7485 ipv6_rx_multicast_addr_cnt) ||
7486 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007487 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307488 goto nla_put_failure;
7489 }
7490
7491 cfg80211_vendor_cmd_reply(skb);
7492
7493 EXIT();
7494 return 0;
7495
7496nla_put_failure:
7497 kfree_skb(skb);
7498 return -EINVAL;
7499}
7500
7501/**
7502 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7503 * @wiphy: wiphy pointer
7504 * @wdev: pointer to struct wireless_dev
7505 * @data: pointer to incoming NL vendor data
7506 * @data_len: length of @data
7507 *
7508 * This function parses the incoming NL vendor command data attributes and
7509 * invokes the SME Api and blocks on a completion variable.
7510 * WMA copies required data and invokes callback
7511 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7512 *
7513 * Return: 0 on success; error number otherwise.
7514 */
7515static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7516 struct wireless_dev *wdev,
7517 const void *data,
7518 int data_len)
7519{
7520 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7521 int status, ret;
7522 struct sir_wake_lock_stats wake_lock_stats;
7523 QDF_STATUS qdf_status;
7524
7525 ENTER();
7526
7527 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007528 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307529 return -EINVAL;
7530 }
7531
7532 status = wlan_hdd_validate_context(hdd_ctx);
7533 if (0 != status)
7534 return -EINVAL;
7535
7536 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7537 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007538 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307539 return -EINVAL;
7540 }
7541
7542 ret = hdd_send_wakelock_stats(hdd_ctx,
7543 &wake_lock_stats);
7544 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007545 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307546
7547 EXIT();
7548 return ret;
7549}
7550
7551/**
7552 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7553 * @wiphy: wiphy pointer
7554 * @wdev: pointer to struct wireless_dev
7555 * @data: pointer to incoming NL vendor data
7556 * @data_len: length of @data
7557 *
7558 * This function parses the incoming NL vendor command data attributes and
7559 * invokes the SME Api and blocks on a completion variable.
7560 * WMA copies required data and invokes callback
7561 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7562 *
7563 * Return: 0 on success; error number otherwise.
7564 */
7565static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7566 struct wireless_dev *wdev,
7567 const void *data, int data_len)
7568{
7569 int ret;
7570
7571 cds_ssr_protect(__func__);
7572 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7573 data_len);
7574 cds_ssr_protect(__func__);
7575
7576 return ret;
7577}
7578
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307579/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307580 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7581 * @wiphy: wiphy structure pointer
7582 * @wdev: Wireless device structure pointer
7583 * @data: Pointer to the data received
7584 * @data_len: Length of @data
7585 *
7586 * This function reads wmi max bus size and fill in the skb with
7587 * NL attributes and send up the NL event.
7588 * Return: 0 on success; errno on failure
7589 */
7590static int
7591__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7592 struct wireless_dev *wdev,
7593 const void *data, int data_len)
7594{
7595 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7596 int ret_val;
7597 struct sk_buff *skb;
7598 uint32_t nl_buf_len;
7599
7600 ENTER();
7601
7602 ret_val = wlan_hdd_validate_context(hdd_ctx);
7603 if (ret_val)
7604 return ret_val;
7605
7606 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7607 hdd_err("Command not allowed in FTM mode");
7608 return -EINVAL;
7609 }
7610
7611 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7612
7613 nl_buf_len = NLMSG_HDRLEN;
7614 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7615
7616 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7617 if (!skb) {
7618 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7619 return -ENOMEM;
7620 }
7621
7622 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7623 hdd_ctx->wmi_max_len)) {
7624 hdd_err("nla put failure");
7625 goto nla_put_failure;
7626 }
7627
7628 cfg80211_vendor_cmd_reply(skb);
7629
7630 EXIT();
7631
7632 return 0;
7633
7634nla_put_failure:
7635 kfree_skb(skb);
7636 return -EINVAL;
7637}
7638
7639/**
7640 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7641 * @wiphy: wiphy structure pointer
7642 * @wdev: Wireless device structure pointer
7643 * @data: Pointer to the data received
7644 * @data_len: Length of @data
7645 *
7646 * Return: 0 on success; errno on failure
7647 */
7648static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7649 struct wireless_dev *wdev,
7650 const void *data, int data_len)
7651{
7652 int ret;
7653
7654 cds_ssr_protect(__func__);
7655 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7656 cds_ssr_unprotect(__func__);
7657
7658 return ret;
7659}
7660
7661/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307662 *__wlan_hdd_cfg80211_setband() - set band
7663 * @wiphy: Pointer to wireless phy
7664 * @wdev: Pointer to wireless device
7665 * @data: Pointer to data
7666 * @data_len: Length of @data
7667 *
7668 * Return: 0 on success, negative errno on failure
7669 */
7670static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7671 struct wireless_dev *wdev,
7672 const void *data, int data_len)
7673{
7674 struct net_device *dev = wdev->netdev;
7675 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7676 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7677 int ret;
7678 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7679 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7680
7681 ENTER();
7682
7683 ret = wlan_hdd_validate_context(hdd_ctx);
7684 if (ret)
7685 return ret;
7686
7687 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7688 hdd_err(FL("Invalid ATTR"));
7689 return -EINVAL;
7690 }
7691
7692 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7693 hdd_err(FL("attr SETBAND_VALUE failed"));
7694 return -EINVAL;
7695 }
7696
7697 ret = hdd_set_band(dev,
7698 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7699
7700 EXIT();
7701 return ret;
7702}
7703
7704/**
7705 * wlan_hdd_cfg80211_setband() - Wrapper to setband
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_setband(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_setband(wiphy, wdev, data, data_len);
7721 cds_ssr_unprotect(__func__);
7722
7723 return ret;
7724}
7725
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307726static const struct
7727nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7728 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7729 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7730 .len = QDF_MAC_ADDR_SIZE},
7731};
7732
7733/**
7734 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7735 * @wiphy: Pointer to wireless phy
7736 * @wdev: Pointer to wireless device
7737 * @data: Pointer to data
7738 * @data_len: Length of @data
7739 *
7740 * This function is used to enable/disable roaming using vendor commands
7741 *
7742 * Return: 0 on success, negative errno on failure
7743 */
7744static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7745 struct wireless_dev *wdev,
7746 const void *data, int data_len)
7747{
7748 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7749 struct net_device *dev = wdev->netdev;
7750 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7751 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7752 uint32_t is_fast_roam_enabled;
7753 int ret;
7754
7755 ENTER_DEV(dev);
7756
7757 ret = wlan_hdd_validate_context(hdd_ctx);
7758 if (0 != ret)
7759 return ret;
7760
7761 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7762 hdd_err("Command not allowed in FTM mode");
7763 return -EINVAL;
7764 }
7765
7766 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
7767 qca_wlan_vendor_attr);
7768 if (ret) {
7769 hdd_err("Invalid ATTR");
7770 return -EINVAL;
7771 }
7772
7773 /* Parse and fetch Enable flag */
7774 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
7775 hdd_err("attr enable failed");
7776 return -EINVAL;
7777 }
7778
7779 is_fast_roam_enabled = nla_get_u32(
7780 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
7781 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
7782
7783 /* Update roaming */
7784 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
7785 is_fast_roam_enabled);
7786 if (ret)
7787 hdd_err("sme_config_fast_roaming failed");
7788 EXIT();
7789 return ret;
7790}
7791
7792/**
7793 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7794 * @wiphy: Pointer to wireless phy
7795 * @wdev: Pointer to wireless device
7796 * @data: Pointer to data
7797 * @data_len: Length of @data
7798 *
7799 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
7800 *
7801 * Return: 0 on success, negative errno on failure
7802 */
7803static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7804 struct wireless_dev *wdev,
7805 const void *data, int data_len)
7806{
7807 int ret;
7808
7809 cds_ssr_protect(__func__);
7810 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
7811 cds_ssr_unprotect(__func__);
7812
7813 return ret;
7814}
7815
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007816const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
7817 {
7818 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7819 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
7820 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05307821 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007822 .doit = is_driver_dfs_capable
7823 },
7824
7825#ifdef WLAN_FEATURE_NAN
7826 {
7827 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7828 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
7829 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7830 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7831 .doit = wlan_hdd_cfg80211_nan_request
7832 },
7833#endif
7834
7835#ifdef WLAN_FEATURE_STATS_EXT
7836 {
7837 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7838 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
7839 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7840 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7841 .doit = wlan_hdd_cfg80211_stats_ext_request
7842 },
7843#endif
7844#ifdef FEATURE_WLAN_EXTSCAN
7845 {
7846 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7847 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
7848 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7849 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7850 .doit = wlan_hdd_cfg80211_extscan_start
7851 },
7852 {
7853 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7854 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
7855 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7856 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7857 .doit = wlan_hdd_cfg80211_extscan_stop
7858 },
7859 {
7860 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7861 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
7862 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7863 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
7864 },
7865 {
7866 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7867 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
7868 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7869 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7870 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
7871 },
7872 {
7873 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7874 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
7875 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7876 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7877 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
7878 },
7879 {
7880 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7881 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
7882 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7883 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7884 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
7885 },
7886 {
7887 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7888 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
7889 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7890 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7891 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
7892 },
7893 {
7894 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7895 .info.subcmd =
7896 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
7897 .flags =
7898 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7899 WIPHY_VENDOR_CMD_NEED_RUNNING,
7900 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
7901 },
7902 {
7903 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7904 .info.subcmd =
7905 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
7906 .flags =
7907 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7908 WIPHY_VENDOR_CMD_NEED_RUNNING,
7909 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
7910 },
7911 {
7912 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7913 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
7914 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7915 WIPHY_VENDOR_CMD_NEED_NETDEV |
7916 WIPHY_VENDOR_CMD_NEED_RUNNING,
7917 .doit = wlan_hdd_cfg80211_set_epno_list
7918 },
7919#endif /* FEATURE_WLAN_EXTSCAN */
7920
7921#ifdef WLAN_FEATURE_LINK_LAYER_STATS
7922 {
7923 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7924 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
7925 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7926 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7927 .doit = wlan_hdd_cfg80211_ll_stats_clear
7928 },
7929
7930 {
7931 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7932 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
7933 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7934 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7935 .doit = wlan_hdd_cfg80211_ll_stats_set
7936 },
7937
7938 {
7939 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7940 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
7941 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7942 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7943 .doit = wlan_hdd_cfg80211_ll_stats_get
7944 },
7945#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
7946#ifdef FEATURE_WLAN_TDLS
7947 {
7948 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7949 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
7950 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7951 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7952 .doit = wlan_hdd_cfg80211_exttdls_enable
7953 },
7954 {
7955 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7956 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
7957 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7958 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7959 .doit = wlan_hdd_cfg80211_exttdls_disable
7960 },
7961 {
7962 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7963 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
7964 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7965 .doit = wlan_hdd_cfg80211_exttdls_get_status
7966 },
7967#endif
7968 {
7969 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7970 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
7971 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7972 .doit = wlan_hdd_cfg80211_get_supported_features
7973 },
7974 {
7975 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7976 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
7977 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7978 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
7979 },
7980 {
7981 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7982 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
7983 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05307984 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007985 },
7986 {
7987 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7988 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
7989 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7990 WIPHY_VENDOR_CMD_NEED_NETDEV,
7991 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
7992 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07007993 {
7994 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7995 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
7996 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7997 WIPHY_VENDOR_CMD_NEED_NETDEV,
7998 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
7999 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008000 {
8001 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308002 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8003 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8004 WIPHY_VENDOR_CMD_NEED_NETDEV |
8005 WIPHY_VENDOR_CMD_NEED_RUNNING,
8006 .doit = hdd_cfg80211_get_station_cmd
8007 },
8008 {
8009 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008010 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8011 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8012 WIPHY_VENDOR_CMD_NEED_NETDEV |
8013 WIPHY_VENDOR_CMD_NEED_RUNNING,
8014 .doit = wlan_hdd_cfg80211_do_acs
8015 },
8016
8017 {
8018 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8019 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8020 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8021 WIPHY_VENDOR_CMD_NEED_NETDEV,
8022 .doit = wlan_hdd_cfg80211_get_features
8023 },
8024#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8025 {
8026 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8027 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8028 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8029 WIPHY_VENDOR_CMD_NEED_NETDEV |
8030 WIPHY_VENDOR_CMD_NEED_RUNNING,
8031 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8032 },
8033#endif
8034#ifdef FEATURE_WLAN_EXTSCAN
8035 {
8036 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8037 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8038 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8039 WIPHY_VENDOR_CMD_NEED_NETDEV |
8040 WIPHY_VENDOR_CMD_NEED_RUNNING,
8041 .doit = wlan_hdd_cfg80211_set_passpoint_list
8042 },
8043 {
8044 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8045 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8046 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8047 WIPHY_VENDOR_CMD_NEED_NETDEV |
8048 WIPHY_VENDOR_CMD_NEED_RUNNING,
8049 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8050 },
8051 {
8052 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8053 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8054 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8055 WIPHY_VENDOR_CMD_NEED_NETDEV |
8056 WIPHY_VENDOR_CMD_NEED_RUNNING,
8057 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8058 },
8059 {
8060 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8061 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8062 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8063 WIPHY_VENDOR_CMD_NEED_NETDEV |
8064 WIPHY_VENDOR_CMD_NEED_RUNNING,
8065 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8066 },
8067#endif /* FEATURE_WLAN_EXTSCAN */
8068 {
8069 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8070 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8071 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8072 WIPHY_VENDOR_CMD_NEED_NETDEV,
8073 .doit = wlan_hdd_cfg80211_get_wifi_info
8074 },
8075 {
8076 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8077 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8078 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8079 WIPHY_VENDOR_CMD_NEED_NETDEV |
8080 WIPHY_VENDOR_CMD_NEED_RUNNING,
8081 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8082 },
8083 {
8084 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8085 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8086 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8087 WIPHY_VENDOR_CMD_NEED_NETDEV,
8088 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8089 },
8090 {
8091 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8092 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8093 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8094 WIPHY_VENDOR_CMD_NEED_NETDEV,
8095 .doit = wlan_hdd_cfg80211_wifi_logger_start
8096 },
8097 {
8098 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8099 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8100 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8101 WIPHY_VENDOR_CMD_NEED_NETDEV,
8102 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8103 },
8104 {
8105 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8106 .info.subcmd =
8107 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8108 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8109 WIPHY_VENDOR_CMD_NEED_NETDEV |
8110 WIPHY_VENDOR_CMD_NEED_RUNNING,
8111 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8112 },
8113 {
8114 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8115 .info.subcmd =
8116 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8117 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8118 WIPHY_VENDOR_CMD_NEED_NETDEV |
8119 WIPHY_VENDOR_CMD_NEED_RUNNING,
8120 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8121 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008122#ifdef WLAN_FEATURE_TSF
8123 {
8124 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8125 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8126 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8127 WIPHY_VENDOR_CMD_NEED_NETDEV |
8128 WIPHY_VENDOR_CMD_NEED_RUNNING,
8129 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8130 },
8131#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008132#ifdef FEATURE_WLAN_TDLS
8133 {
8134 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8135 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8136 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8137 WIPHY_VENDOR_CMD_NEED_NETDEV |
8138 WIPHY_VENDOR_CMD_NEED_RUNNING,
8139 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8140 },
8141#endif
8142#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8143 {
8144 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8145 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8146 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8147 WIPHY_VENDOR_CMD_NEED_NETDEV |
8148 WIPHY_VENDOR_CMD_NEED_RUNNING,
8149 .doit = wlan_hdd_cfg80211_offloaded_packets
8150 },
8151#endif
8152 {
8153 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8154 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8155 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8156 WIPHY_VENDOR_CMD_NEED_NETDEV |
8157 WIPHY_VENDOR_CMD_NEED_RUNNING,
8158 .doit = wlan_hdd_cfg80211_monitor_rssi
8159 },
8160 {
8161 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308162 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8163 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8164 WIPHY_VENDOR_CMD_NEED_NETDEV |
8165 WIPHY_VENDOR_CMD_NEED_RUNNING,
8166 .doit = wlan_hdd_cfg80211_set_ns_offload
8167 },
8168 {
8169 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008170 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8171 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8172 WIPHY_VENDOR_CMD_NEED_NETDEV |
8173 WIPHY_VENDOR_CMD_NEED_RUNNING,
8174 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8175 },
8176#ifdef WLAN_FEATURE_MEMDUMP
8177 {
8178 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8179 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8180 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8181 WIPHY_VENDOR_CMD_NEED_NETDEV |
8182 WIPHY_VENDOR_CMD_NEED_RUNNING,
8183 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8184 },
8185#endif /* WLAN_FEATURE_MEMDUMP */
8186 {
8187 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8188 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8189 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8190 WIPHY_VENDOR_CMD_NEED_NETDEV |
8191 WIPHY_VENDOR_CMD_NEED_RUNNING,
8192 .doit = wlan_hdd_cfg80211_vendor_scan
8193 },
8194
8195 /* OCB commands */
8196 {
8197 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8198 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8199 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8200 WIPHY_VENDOR_CMD_NEED_NETDEV |
8201 WIPHY_VENDOR_CMD_NEED_RUNNING,
8202 .doit = wlan_hdd_cfg80211_ocb_set_config
8203 },
8204 {
8205 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8206 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8207 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8208 WIPHY_VENDOR_CMD_NEED_NETDEV |
8209 WIPHY_VENDOR_CMD_NEED_RUNNING,
8210 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8211 },
8212 {
8213 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8214 .info.subcmd =
8215 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8216 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8217 WIPHY_VENDOR_CMD_NEED_NETDEV |
8218 WIPHY_VENDOR_CMD_NEED_RUNNING,
8219 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8220 },
8221 {
8222 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8223 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8224 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8225 WIPHY_VENDOR_CMD_NEED_NETDEV |
8226 WIPHY_VENDOR_CMD_NEED_RUNNING,
8227 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8228 },
8229 {
8230 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8231 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8232 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8233 WIPHY_VENDOR_CMD_NEED_NETDEV |
8234 WIPHY_VENDOR_CMD_NEED_RUNNING,
8235 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8236 },
8237 {
8238 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8239 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8240 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8241 WIPHY_VENDOR_CMD_NEED_NETDEV |
8242 WIPHY_VENDOR_CMD_NEED_RUNNING,
8243 .doit = wlan_hdd_cfg80211_dcc_get_stats
8244 },
8245 {
8246 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8247 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8248 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8249 WIPHY_VENDOR_CMD_NEED_NETDEV |
8250 WIPHY_VENDOR_CMD_NEED_RUNNING,
8251 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8252 },
8253 {
8254 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8255 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8256 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8257 WIPHY_VENDOR_CMD_NEED_NETDEV |
8258 WIPHY_VENDOR_CMD_NEED_RUNNING,
8259 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8260 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308261 {
8262 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8263 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8264 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8265 WIPHY_VENDOR_CMD_NEED_NETDEV |
8266 WIPHY_VENDOR_CMD_NEED_RUNNING,
8267 .doit = wlan_hdd_cfg80211_get_link_properties
8268 },
Peng Xu278d0122015-09-24 16:34:17 -07008269 {
Peng Xud2220962016-07-11 17:59:17 -07008270 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008271 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8272 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8273 WIPHY_VENDOR_CMD_NEED_NETDEV |
8274 WIPHY_VENDOR_CMD_NEED_RUNNING,
8275 .doit = wlan_hdd_cfg80211_set_ota_test
8276 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008277#ifdef FEATURE_LFR_SUBNET_DETECTION
8278 {
8279 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8280 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8281 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8282 WIPHY_VENDOR_CMD_NEED_NETDEV |
8283 WIPHY_VENDOR_CMD_NEED_RUNNING,
8284 .doit = wlan_hdd_cfg80211_set_gateway_params
8285 },
8286#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008287 {
Peng Xud2220962016-07-11 17:59:17 -07008288 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008289 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8290 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8291 WIPHY_VENDOR_CMD_NEED_NETDEV |
8292 WIPHY_VENDOR_CMD_NEED_RUNNING,
8293 .doit = wlan_hdd_cfg80211_txpower_scale
8294 },
8295 {
8296 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8297 .info.subcmd =
8298 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8299 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8300 WIPHY_VENDOR_CMD_NEED_NETDEV |
8301 WIPHY_VENDOR_CMD_NEED_RUNNING,
8302 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8303 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308304 {
8305 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8306 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8307 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8308 WIPHY_VENDOR_CMD_NEED_NETDEV |
8309 WIPHY_VENDOR_CMD_NEED_RUNNING,
8310 .doit = wlan_hdd_cfg80211_bpf_offload
8311 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308312 {
8313 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308314 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8315 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8316 WIPHY_VENDOR_CMD_NEED_NETDEV |
8317 WIPHY_VENDOR_CMD_NEED_RUNNING,
8318 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8319 },
8320 {
8321 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308322 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8323 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8324 WIPHY_VENDOR_CMD_NEED_NETDEV |
8325 WIPHY_VENDOR_CMD_NEED_RUNNING,
8326 .doit = wlan_hdd_cfg80211_sta_roam_policy
8327 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308328#ifdef FEATURE_WLAN_CH_AVOID
8329 {
8330 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8331 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8332 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8333 WIPHY_VENDOR_CMD_NEED_NETDEV |
8334 WIPHY_VENDOR_CMD_NEED_RUNNING,
8335 .doit = wlan_hdd_cfg80211_avoid_freq
8336 },
8337#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308338 {
8339 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308340 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8341 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8342 WIPHY_VENDOR_CMD_NEED_NETDEV |
8343 WIPHY_VENDOR_CMD_NEED_RUNNING,
8344 .doit = wlan_hdd_cfg80211_sap_configuration_set
8345 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008346 {
Peng Xu4225c152016-07-14 21:18:14 -07008347 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008348 .info.subcmd =
8349 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8350 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8351 WIPHY_VENDOR_CMD_NEED_NETDEV |
8352 WIPHY_VENDOR_CMD_NEED_RUNNING,
8353 .doit = wlan_hdd_cfg80211_p2p_lo_start
8354 },
8355 {
8356 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8357 .info.subcmd =
8358 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8359 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8360 WIPHY_VENDOR_CMD_NEED_NETDEV |
8361 WIPHY_VENDOR_CMD_NEED_RUNNING,
8362 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8363 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308364 {
8365 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8366 .info.subcmd =
8367 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8368 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8369 WIPHY_VENDOR_CMD_NEED_NETDEV |
8370 WIPHY_VENDOR_CMD_NEED_RUNNING,
8371 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8372 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008373#ifdef WLAN_FEATURE_NAN_DATAPATH
8374 {
8375 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8376 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8377 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8378 WIPHY_VENDOR_CMD_NEED_NETDEV |
8379 WIPHY_VENDOR_CMD_NEED_RUNNING,
8380 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8381 },
8382#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308383 {
8384 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8385 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8386 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8387 WIPHY_VENDOR_CMD_NEED_NETDEV |
8388 WIPHY_VENDOR_CMD_NEED_RUNNING,
8389 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8390 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308391 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308392 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8393 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8394 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8395 WIPHY_VENDOR_CMD_NEED_NETDEV |
8396 WIPHY_VENDOR_CMD_NEED_RUNNING,
8397 .doit = wlan_hdd_cfg80211_get_bus_size
8398 },
8399 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308400 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8401 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8402 WIPHY_VENDOR_CMD_NEED_NETDEV |
8403 WIPHY_VENDOR_CMD_NEED_RUNNING,
8404 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308405 },
8406 {
8407 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8408 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8409 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8410 WIPHY_VENDOR_CMD_NEED_NETDEV |
8411 WIPHY_VENDOR_CMD_NEED_RUNNING,
8412 .doit = wlan_hdd_cfg80211_set_fast_roaming
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308413 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008414};
8415
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008416/**
8417 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8418 * @priv_size: Size of the hdd context.
8419 *
8420 * Allocate wiphy context and hdd context.
8421 *
8422 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008423 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008424hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008425{
8426 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008427 hdd_context_t *hdd_ctx;
8428
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008429 ENTER();
8430
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008431 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8432
8433 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008434 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008435 return NULL;
8436 }
8437
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008438 hdd_ctx = wiphy_priv(wiphy);
8439
8440 hdd_ctx->wiphy = wiphy;
8441
8442 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008443}
8444
8445/*
8446 * FUNCTION: wlan_hdd_cfg80211_update_band
8447 * This function is called from the supplicant through a
8448 * private ioctl to change the band value
8449 */
8450int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8451{
8452 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008453 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008454
8455 ENTER();
8456
8457 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8458
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008459 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008460 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008461
8462 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8463 struct ieee80211_supported_band *band = wiphy->bands[i];
8464
8465 channelEnabledState =
8466 cds_get_channel_state(band->channels[j].
8467 hw_value);
8468
8469 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
8470 /* 5G only */
8471#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8472 /* Enable Social channels for P2P */
8473 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8474 (band->channels[j].center_freq)
8475 && CHANNEL_STATE_ENABLE ==
8476 channelEnabledState)
8477 band->channels[j].flags &=
8478 ~IEEE80211_CHAN_DISABLED;
8479 else
8480#endif
8481 band->channels[j].flags |=
8482 IEEE80211_CHAN_DISABLED;
8483 continue;
8484 } else if (IEEE80211_BAND_5GHZ == i &&
8485 eCSR_BAND_24 == eBand) {
8486 /* 2G only */
8487 band->channels[j].flags |=
8488 IEEE80211_CHAN_DISABLED;
8489 continue;
8490 }
8491
Amar Singhal6842e8f2016-02-23 16:30:32 -08008492 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008493 band->channels[j].flags &=
8494 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008495 }
8496 }
8497 return 0;
8498}
8499
8500/*
8501 * FUNCTION: wlan_hdd_cfg80211_init
8502 * This function is called by hdd_wlan_startup()
8503 * during initialization.
8504 * This function is used to initialize and register wiphy structure.
8505 */
8506int wlan_hdd_cfg80211_init(struct device *dev,
8507 struct wiphy *wiphy, struct hdd_config *pCfg)
8508{
8509 int i, j;
8510 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8511
8512 ENTER();
8513
8514 /* Now bind the underlying wlan device with wiphy */
8515 set_wiphy_dev(wiphy, dev);
8516
8517 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8518
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008519#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8520 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008521 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008522#else
8523 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008524 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008525#endif
8526
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008527 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8528 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8529 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8530#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8531 | WIPHY_FLAG_4ADDR_STATION
8532#endif
8533 | WIPHY_FLAG_OFFCHAN_TX;
8534
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008535#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8536 wiphy->wowlan = &wowlan_support_cfg80211_init;
8537#else
8538 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8539 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8540 wiphy->wowlan.pattern_min_len = 1;
8541 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8542#endif
8543
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008544 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008545#ifdef FEATURE_WLAN_ESE
8546 || pCfg->isEseIniFeatureEnabled
8547#endif
8548 ) {
8549 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8550 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008551#ifdef FEATURE_WLAN_TDLS
8552 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8553 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8554#endif
8555
8556 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8557
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008558#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8559 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8560#endif
8561
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008562#ifdef FEATURE_WLAN_SCAN_PNO
8563 if (pCfg->configPNOScanSupport) {
8564 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8565 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8566 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8567 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008568#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8569 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8570#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008571 }
8572#endif /*FEATURE_WLAN_SCAN_PNO */
8573
8574#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308575 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008576#endif
8577
8578 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8579 driver can still register regulatory callback and
8580 it will get regulatory settings in wiphy->band[], but
8581 driver need to determine what to do with both
8582 regulatory settings */
8583
8584 wiphy->reg_notifier = hdd_reg_notifier;
8585
8586#if defined QCA_WIFI_FTM
8587}
8588#endif
8589
8590 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8591
8592 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8593
8594 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8595
Arun Khandavallifae92942016-08-01 13:31:08 +05308596 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8597 | BIT(NL80211_IFTYPE_ADHOC)
8598 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8599 | BIT(NL80211_IFTYPE_P2P_GO)
8600 | BIT(NL80211_IFTYPE_AP)
8601 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008602
Arun Khandavallifae92942016-08-01 13:31:08 +05308603 if (pCfg->advertiseConcurrentOperation) {
8604 if (pCfg->enableMCC) {
8605 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008606
Arun Khandavallifae92942016-08-01 13:31:08 +05308607 for (i = 0;
8608 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8609 i++) {
8610 if (!pCfg->allowMCCGODiffBI)
8611 wlan_hdd_iface_combination[i].
8612 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008613 }
8614 }
8615 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308616 ARRAY_SIZE(wlan_hdd_iface_combination);
8617 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008618 }
8619
8620 /* Before registering we need to update the ht capabilitied based
8621 * on ini values*/
8622 if (!pCfg->ShortGI20MhzEnable) {
8623 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8624 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008625 }
8626
8627 if (!pCfg->ShortGI40MhzEnable) {
8628 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8629 }
8630
8631 if (!pCfg->nChannelBondingMode5GHz) {
8632 wlan_hdd_band_5_ghz.ht_cap.cap &=
8633 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8634 }
8635
Abhishek Singhf512bf32016-05-04 16:47:46 +05308636 /*
8637 * In case of static linked driver at the time of driver unload,
8638 * module exit doesn't happens. Module cleanup helps in cleaning
8639 * of static memory.
8640 * If driver load happens statically, at the time of driver unload,
8641 * wiphy flags don't get reset because of static memory.
8642 * It's better not to store channel in static memory.
8643 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008644 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308645 wiphy->bands[IEEE80211_BAND_2GHZ]->channels =
8646 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
8647 if (wiphy->bands[IEEE80211_BAND_2GHZ]->channels == NULL) {
8648 hdd_err("Not enough memory to allocate channels");
8649 return -ENOMEM;
8650 }
8651 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_2GHZ]->channels,
8652 &hdd_channels_2_4_ghz[0],
8653 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308654 if ((hdd_is_5g_supported(pHddCtx)) &&
8655 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8656 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8657 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8658 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008659 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308660 wiphy->bands[IEEE80211_BAND_5GHZ]->channels =
8661 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
8662 if (wiphy->bands[IEEE80211_BAND_5GHZ]->channels == NULL) {
8663 hdd_err("Not enough memory to allocate channels");
8664 qdf_mem_free(wiphy->
8665 bands[IEEE80211_BAND_2GHZ]->channels);
8666 wiphy->bands[IEEE80211_BAND_2GHZ]->channels = NULL;
8667 return -ENOMEM;
8668 }
8669 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_5GHZ]->channels,
8670 &hdd_channels_5_ghz[0],
8671 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008672 }
8673
8674 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8675
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008676 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008677 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008678
8679 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8680 struct ieee80211_supported_band *band = wiphy->bands[i];
8681
8682 if (IEEE80211_BAND_2GHZ == i &&
8683 eCSR_BAND_5G == pCfg->nBandCapability) {
8684 /* 5G only */
8685#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8686 /* Enable social channels for P2P */
8687 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8688 (band->channels[j].center_freq))
8689 band->channels[j].flags &=
8690 ~IEEE80211_CHAN_DISABLED;
8691 else
8692#endif
8693 band->channels[j].flags |=
8694 IEEE80211_CHAN_DISABLED;
8695 continue;
8696 } else if (IEEE80211_BAND_5GHZ == i &&
8697 eCSR_BAND_24 == pCfg->nBandCapability) {
8698 /* 2G only */
8699 band->channels[j].flags |=
8700 IEEE80211_CHAN_DISABLED;
8701 continue;
8702 }
8703 }
8704 }
8705 /*Initialise the supported cipher suite details */
8706 wiphy->cipher_suites = hdd_cipher_suites;
8707 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8708
8709 /*signal strength in mBm (100*dBm) */
8710 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8711 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8712
Anurag Chouhan6d760662016-02-20 16:05:43 +05308713 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008714 wiphy->n_vendor_commands =
8715 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8716 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8717
8718 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8719 wiphy->n_vendor_events =
8720 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8721 }
8722
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008723 if (pCfg->enableDFSMasterCap) {
8724 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8725 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008726
8727 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8728
8729#ifdef QCA_HT_2040_COEX
8730 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8731#endif
8732
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308733 hdd_add_channel_switch_support(&wiphy->flags);
8734
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008735 EXIT();
8736 return 0;
8737}
8738
Abhishek Singhf512bf32016-05-04 16:47:46 +05308739/**
8740 * wlan_hdd_cfg80211_deinit - Deinit cfg80211
8741 * @ wiphy: the wiphy to validate against
8742 *
8743 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308744 * memory allocated in wlan_hdd_cfg80211_init also
8745 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308746 *
8747 * Return: void
8748 */
8749void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8750{
8751 int i;
8752
8753 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8754 if (NULL != wiphy->bands[i] &&
8755 (NULL != wiphy->bands[i]->channels)) {
8756 qdf_mem_free(wiphy->bands[i]->channels);
8757 wiphy->bands[i]->channels = NULL;
8758 }
8759 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308760 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05308761}
8762
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008763/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308764 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008765 * initialization. In wlan_hdd_cfg80211_init, only the
8766 * default values will be initialized. The final initialization
8767 * of all required members can be done here.
8768 */
8769void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
8770{
8771 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8772}
8773
8774/* In this function we are registering wiphy. */
8775int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
8776{
8777 ENTER();
8778 /* Register our wiphy dev with cfg80211 */
8779 if (0 > wiphy_register(wiphy)) {
8780 /* print error */
Jeff Johnson77848112016-06-29 14:52:06 -07008781 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008782 return -EIO;
8783 }
8784
8785 EXIT();
8786 return 0;
8787}
8788
8789/*
8790 HDD function to update wiphy capability based on target offload status.
8791
8792 wlan_hdd_cfg80211_init() does initialization of all wiphy related
8793 capability even before downloading firmware to the target. In discrete
8794 case, host will get know certain offload capability (say sched_scan
8795 caps) only after downloading firmware to the target and target boots up.
8796 This function is used to override setting done in wlan_hdd_cfg80211_init()
8797 based on target capability.
8798 */
8799void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
8800{
8801#ifdef FEATURE_WLAN_SCAN_PNO
8802 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8803 struct hdd_config *pCfg = pHddCtx->config;
8804
8805 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
8806 * control comes here. Here just we need to clear it if firmware doesn't
8807 * have PNO support. */
8808 if (!pCfg->PnoOffload) {
8809 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8810 wiphy->max_sched_scan_ssids = 0;
8811 wiphy->max_match_sets = 0;
8812 wiphy->max_sched_scan_ie_len = 0;
8813 }
8814#endif
8815}
8816
8817/* This function registers for all frame which supplicant is interested in */
8818void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
8819{
8820 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8821 /* Register for all P2P action, public action etc frames */
8822 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8823
8824 ENTER();
8825
Abhishek Singh7996eb72015-12-30 17:24:02 +05308826 /* Register frame indication call back */
8827 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
8828
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05308829 /* Register for p2p ack indication */
8830 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
8831
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008832 /* Right now we are registering these frame when driver is getting
8833 initialized. Once we will move to 2.6.37 kernel, in which we have
8834 frame register ops, we will move this code as a part of that */
8835 /* GAS Initial Request */
8836 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8837 (uint8_t *) GAS_INITIAL_REQ,
8838 GAS_INITIAL_REQ_SIZE);
8839
8840 /* GAS Initial Response */
8841 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8842 (uint8_t *) GAS_INITIAL_RSP,
8843 GAS_INITIAL_RSP_SIZE);
8844
8845 /* GAS Comeback Request */
8846 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8847 (uint8_t *) GAS_COMEBACK_REQ,
8848 GAS_COMEBACK_REQ_SIZE);
8849
8850 /* GAS Comeback Response */
8851 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8852 (uint8_t *) GAS_COMEBACK_RSP,
8853 GAS_COMEBACK_RSP_SIZE);
8854
8855 /* P2P Public Action */
8856 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8857 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
8858 P2P_PUBLIC_ACTION_FRAME_SIZE);
8859
8860 /* P2P Action */
8861 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8862 (uint8_t *) P2P_ACTION_FRAME,
8863 P2P_ACTION_FRAME_SIZE);
8864
8865 /* WNM BSS Transition Request frame */
8866 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8867 (uint8_t *) WNM_BSS_ACTION_FRAME,
8868 WNM_BSS_ACTION_FRAME_SIZE);
8869
8870 /* WNM-Notification */
8871 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
8872 (uint8_t *) WNM_NOTIFICATION_FRAME,
8873 WNM_NOTIFICATION_FRAME_SIZE);
8874}
8875
8876void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
8877{
8878 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8879 /* Register for all P2P action, public action etc frames */
8880 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8881
8882 ENTER();
8883
8884 /* Right now we are registering these frame when driver is getting
8885 initialized. Once we will move to 2.6.37 kernel, in which we have
8886 frame register ops, we will move this code as a part of that */
8887 /* GAS Initial Request */
8888
8889 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8890 (uint8_t *) GAS_INITIAL_REQ,
8891 GAS_INITIAL_REQ_SIZE);
8892
8893 /* GAS Initial Response */
8894 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8895 (uint8_t *) GAS_INITIAL_RSP,
8896 GAS_INITIAL_RSP_SIZE);
8897
8898 /* GAS Comeback Request */
8899 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8900 (uint8_t *) GAS_COMEBACK_REQ,
8901 GAS_COMEBACK_REQ_SIZE);
8902
8903 /* GAS Comeback Response */
8904 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8905 (uint8_t *) GAS_COMEBACK_RSP,
8906 GAS_COMEBACK_RSP_SIZE);
8907
8908 /* P2P Public Action */
8909 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8910 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
8911 P2P_PUBLIC_ACTION_FRAME_SIZE);
8912
8913 /* P2P Action */
8914 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8915 (uint8_t *) P2P_ACTION_FRAME,
8916 P2P_ACTION_FRAME_SIZE);
8917
8918 /* WNM-Notification */
8919 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
8920 (uint8_t *) WNM_NOTIFICATION_FRAME,
8921 WNM_NOTIFICATION_FRAME_SIZE);
8922}
8923
8924#ifdef FEATURE_WLAN_WAPI
8925void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
8926 const uint8_t *mac_addr, const uint8_t *key,
8927 int key_Len)
8928{
8929 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8930 tCsrRoamSetKey setKey;
8931 bool isConnected = true;
8932 int status = 0;
8933 uint32_t roamId = 0xFF;
8934 uint8_t *pKeyPtr = NULL;
8935 int n = 0;
8936
Jeff Johnson46b40792016-06-29 14:03:14 -07008937 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008938 hdd_device_mode_to_string(pAdapter->device_mode),
8939 pAdapter->device_mode);
8940
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308941 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008942 setKey.keyId = key_index; /* Store Key ID */
8943 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
8944 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
8945 setKey.paeRole = 0; /* the PAE role */
8946 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05308947 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008948 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308949 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008950 }
8951 setKey.keyLength = key_Len;
8952 pKeyPtr = setKey.Key;
8953 memcpy(pKeyPtr, key, key_Len);
8954
Jeff Johnson46b40792016-06-29 14:03:14 -07008955 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008956 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07008957 hdd_notice("WAPI KEY Data[%d]:%02x ",
8958 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008959
8960 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
8961 if (isConnected) {
8962 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
8963 pAdapter->sessionId, &setKey, &roamId);
8964 }
8965 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07008966 hdd_err("sme_roam_set_key returned ERROR status= %d",
8967 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008968 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
8969 }
8970}
8971#endif /* FEATURE_WLAN_WAPI */
8972
8973uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
8974 uint8_t eid)
8975{
8976 int left = length;
8977 uint8_t *ptr = (uint8_t *)ies_ptr;
8978 uint8_t elem_id, elem_len;
8979
8980 while (left >= 2) {
8981 elem_id = ptr[0];
8982 elem_len = ptr[1];
8983 left -= 2;
8984 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07008985 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008986 eid, elem_len, left);
8987 return NULL;
8988 }
8989 if (elem_id == eid) {
8990 return ptr;
8991 }
8992
8993 left -= elem_len;
8994 ptr += (elem_len + 2);
8995 }
8996 return NULL;
8997}
8998
8999/*
9000 * FUNCTION: wlan_hdd_validate_operation_channel
9001 * called by wlan_hdd_cfg80211_start_bss() and
9002 * wlan_hdd_set_channel()
9003 * This function validates whether given channel is part of valid
9004 * channel list.
9005 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309006QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009007 int channel)
9008{
9009
9010 uint32_t num_ch = 0;
9011 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9012 u32 indx = 0;
9013 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9014 uint8_t fValidChannel = false, count = 0;
9015 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9016
9017 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9018
9019 if (hdd_pConfig_ini->sapAllowAllChannel) {
9020 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009021 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009022 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009023 fValidChannel = true;
9024 break;
9025 }
9026 }
9027 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009028 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309029 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009030 }
9031 } else {
9032 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9033 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009034 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309035 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009036 }
9037 for (indx = 0; indx < num_ch; indx++) {
9038 if (channel == valid_ch[indx]) {
9039 break;
9040 }
9041 }
9042
9043 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009044 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309045 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009046 }
9047 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309048 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009049
9050}
9051
9052#ifdef DHCP_SERVER_OFFLOAD
9053static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9054{
9055 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9056 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9057 uint8_t numEntries = 0;
9058 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9059 uint8_t num;
9060 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309061 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009062 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009063 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009064 return;
9065 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309066 qdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009067 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9068 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9069 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9070 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9071 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9072 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009073 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009074 goto end;
9075 }
9076 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009077 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009078 goto end;
9079 }
9080 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009081 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009082 goto end;
9083 }
9084 for (num = 0; num < numEntries; num++) {
9085 temp = srv_ip[num];
9086 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9087 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309088 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009089 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009090 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009091 goto end;
9092 }
Jeff Johnson77848112016-06-29 14:52:06 -07009093 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009094end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309095 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009096 return;
9097}
9098#endif /* DHCP_SERVER_OFFLOAD */
9099
9100static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9101 struct net_device *dev,
9102 struct bss_parameters *params)
9103{
9104 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9105 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9106 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309107 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009108
9109 ENTER();
9110
Anurag Chouhan6d760662016-02-20 16:05:43 +05309111 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009112 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009113 return -EINVAL;
9114 }
9115
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309116 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009117 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9118 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009119 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009120 hdd_device_mode_to_string(pAdapter->device_mode),
9121 pAdapter->device_mode, params->ap_isolate);
9122
9123 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9124 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309125 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009126 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009127
Krunal Sonib4326f22016-03-10 13:05:51 -08009128 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9129 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009130 return -EOPNOTSUPP;
9131 }
9132
9133 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9134 * want to update this parameter */
9135 if (-1 != params->ap_isolate) {
9136 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9137 !!params->ap_isolate;
9138
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309139 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009140 pAdapter->sessionId,
9141 pAdapter->sessionCtx.
9142 ap.
9143 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309144 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009145 ret = -EINVAL;
9146 }
9147 }
9148
9149 EXIT();
9150 return ret;
9151}
9152
Krunal Soni8c37e322016-02-03 16:08:37 -08009153/**
9154 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9155 * @ndev: pointer to net device provided by supplicant
9156 * @type: type of the interface, upper layer wanted to change
9157 *
9158 * Upper layer provides the new interface mode that needs to be changed
9159 * for given net device
9160 *
9161 * Return: success or failure in terms of integer value
9162 */
9163static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009164 enum nl80211_iftype type)
9165{
Krunal Soni8c37e322016-02-03 16:08:37 -08009166 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9167 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9168 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009169 hdd_wext_state_t *wext;
9170 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309171 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009172
9173 ENTER();
9174
Krunal Soni8c37e322016-02-03 16:08:37 -08009175 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009176 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009177 return 0;
9178 }
9179
9180 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009181 hdd_stop_adapter(hdd_ctx, adapter, true);
9182 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009183 wdev->iftype = type;
9184 /*Check for sub-string p2p to confirm its a p2p interface */
9185 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009186 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009187 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009188 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009189 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009190 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009191 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009192 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009193 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009194 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009195 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009196 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9197 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009198 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9199 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009200 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009201 adapter->scan_info.scanAddIE.length;
9202 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309203 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009204 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9205 wext->roamProfile.phyMode =
9206 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9207 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009208 EXIT();
9209 return status;
9210}
9211
9212static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9213 struct net_device *dev,
9214 struct bss_parameters *params)
9215{
9216 int ret;
9217
9218 cds_ssr_protect(__func__);
9219 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9220 cds_ssr_unprotect(__func__);
9221
9222 return ret;
9223}
9224
9225/* FUNCTION: wlan_hdd_change_country_code_cd
9226 * to wait for contry code completion
9227 */
9228void *wlan_hdd_change_country_code_cb(void *pAdapter)
9229{
9230 hdd_adapter_t *call_back_pAdapter = pAdapter;
9231 complete(&call_back_pAdapter->change_country_code);
9232 return NULL;
9233}
9234
Rajeev Kumar98edb772016-01-19 12:42:19 -08009235/**
9236 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9237 * @wiphy: Pointer to the wiphy structure
9238 * @ndev: Pointer to the net device
9239 * @type: Interface type
9240 * @flags: Flags for change interface
9241 * @params: Pointer to change interface parameters
9242 *
9243 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009244 */
9245static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9246 struct net_device *ndev,
9247 enum nl80211_iftype type,
9248 u32 *flags,
9249 struct vif_params *params)
9250{
9251 struct wireless_dev *wdev;
9252 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9253 hdd_context_t *pHddCtx;
9254 tCsrRoamProfile *pRoamProfile = NULL;
9255 eCsrRoamBssType LastBSSType;
9256 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309257 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009258 int status;
9259
9260 ENTER();
9261
Anurag Chouhan6d760662016-02-20 16:05:43 +05309262 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009263 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009264 return -EINVAL;
9265 }
9266
9267 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9268 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309269 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009270 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009271
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309272 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009273 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9274 pAdapter->sessionId, type));
9275
Jeff Johnson77848112016-06-29 14:52:06 -07009276 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009277 pAdapter->device_mode, type);
9278
Arun Khandavallifae92942016-08-01 13:31:08 +05309279 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9280 if (status) {
9281 hdd_err("Failed to start modules");
9282 return -EINVAL;
9283 }
9284
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009285 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009286 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9287 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009288 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009289 return -EINVAL;
9290 }
9291
9292 pConfig = pHddCtx->config;
9293 wdev = ndev->ieee80211_ptr;
9294
9295 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009296 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009297
9298 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9299
Krunal Sonib4326f22016-03-10 13:05:51 -08009300 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9301 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9302 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9303 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009304 hdd_wext_state_t *pWextState =
9305 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9306
9307 pRoamProfile = &pWextState->roamProfile;
9308 LastBSSType = pRoamProfile->BSSType;
9309
9310 switch (type) {
9311 case NL80211_IFTYPE_STATION:
9312 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009313 case NL80211_IFTYPE_ADHOC:
9314 if (type == NL80211_IFTYPE_ADHOC) {
9315 wlan_hdd_tdls_exit(pAdapter);
9316 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009317 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009318 }
9319 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9320 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309321 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009322 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309323 if (hdd_start_adapter(pAdapter)) {
9324 hdd_err("Failed to start adapter :%d",
9325 pAdapter->device_mode);
9326 return -EINVAL;
9327 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009328 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009329 case NL80211_IFTYPE_AP:
9330 case NL80211_IFTYPE_P2P_GO:
9331 {
Jeff Johnson77848112016-06-29 14:52:06 -07009332 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009333 (type ==
9334 NL80211_IFTYPE_AP) ? "SoftAP" :
9335 "P2pGo");
9336
9337 /* Cancel any remain on channel for GO mode */
9338 if (NL80211_IFTYPE_P2P_GO == type) {
9339 wlan_hdd_cancel_existing_remain_on_channel
9340 (pAdapter);
9341 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009342
Arun Khandavallifae92942016-08-01 13:31:08 +05309343 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009344 /* De-init the adapter */
9345 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9346 memset(&pAdapter->sessionCtx, 0,
9347 sizeof(pAdapter->sessionCtx));
9348 pAdapter->device_mode =
9349 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009350 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9351 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009352
9353 /*
9354 * Fw will take care incase of concurrency
9355 */
9356
Krunal Sonib4326f22016-03-10 13:05:51 -08009357 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009358 && (pConfig->apRandomBssidEnabled)) {
9359 /* To meet Android requirements create a randomized
9360 MAC address of the form 02:1A:11:Fx:xx:xx */
9361 get_random_bytes(&ndev->dev_addr[3], 3);
9362 ndev->dev_addr[0] = 0x02;
9363 ndev->dev_addr[1] = 0x1A;
9364 ndev->dev_addr[2] = 0x11;
9365 ndev->dev_addr[3] |= 0xF0;
9366 memcpy(pAdapter->macAddressCurrent.
9367 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309368 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009369 pr_info("wlan: Generated HotSpot BSSID "
9370 MAC_ADDRESS_STR "\n",
9371 MAC_ADDR_ARRAY(ndev->dev_addr));
9372 }
9373
9374 hdd_set_ap_ops(pAdapter->dev);
9375
Arun Khandavallifae92942016-08-01 13:31:08 +05309376 if (hdd_start_adapter(pAdapter)) {
9377 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009378 return -EINVAL;
9379 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009380 /* Interface type changed update in wiphy structure */
9381 if (wdev) {
9382 wdev->iftype = type;
9383 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009384 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009385 return -EINVAL;
9386 }
9387 goto done;
9388 }
9389
9390 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009391 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009392 type);
9393 return -EOPNOTSUPP;
9394 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009395 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9396 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009397 switch (type) {
9398 case NL80211_IFTYPE_STATION:
9399 case NL80211_IFTYPE_P2P_CLIENT:
9400 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009401 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9402 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309403 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009404 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309405 if (hdd_start_adapter(pAdapter)) {
9406 hdd_err("Failed to start adapter :%d",
9407 pAdapter->device_mode);
9408 return -EINVAL;
9409 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009410 goto done;
9411
9412 case NL80211_IFTYPE_AP:
9413 case NL80211_IFTYPE_P2P_GO:
9414 wdev->iftype = type;
9415 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009416 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009417 goto done;
9418
9419 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009420 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009421 type);
9422 return -EOPNOTSUPP;
9423 }
9424 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009425 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009426 pAdapter->device_mode);
9427 return -EOPNOTSUPP;
9428 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009429done:
9430 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009431 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009432
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009433 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009434
9435 EXIT();
9436 return 0;
9437}
9438
Rajeev Kumar98edb772016-01-19 12:42:19 -08009439/**
9440 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9441 * @wiphy: Pointer to the wiphy structure
9442 * @ndev: Pointer to the net device
9443 * @type: Interface type
9444 * @flags: Flags for change interface
9445 * @params: Pointer to change interface parameters
9446 *
9447 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009448 */
9449static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9450 struct net_device *ndev,
9451 enum nl80211_iftype type,
9452 u32 *flags,
9453 struct vif_params *params)
9454{
9455 int ret;
9456
9457 cds_ssr_protect(__func__);
9458 ret =
9459 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9460 cds_ssr_unprotect(__func__);
9461
9462 return ret;
9463}
9464
9465#ifdef FEATURE_WLAN_TDLS
9466static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9467 int index, uint8_t match)
9468{
9469 int i;
9470 for (i = 0; i < index; i++) {
9471 if (arr[i] == match)
9472 return true;
9473 }
9474 return false;
9475}
9476#endif
9477
9478/**
9479 * __wlan_hdd_change_station() - change station
9480 * @wiphy: Pointer to the wiphy structure
9481 * @dev: Pointer to the net device.
9482 * @mac: bssid
9483 * @params: Pointer to station parameters
9484 *
9485 * Return: 0 for success, error number on failure.
9486 */
9487#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9488static int __wlan_hdd_change_station(struct wiphy *wiphy,
9489 struct net_device *dev,
9490 const uint8_t *mac,
9491 struct station_parameters *params)
9492#else
9493static int __wlan_hdd_change_station(struct wiphy *wiphy,
9494 struct net_device *dev,
9495 uint8_t *mac,
9496 struct station_parameters *params)
9497#endif
9498{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309499 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009500 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9501 hdd_context_t *pHddCtx;
9502 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309503 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009504#ifdef FEATURE_WLAN_TDLS
9505 tCsrStaParams StaParams = { 0 };
9506 uint8_t isBufSta = 0;
9507 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309508 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009509#endif
9510 int ret;
9511
9512 ENTER();
9513
Anurag Chouhan6d760662016-02-20 16:05:43 +05309514 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009515 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009516 return -EINVAL;
9517 }
9518
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309519 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009520 TRACE_CODE_HDD_CHANGE_STATION,
9521 pAdapter->sessionId, params->listen_interval));
9522
9523 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9524 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309525 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009526 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009527
9528 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9529
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309530 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009531
Krunal Sonib4326f22016-03-10 13:05:51 -08009532 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9533 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009534 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9535 status =
9536 hdd_softap_change_sta_state(pAdapter,
9537 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009538 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009539
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309540 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009541 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009542 return -EINVAL;
9543 }
9544 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009545 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9546 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009547#ifdef FEATURE_WLAN_TDLS
9548 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009549
9550 if (cds_is_sub_20_mhz_enabled()) {
9551 hdd_err("TDLS not allowed with sub 20 MHz");
9552 return -EINVAL;
9553 }
9554
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009555 StaParams.capability = params->capability;
9556 StaParams.uapsd_queues = params->uapsd_queues;
9557 StaParams.max_sp = params->max_sp;
9558
9559 /* Convert (first channel , number of channels) tuple to
9560 * the total list of channels. This goes with the assumption
9561 * that if the first channel is < 14, then the next channels
9562 * are an incremental of 1 else an incremental of 4 till the number
9563 * of channels.
9564 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009565 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009566 if (0 != params->supported_channels_len) {
9567 int i = 0, j = 0, k = 0, no_of_channels = 0;
9568 int num_unique_channels;
9569 int next;
9570 for (i = 0;
9571 i < params->supported_channels_len
9572 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9573 int wifi_chan_index;
9574 if (!wlan_hdd_is_duplicate_channel
9575 (StaParams.supported_channels, j,
9576 params->supported_channels[i])) {
9577 StaParams.
9578 supported_channels[j] =
9579 params->
9580 supported_channels[i];
9581 } else {
9582 continue;
9583 }
9584 wifi_chan_index =
9585 ((StaParams.supported_channels[j] <=
9586 HDD_CHANNEL_14) ? 1 : 4);
9587 no_of_channels =
9588 params->supported_channels[i + 1];
9589
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009590 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 -08009591 StaParams.
9592 supported_channels[j],
9593 wifi_chan_index,
9594 no_of_channels);
9595 for (k = 1; k <= no_of_channels &&
9596 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9597 k++) {
9598 next =
9599 StaParams.
9600 supported_channels[j] +
9601 wifi_chan_index;
9602 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9603 StaParams.
9604 supported_channels[j
9605 +
9606 1]
9607 = next;
9608 } else {
9609 continue;
9610 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009611 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009612 j + 1,
9613 StaParams.
9614 supported_channels[j +
9615 1]);
9616 j += 1;
9617 }
9618 }
9619 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009620 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009621 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009622 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009623 StaParams.
9624 supported_channels[i]);
9625 }
9626 if (MAX_CHANNEL < num_unique_channels)
9627 num_unique_channels = MAX_CHANNEL;
9628 StaParams.supported_channels_len =
9629 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009630 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009631 StaParams.supported_channels_len);
9632 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309633 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009634 params->supported_oper_classes,
9635 params->supported_oper_classes_len);
9636 StaParams.supported_oper_classes_len =
9637 params->supported_oper_classes_len;
9638
9639 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309640 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009641 params->ext_capab,
9642 sizeof(StaParams.extn_capability));
9643
9644 if (NULL != params->ht_capa) {
9645 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309646 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009647 sizeof(tSirHTCap));
9648 }
9649
9650 StaParams.supported_rates_len =
9651 params->supported_rates_len;
9652
9653 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9654 * The supported_rates array , for all the structures propogating till Add Sta
9655 * to the firmware has to be modified , if the supplicant (ieee80211) is
9656 * modified to send more rates.
9657 */
9658
9659 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
9660 */
9661 if (StaParams.supported_rates_len >
9662 SIR_MAC_MAX_SUPP_RATES)
9663 StaParams.supported_rates_len =
9664 SIR_MAC_MAX_SUPP_RATES;
9665
9666 if (0 != StaParams.supported_rates_len) {
9667 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309668 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009669 params->supported_rates,
9670 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009671 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009672 StaParams.supported_rates_len);
9673 for (i = 0; i < StaParams.supported_rates_len;
9674 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009675 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009676 StaParams.supported_rates[i]);
9677 }
9678
9679 if (NULL != params->vht_capa) {
9680 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309681 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009682 params->vht_capa,
9683 sizeof(tSirVHTCap));
9684 }
9685
9686 if (0 != params->ext_capab_len) {
9687 /*Define A Macro : TODO Sunil */
9688 if ((1 << 4) & StaParams.extn_capability[3]) {
9689 isBufSta = 1;
9690 }
9691 /* TDLS Channel Switching Support */
9692 if ((1 << 6) & StaParams.extn_capability[3]) {
9693 isOffChannelSupported = 1;
9694 }
9695 }
9696
Nitesh Shah99934ac2016-09-05 15:54:08 +05309697 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +05309698 (params->ht_capa || params->vht_capa ||
9699 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +05309700 is_qos_wmm_sta = true;
9701
9702 hdd_notice("%s: TDLS Peer is QOS capable"
9703 " is_qos_wmm_sta= %d HTcapPresent = %d",
9704 __func__, is_qos_wmm_sta,
9705 StaParams.htcap_present);
9706
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009707 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +05309708 &StaParams,
9709 isBufSta,
9710 isOffChannelSupported,
9711 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309712 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009713 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009714 return -EINVAL;
9715 }
9716
9717 status =
9718 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
9719 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309720 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009721 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009722 return -EINVAL;
9723 }
9724 }
9725#endif
9726 }
9727 EXIT();
9728 return ret;
9729}
9730
9731/**
9732 * wlan_hdd_change_station() - cfg80211 change station handler function
9733 * @wiphy: Pointer to the wiphy structure
9734 * @dev: Pointer to the net device.
9735 * @mac: bssid
9736 * @params: Pointer to station parameters
9737 *
9738 * This is the cfg80211 change station handler function which invokes
9739 * the internal function @__wlan_hdd_change_station with
9740 * SSR protection.
9741 *
9742 * Return: 0 for success, error number on failure.
9743 */
9744#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
9745static int wlan_hdd_change_station(struct wiphy *wiphy,
9746 struct net_device *dev,
9747 const u8 *mac,
9748 struct station_parameters *params)
9749#else
9750static int wlan_hdd_change_station(struct wiphy *wiphy,
9751 struct net_device *dev,
9752 u8 *mac,
9753 struct station_parameters *params)
9754#endif
9755{
9756 int ret;
9757
9758 cds_ssr_protect(__func__);
9759 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
9760 cds_ssr_unprotect(__func__);
9761
9762 return ret;
9763}
9764
9765/*
9766 * FUNCTION: __wlan_hdd_cfg80211_add_key
9767 * This function is used to initialize the key information
9768 */
9769static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
9770 struct net_device *ndev,
9771 u8 key_index, bool pairwise,
9772 const u8 *mac_addr,
9773 struct key_params *params)
9774{
9775 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9776 tCsrRoamSetKey setKey;
9777 int status;
9778 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009779 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309780 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009781 hdd_context_t *pHddCtx;
9782 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9783
9784 ENTER();
9785
Anurag Chouhan6d760662016-02-20 16:05:43 +05309786 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009787 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009788 return -EINVAL;
9789 }
9790
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309791 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009792 TRACE_CODE_HDD_CFG80211_ADD_KEY,
9793 pAdapter->sessionId, params->key_len));
9794 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9795 status = wlan_hdd_validate_context(pHddCtx);
9796
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309797 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009798 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009799
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009800 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009801 hdd_device_mode_to_string(pAdapter->device_mode),
9802 pAdapter->device_mode);
9803
9804 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009805 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009806
9807 return -EINVAL;
9808 }
9809
9810 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009811 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009812
9813 return -EINVAL;
9814 }
9815
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009816 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009817
9818 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309819 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009820 setKey.keyId = key_index;
9821 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309822 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009823
9824 switch (params->cipher) {
9825 case WLAN_CIPHER_SUITE_WEP40:
9826 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9827 break;
9828
9829 case WLAN_CIPHER_SUITE_WEP104:
9830 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
9831 break;
9832
9833 case WLAN_CIPHER_SUITE_TKIP:
9834 {
9835 u8 *pKey = &setKey.Key[0];
9836 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
9837
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309838 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009839
9840 /*Supplicant sends the 32bytes key in this order
9841
9842 |--------------|----------|----------|
9843 | Tk1 |TX-MIC | RX Mic |
9844 |||--------------|----------|----------|
9845 <---16bytes---><--8bytes--><--8bytes-->
9846
9847 */
9848 /*Sme expects the 32 bytes key to be in the below order
9849
9850 |--------------|----------|----------|
9851 | Tk1 |RX-MIC | TX Mic |
9852 |||--------------|----------|----------|
9853 <---16bytes---><--8bytes--><--8bytes-->
9854 */
9855 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309856 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009857
9858 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309859 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009860
9861 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309862 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009863
9864 break;
9865 }
9866
9867 case WLAN_CIPHER_SUITE_CCMP:
9868 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
9869 break;
9870
9871#ifdef FEATURE_WLAN_WAPI
9872 case WLAN_CIPHER_SUITE_SMS4:
9873 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309874 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009875 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
9876 mac_addr, params->key,
9877 params->key_len);
9878 return 0;
9879 }
9880#endif
9881
9882#ifdef FEATURE_WLAN_ESE
9883 case WLAN_CIPHER_SUITE_KRK:
9884 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
9885 break;
9886#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9887 case WLAN_CIPHER_SUITE_BTK:
9888 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
9889 break;
9890#endif
9891#endif
9892
9893#ifdef WLAN_FEATURE_11W
9894 case WLAN_CIPHER_SUITE_AES_CMAC:
9895 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
9896 break;
9897#endif
9898
9899 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009900 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009901 return -EOPNOTSUPP;
9902 }
9903
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009904 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009905
9906 if (!pairwise) {
9907 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009908 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009909 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05309910 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009911 } else {
9912 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009913 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009914 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309915 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009916 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009917 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009918 /* if a key is already installed, block all subsequent ones */
9919 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009920 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009921 return 0;
9922 }
9923
9924 setKey.keyDirection = eSIR_TX_RX;
9925 /*Set the group key */
9926 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9927 pAdapter->sessionId, &setKey, &roamId);
9928
9929 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009930 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009931 return -EINVAL;
9932 }
9933 /*Save the keys here and call sme_roam_set_key for setting
9934 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309935 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009936 &setKey, sizeof(tCsrRoamSetKey));
9937
9938 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
9939 return status;
9940 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009941 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9942 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009943 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9944 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -07009945 status = wlansap_set_key_sta(
9946 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309947 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009948 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009949 __LINE__, status);
9950 }
9951 }
9952
9953 /* Save the key in ap ctx for use on START_BASS and restart */
9954 if (pairwise ||
9955 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
9956 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309957 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009958 sizeof(tCsrRoamSetKey));
9959 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309960 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009961 sizeof(tCsrRoamSetKey));
9962
Krunal Sonib4326f22016-03-10 13:05:51 -08009963 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9964 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009965 hdd_wext_state_t *pWextState =
9966 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9967 hdd_station_ctx_t *pHddStaCtx =
9968 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9969
9970 if (!pairwise) {
9971 /* set group key */
9972 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009973 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009974 __func__, __LINE__);
9975 hdd_perform_roam_set_key_complete(pAdapter);
9976 }
9977 }
9978
9979 pWextState->roamProfile.Keys.KeyLength[key_index] =
9980 (u8) params->key_len;
9981
9982 pWextState->roamProfile.Keys.defaultIndex = key_index;
9983
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309984 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009985 KeyMaterial[key_index][0], params->key,
9986 params->key_len);
9987
9988 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9989
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009990 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009991 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
9992 setKey.keyDirection);
9993
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009994 /* The supplicant may attempt to set the PTK once pre-authentication
9995 is done. Save the key in the UMAC and include it in the ADD BSS
9996 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309997 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009998 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309999 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010000 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010001 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010002 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010003 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010004 return -EINVAL;
10005 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010006
10007 /* issue set key request to SME */
10008 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10009 pAdapter->sessionId, &setKey, &roamId);
10010
10011 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010012 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010013 pHddStaCtx->roam_info.roamingState =
10014 HDD_ROAM_STATE_NONE;
10015 return -EINVAL;
10016 }
10017
10018 /* in case of IBSS as there was no information available about WEP keys during
10019 * IBSS join, group key intialized with NULL key, so re-initialize group key
10020 * with correct value*/
10021 if ((eCSR_BSS_TYPE_START_IBSS ==
10022 pWextState->roamProfile.BSSType)
10023 &&
10024 !((IW_AUTH_KEY_MGMT_802_1X ==
10025 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10026 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10027 pHddStaCtx->conn_info.authType)
10028 )
10029 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10030 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10031 )
10032 ) {
10033 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010034 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010035
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010036 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010037 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10038 setKey.keyDirection);
10039
10040 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10041 pAdapter->sessionId, &setKey,
10042 &roamId);
10043
10044 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010045 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010046 pHddStaCtx->roam_info.roamingState =
10047 HDD_ROAM_STATE_NONE;
10048 return -EINVAL;
10049 }
10050 }
10051 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010052 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010053 return 0;
10054}
10055
10056static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10057 struct net_device *ndev,
10058 u8 key_index, bool pairwise,
10059 const u8 *mac_addr,
10060 struct key_params *params)
10061{
10062 int ret;
10063 cds_ssr_protect(__func__);
10064 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10065 mac_addr, params);
10066 cds_ssr_unprotect(__func__);
10067
10068 return ret;
10069}
10070
10071/*
10072 * FUNCTION: __wlan_hdd_cfg80211_get_key
10073 * This function is used to get the key information
10074 */
10075static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10076 struct net_device *ndev,
10077 u8 key_index, bool pairwise,
10078 const u8 *mac_addr, void *cookie,
10079 void (*callback)(void *cookie,
10080 struct key_params *)
10081 )
10082{
10083 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10084 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10085 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10086 struct key_params params;
10087
10088 ENTER();
10089
Anurag Chouhan6d760662016-02-20 16:05:43 +053010090 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010091 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010092 return -EINVAL;
10093 }
10094
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010095 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010096 hdd_device_mode_to_string(pAdapter->device_mode),
10097 pAdapter->device_mode);
10098
10099 memset(&params, 0, sizeof(params));
10100
10101 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010102 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010103 key_index);
10104 return -EINVAL;
10105 }
10106
10107 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10108 case eCSR_ENCRYPT_TYPE_NONE:
10109 params.cipher = IW_AUTH_CIPHER_NONE;
10110 break;
10111
10112 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10113 case eCSR_ENCRYPT_TYPE_WEP40:
10114 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10115 break;
10116
10117 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10118 case eCSR_ENCRYPT_TYPE_WEP104:
10119 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10120 break;
10121
10122 case eCSR_ENCRYPT_TYPE_TKIP:
10123 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10124 break;
10125
10126 case eCSR_ENCRYPT_TYPE_AES:
10127 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10128 break;
10129
10130 default:
10131 params.cipher = IW_AUTH_CIPHER_NONE;
10132 break;
10133 }
10134
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010135 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010136 TRACE_CODE_HDD_CFG80211_GET_KEY,
10137 pAdapter->sessionId, params.cipher));
10138
10139 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10140 params.seq_len = 0;
10141 params.seq = NULL;
10142 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10143 callback(cookie, &params);
10144
10145 EXIT();
10146 return 0;
10147}
10148
10149static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10150 struct net_device *ndev,
10151 u8 key_index, bool pairwise,
10152 const u8 *mac_addr, void *cookie,
10153 void (*callback)(void *cookie,
10154 struct key_params *)
10155 )
10156{
10157 int ret;
10158
10159 cds_ssr_protect(__func__);
10160 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10161 mac_addr, cookie, callback);
10162 cds_ssr_unprotect(__func__);
10163
10164 return ret;
10165}
10166
10167/**
10168 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10169 * @wiphy: wiphy interface context
10170 * @ndev: pointer to net device
10171 * @key_index: Key index used in 802.11 frames
10172 * @unicast: true if it is unicast key
10173 * @multicast: true if it is multicast key
10174 *
10175 * This function is required for cfg80211_ops API.
10176 * It is used to delete the key information
10177 * Underlying hardware implementation does not have API to delete the
10178 * encryption key. It is automatically deleted when the peer is
10179 * removed. Hence this function currently does nothing.
10180 * Future implementation may interprete delete key operation to
10181 * replacing the key with a random junk value, effectively making it
10182 * useless.
10183 *
10184 * Return: status code, always 0.
10185 */
10186
10187static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10188 struct net_device *ndev,
10189 u8 key_index,
10190 bool pairwise, const u8 *mac_addr)
10191{
10192 EXIT();
10193 return 0;
10194}
10195
10196/**
10197 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10198 * @wiphy: Pointer to wiphy structure.
10199 * @dev: Pointer to net_device structure.
10200 * @key_index: key index
10201 * @pairwise: pairwise
10202 * @mac_addr: mac address
10203 *
10204 * This is the cfg80211 delete key handler function which invokes
10205 * the internal function @__wlan_hdd_cfg80211_del_key with
10206 * SSR protection.
10207 *
10208 * Return: 0 for success, error number on failure.
10209 */
10210static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10211 struct net_device *dev,
10212 u8 key_index,
10213 bool pairwise, const u8 *mac_addr)
10214{
10215 int ret;
10216
10217 cds_ssr_protect(__func__);
10218 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10219 pairwise, mac_addr);
10220 cds_ssr_unprotect(__func__);
10221
10222 return ret;
10223}
10224
10225/*
10226 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10227 * This function is used to set the default tx key index
10228 */
10229static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10230 struct net_device *ndev,
10231 u8 key_index,
10232 bool unicast, bool multicast)
10233{
10234 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10235 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10236 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10237 hdd_context_t *pHddCtx;
10238 int status;
10239
10240 ENTER();
10241
Anurag Chouhan6d760662016-02-20 16:05:43 +053010242 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010243 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010244 return -EINVAL;
10245 }
10246
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010247 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010248 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10249 pAdapter->sessionId, key_index));
10250
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010251 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010252 hdd_device_mode_to_string(pAdapter->device_mode),
10253 pAdapter->device_mode, key_index);
10254
10255 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010256 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010257 return -EINVAL;
10258 }
10259
10260 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10261 status = wlan_hdd_validate_context(pHddCtx);
10262
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010263 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010264 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010265
Krunal Sonib4326f22016-03-10 13:05:51 -080010266 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10267 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010268 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10269 pHddStaCtx->conn_info.ucEncryptionType) &&
10270 (eCSR_ENCRYPT_TYPE_AES !=
10271 pHddStaCtx->conn_info.ucEncryptionType)) {
10272 /* If default key index is not same as previous one,
10273 * then update the default key index */
10274
10275 tCsrRoamSetKey setKey;
10276 uint32_t roamId = 0xFF;
10277 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10278
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010279 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010280
10281 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010282 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010283 setKey.keyId = key_index;
10284 setKey.keyLength = Keys->KeyLength[key_index];
10285
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010286 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010287 &Keys->KeyMaterial[key_index][0],
10288 Keys->KeyLength[key_index]);
10289
10290 setKey.keyDirection = eSIR_TX_RX;
10291
Anurag Chouhanc5548422016-02-24 18:33:27 +053010292 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010293 &pHddStaCtx->conn_info.bssId);
10294
10295 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10296 pWextState->roamProfile.EncryptionType.
10297 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10298 /* In the case of dynamic wep supplicant hardcodes DWEP type
10299 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10300 * WEP-40 encryption. In this canse the key length is 5 but the
10301 * encryption type is 104 hence checking the key langht(5) and
10302 * encryption type(104) and switching encryption type to 40*/
10303 pWextState->roamProfile.EncryptionType.
10304 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10305 pWextState->roamProfile.mcEncryptionType.
10306 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10307 }
10308
10309 setKey.encType =
10310 pWextState->roamProfile.EncryptionType.
10311 encryptionType[0];
10312
10313 /* Issue set key request */
10314 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10315 pAdapter->sessionId, &setKey,
10316 &roamId);
10317
10318 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010319 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010320 status);
10321 return -EINVAL;
10322 }
10323 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010324 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010325 /* In SoftAp mode setting key direction for default mode */
10326 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10327 pWextState->roamProfile.EncryptionType.encryptionType[0])
10328 && (eCSR_ENCRYPT_TYPE_AES !=
10329 pWextState->roamProfile.EncryptionType.
10330 encryptionType[0])) {
10331 /* Saving key direction for default key index to TX default */
10332 hdd_ap_ctx_t *pAPCtx =
10333 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10334 pAPCtx->wepKey[key_index].keyDirection =
10335 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010336 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010337 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010338 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010339 }
10340 }
10341
10342 EXIT();
10343 return status;
10344}
10345
10346static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10347 struct net_device *ndev,
10348 u8 key_index,
10349 bool unicast, bool multicast)
10350{
10351 int ret;
10352 cds_ssr_protect(__func__);
10353 ret =
10354 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10355 multicast);
10356 cds_ssr_unprotect(__func__);
10357
10358 return ret;
10359}
10360
Abhishek Singhc9941602016-08-09 16:06:22 +053010361/*
10362 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10363 * @wiphy: wiphy pointer
10364 * @channel: channel of the BSS
10365 * @bssid: Bssid of BSS
10366 * @ssid: Ssid of the BSS
10367 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010368 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010369 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010370 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010371#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
10372struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10373 struct ieee80211_channel *channel, const u8 *bssid,
10374 const u8 *ssid, size_t ssid_len)
10375{
10376 return cfg80211_get_bss(wiphy, channel, bssid,
10377 ssid,
10378 ssid_len,
10379 WLAN_CAPABILITY_ESS,
10380 WLAN_CAPABILITY_ESS);
10381}
10382#else
10383struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10384 struct ieee80211_channel *channel, const u8 *bssid,
10385 const u8 *ssid, size_t ssid_len)
10386{
10387 return cfg80211_get_bss(wiphy, channel, bssid,
10388 ssid,
10389 ssid_len,
10390 IEEE80211_BSS_TYPE_ESS,
10391 IEEE80211_PRIVACY_ANY);
10392}
10393#endif
10394
10395
10396/*
10397 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10398 * interface that BSS might have been lost.
10399 * @pAdapter: adaptor
10400 * @bssid: bssid which might have been lost
10401 *
10402 * Return: bss which is unlinked from kernel cache
10403 */
10404struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10405 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010406{
10407 struct net_device *dev = pAdapter->dev;
10408 struct wireless_dev *wdev = dev->ieee80211_ptr;
10409 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010410 struct cfg80211_bss *bss = NULL;
10411
Abhishek Singhc9941602016-08-09 16:06:22 +053010412 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10413 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010414 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010415 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010416 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010417 hdd_info("cfg80211_unlink_bss called for BSSID "
10418 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010419 cfg80211_unlink_bss(wiphy, bss);
10420 }
10421 return bss;
10422}
10423
Abhishek Singhc9941602016-08-09 16:06:22 +053010424
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010425/**
10426 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10427 * @pAdapter: Pointer to adapter
10428 * @bss_desc: Pointer to bss descriptor
10429 *
10430 * This function is used to inform the BSS details to nl80211 interface.
10431 *
10432 * Return: struct cfg80211_bss pointer
10433 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010434struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10435 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010436{
10437 /*
10438 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10439 * already exists in bss data base of cfg80211 for that particular BSS
10440 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10441 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10442 * As of now there is no possibility to get the mgmt(probe response)
10443 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10444 * and passing to cfg80211_inform_bss_frame.
10445 */
10446 struct net_device *dev = pAdapter->dev;
10447 struct wireless_dev *wdev = dev->ieee80211_ptr;
10448 struct wiphy *wiphy = wdev->wiphy;
10449 int chan_no = bss_desc->channelId;
10450#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10451 qcom_ie_age *qie_age = NULL;
10452 int ie_length =
10453 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10454#else
10455 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10456#endif
10457 const char *ie =
10458 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10459 unsigned int freq;
10460 struct ieee80211_channel *chan;
10461 struct ieee80211_mgmt *mgmt = NULL;
10462 struct cfg80211_bss *bss_status = NULL;
10463 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10464 int rssi = 0;
10465 hdd_context_t *pHddCtx;
10466 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010467 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010468 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010469
10470 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10471 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010472 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010473 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010474
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010475 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010476 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10477 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010478 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010479 return NULL;
10480 }
10481
10482 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10483
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010484 /* Android does not want the timestamp from the frame.
10485 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010486 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010487 mgmt->u.probe_resp.timestamp =
10488 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010489
10490 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10491 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10492
10493#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10494 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10495 /* Assuming this is the last IE, copy at the end */
10496 ie_length -= sizeof(qcom_ie_age);
10497 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10498 qie_age->element_id = QCOM_VENDOR_IE_ID;
10499 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10500 qie_age->oui_1 = QCOM_OUI1;
10501 qie_age->oui_2 = QCOM_OUI2;
10502 qie_age->oui_3 = QCOM_OUI3;
10503 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
10504 qie_age->age =
Anurag Chouhan210db072016-02-22 18:42:15 +053010505 qdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010506 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010507 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10508 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010509 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10510 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010511#endif
10512
10513 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10514 if (bss_desc->fProbeRsp) {
10515 mgmt->frame_control |=
10516 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10517 } else {
10518 mgmt->frame_control |=
10519 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10520 }
10521
10522 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
10523 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
10524 freq =
10525 ieee80211_channel_to_frequency(chan_no,
10526 IEEE80211_BAND_2GHZ);
10527 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
10528 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
10529 freq =
10530 ieee80211_channel_to_frequency(chan_no,
10531 IEEE80211_BAND_5GHZ);
10532 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010533 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010534 kfree(mgmt);
10535 return NULL;
10536 }
10537
10538 chan = __ieee80211_get_channel(wiphy, freq);
10539 /* When the band is changed on the fly using the GUI, three things are done
10540 * 1. scan abort
10541 * 2. flush scan results from cache
10542 * 3. update the band with the new band user specified (refer to the
10543 * hdd_set_band_helper function) as part of the scan abort, message will be
10544 * queued to PE and we proceed with flushing and changinh the band.
10545 * PE will stop the scanning further and report back the results what ever
10546 * it had till now by calling the call back function.
10547 * if the time between update band and scandone call back is sufficient
10548 * enough the band change reflects in SME, SME validates the channels
10549 * and discards the channels correponding to previous band and calls back
10550 * with zero bss results. but if the time between band update and scan done
10551 * callback is very small then band change will not reflect in SME and SME
10552 * reports to HDD all the channels correponding to previous band.this is due
10553 * to race condition.but those channels are invalid to the new band and so
10554 * this function __ieee80211_get_channel will return NULL.Each time we
10555 * report scan result with this pointer null warning kernel trace is printed.
10556 * if the scan results contain large number of APs continuosly kernel
10557 * warning trace is printed and it will lead to apps watch dog bark.
10558 * So drop the bss and continue to next bss.
10559 */
10560 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010561 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10562 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010563 kfree(mgmt);
10564 return NULL;
10565 }
10566
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010567 /* Based on .ini configuration, raw rssi can be reported for bss.
10568 * Raw rssi is typically used for estimating power.
10569 */
10570
10571 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10572 bss_desc->rssi;
10573
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010574 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010575 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010576
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010577 hdd_notice("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010578 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010579 (int)(rssi / 100),
10580 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010581
10582 bss_status =
10583 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10584 GFP_KERNEL);
10585 kfree(mgmt);
10586 return bss_status;
10587}
10588
10589/**
10590 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10591 * @pAdapter: Pointer to adapter
10592 * @pRoamInfo: Pointer to roam info
10593 *
10594 * This function is used to update the BSS data base of CFG8011
10595 *
10596 * Return: struct cfg80211_bss pointer
10597 */
10598struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10599 tCsrRoamInfo *pRoamInfo)
10600{
10601 tCsrRoamConnectedProfile roamProfile;
10602 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10603 struct cfg80211_bss *bss = NULL;
10604
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010605 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10606 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10607
10608 if (NULL != roamProfile.pBssDesc) {
10609 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10610 roamProfile.pBssDesc);
10611
10612 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010613 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010614
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010615 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010616 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010617 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010618 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010619 return bss;
10620}
10621/**
10622 * wlan_hdd_cfg80211_update_bss() - update bss
10623 * @wiphy: Pointer to wiphy
10624 * @pAdapter: Pointer to adapter
10625 * @scan_time: scan request timestamp
10626 *
10627 * Return: zero if success, non-zero otherwise
10628 */
10629int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10630 hdd_adapter_t *pAdapter,
10631 uint32_t scan_time)
10632{
10633 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10634 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010635 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010636 tScanResultHandle pResult;
10637 struct cfg80211_bss *bss_status = NULL;
10638 hdd_context_t *pHddCtx;
10639 int ret;
10640
10641 ENTER();
10642
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010643 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010644 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10645 NO_SESSION, pAdapter->sessionId));
10646
10647 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10648 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010649 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010650 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010651
10652 /* start getting scan results and populate cgf80211 BSS database */
10653 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
10654
10655 /* no scan results */
10656 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010657 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053010658 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010659 }
10660
10661 pScanResult = sme_scan_result_get_first(hHal, pResult);
10662
10663 while (pScanResult) {
10664 /*
10665 * - cfg80211_inform_bss() is not updating ie field of bss
10666 * entry if entry already exists in bss data base of cfg80211
10667 * for that particular BSS ID. Using cfg80211_inform_bss_frame
10668 * to update thebss entry instead of cfg80211_inform_bss,
10669 * But this call expects mgmt packet as input. As of now
10670 * there is no possibility to get the mgmt(probe response)
10671 * frame from PE, converting bss_desc to
10672 * ieee80211_mgmt(probe response) and passing to c
10673 * fg80211_inform_bss_frame.
10674 * - Update BSS only if beacon timestamp is later than
10675 * scan request timestamp.
10676 */
10677 if ((scan_time == 0) ||
10678 (scan_time <
10679 pScanResult->BssDescriptor.nReceivedTime)) {
10680 bss_status =
10681 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10682 &pScanResult->BssDescriptor);
10683
10684 if (NULL == bss_status) {
10685 hdd_info("NULL returned by cfg80211_inform_bss_frame");
10686 } else {
10687 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010688 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010689 bss_status);
10690 }
10691 } else {
10692 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
10693 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
10694 }
10695 pScanResult = sme_scan_result_get_next(hHal, pResult);
10696 }
10697
10698 sme_scan_result_purge(hHal, pResult);
10699 /*
10700 * For SAP mode, scan is invoked by hostapd during SAP start
10701 * if hostapd is restarted, we need to flush previous scan
10702 * result so that it will reflect environment change
10703 */
Krunal Sonib4326f22016-03-10 13:05:51 -080010704 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010705#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
10706 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
10707#endif
10708 )
10709 sme_scan_flush_result(hHal);
10710
10711 EXIT();
10712 return 0;
10713}
10714
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010715/**
10716 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
10717 * @pAdapter: Pointer to adapter
10718 * @pRoamInfo: Pointer to roam info
10719 * @index: Index
10720 * @preauth: Preauth flag
10721 *
10722 * This function is used to notify the supplicant of a new PMKSA candidate.
10723 *
10724 * Return: 0 for success, non-zero for failure
10725 */
10726int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
10727 tCsrRoamInfo *pRoamInfo,
10728 int index, bool preauth)
10729{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010730 struct net_device *dev = pAdapter->dev;
10731 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
10732
10733 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010734 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010735
10736 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010737 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010738 return -EINVAL;
10739 }
10740
10741 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010742 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010743 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
10744 cfg80211_pmksa_candidate_notify(dev, index,
10745 pRoamInfo->bssid.bytes,
10746 preauth, GFP_KERNEL);
10747 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010748 return 0;
10749}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010750
10751#ifdef FEATURE_WLAN_LFR_METRICS
10752/**
10753 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
10754 * @pAdapter: Pointer to adapter
10755 * @pRoamInfo: Pointer to roam info
10756 *
10757 * 802.11r/LFR metrics reporting function to report preauth initiation
10758 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010759 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010760 */
10761#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010762QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010763 tCsrRoamInfo *pRoamInfo)
10764{
10765 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10766 union iwreq_data wrqu;
10767
10768 ENTER();
10769
10770 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010771 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010772 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010773 }
10774
10775 /* create the event */
10776 memset(&wrqu, 0, sizeof(wrqu));
10777 memset(metrics_notification, 0, sizeof(metrics_notification));
10778
10779 wrqu.data.pointer = metrics_notification;
10780 wrqu.data.length = scnprintf(metrics_notification,
10781 sizeof(metrics_notification),
10782 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
10783 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10784
10785 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10786 metrics_notification);
10787
10788 EXIT();
10789
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010790 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010791}
10792
10793/**
10794 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10795 * @pAdapter: Pointer to adapter
10796 * @pRoamInfo: Pointer to roam info
10797 * @preauth_status: Preauth status
10798 *
10799 * 802.11r/LFR metrics reporting function to report handover initiation
10800 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010801 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010802 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010803QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010804wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
10805 tCsrRoamInfo *pRoamInfo,
10806 bool preauth_status)
10807{
10808 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10809 union iwreq_data wrqu;
10810
10811 ENTER();
10812
10813 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010814 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010815 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010816 }
10817
10818 /* create the event */
10819 memset(&wrqu, 0, sizeof(wrqu));
10820 memset(metrics_notification, 0, sizeof(metrics_notification));
10821
10822 scnprintf(metrics_notification, sizeof(metrics_notification),
10823 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
10824 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10825
10826 if (1 == preauth_status)
10827 strlcat(metrics_notification, " true",
10828 sizeof(metrics_notification));
10829 else
10830 strlcat(metrics_notification, " false",
10831 sizeof(metrics_notification));
10832
10833 wrqu.data.pointer = metrics_notification;
10834 wrqu.data.length = strlen(metrics_notification);
10835
10836 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10837 metrics_notification);
10838
10839 EXIT();
10840
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010841 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010842}
10843
10844/**
10845 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10846 * @pAdapter: Pointer to adapter
10847 * @pRoamInfo: Pointer to roam info
10848 *
10849 * 802.11r/LFR metrics reporting function to report handover initiation
10850 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010851 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010852 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010853QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010854 tCsrRoamInfo *pRoamInfo)
10855{
10856 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10857 union iwreq_data wrqu;
10858
10859 ENTER();
10860
10861 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010862 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010863 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010864 }
10865
10866 /* create the event */
10867 memset(&wrqu, 0, sizeof(wrqu));
10868 memset(metrics_notification, 0, sizeof(metrics_notification));
10869
10870 wrqu.data.pointer = metrics_notification;
10871 wrqu.data.length = scnprintf(metrics_notification,
10872 sizeof(metrics_notification),
10873 "QCOM: LFR_PREAUTH_HANDOVER "
10874 MAC_ADDRESS_STR,
10875 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10876
10877 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10878 metrics_notification);
10879
10880 EXIT();
10881
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010882 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010883}
10884#endif
10885
10886/**
10887 * hdd_select_cbmode() - select channel bonding mode
10888 * @pAdapter: Pointer to adapter
10889 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010890 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010891 *
10892 * Return: none
10893 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010894void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
10895 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010896{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010897 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010898 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010899 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010900
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010901 /*
10902 * CDS api expects secondary channel for calculating
10903 * the channel params
10904 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010905 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010906 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
10907 if (operationChannel >= 1 && operationChannel <= 5)
10908 sec_ch = operationChannel + 4;
10909 else if (operationChannel >= 6 && operationChannel <= 13)
10910 sec_ch = operationChannel - 4;
10911 }
10912
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010913 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010914 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010915
10916 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010917 eHddDot11Mode hdd_dot11_mode;
10918 uint8_t iniDot11Mode =
10919 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
10920
10921 hdd_notice("Dot11Mode is %u", iniDot11Mode);
10922 switch (iniDot11Mode) {
10923 case eHDD_DOT11_MODE_AUTO:
10924 case eHDD_DOT11_MODE_11ac:
10925 case eHDD_DOT11_MODE_11ac_ONLY:
10926 if (sme_is_feature_supported_by_fw(DOT11AC))
10927 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
10928 else
10929 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
10930 break;
10931 case eHDD_DOT11_MODE_11n:
10932 case eHDD_DOT11_MODE_11n_ONLY:
10933 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
10934 break;
10935 default:
10936 hdd_dot11_mode = iniDot11Mode;
10937 break;
10938 }
10939 ch_info->channel_width = ch_params->ch_width;
10940 ch_info->phy_mode =
10941 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010942 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010943 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010944 hdd_info("ch_info width %d, phymode %d channel %d",
10945 ch_info->channel_width, ch_info->phy_mode,
10946 ch_info->channel);
10947 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010948}
10949
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070010950/**
10951 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
10952 * @adapter: STA adapter
10953 * @roam_profile: STA roam profile
10954 *
10955 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
10956 *
10957 * Return: false if sta-sap conc is not allowed, else return true
10958 */
10959static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
10960 tCsrRoamProfile *roam_profile)
10961{
10962 hdd_context_t *hdd_ctx;
10963 hdd_adapter_t *ap_adapter;
10964 hdd_ap_ctx_t *hdd_ap_ctx;
10965 hdd_hostapd_state_t *hostapd_state;
10966 uint8_t channel = 0;
10967 QDF_STATUS status;
10968
10969 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10970 if (!hdd_ctx) {
10971 hdd_err("HDD context is NULL");
10972 return true;
10973 }
10974
10975 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
10976 /* probably no sap running, no handling required */
10977 if (ap_adapter == NULL)
10978 return true;
10979
10980 /*
10981 * sap is not in started state, so it is fine to go ahead with sta.
10982 * if sap is currently doing CAC then don't allow sta to go further.
10983 */
10984 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
10985 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
10986 return true;
10987
10988 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
10989 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
10990 return false;
10991 }
10992
10993 /*
10994 * log and return error, if we allow STA to go through, we don't
10995 * know what is going to happen better stop sta connection
10996 */
10997 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10998 if (NULL == hdd_ap_ctx) {
10999 hdd_err("AP context not found");
11000 return false;
11001 }
11002
11003 /* sap is on non-dfs channel, nothing to handle */
11004 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11005 hdd_info("sap is on non-dfs channel, sta is allowed");
11006 return true;
11007 }
11008 /*
11009 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011010 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011011 */
11012 status = cds_get_channel_from_scan_result(adapter,
11013 roam_profile, &channel);
11014
Nitesh Shah59774522016-09-16 15:14:21 +053011015 /*
11016 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11017 * channels for roaming case.
11018 */
11019 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11020 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11021 return true;
11022 }
11023
11024 /*
11025 * If channel is 0 or DFS then better to call pcl and find out the
11026 * best channel. If channel is non-dfs 5 GHz then better move SAP
11027 * to STA's channel to make scc, so we have room for 3port MCC
11028 * scenario.
11029 */
11030 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011031 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11032 true);
11033
11034 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11035 qdf_event_reset(&hostapd_state->qdf_event);
11036 status = wlansap_set_channel_change_with_csa(
11037 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11038 hdd_ap_ctx->sapConfig.ch_width_orig);
11039
11040 if (QDF_STATUS_SUCCESS != status) {
11041 hdd_err("Set channel with CSA IE failed, can't allow STA");
11042 return false;
11043 }
11044
11045 /*
11046 * wait here for SAP to finish the channel switch. When channel
11047 * switch happens, SAP sends few beacons with CSA_IE. After
11048 * successfully Transmission of those beacons, it will move its
11049 * state from started to disconnected and move to new channel.
11050 * once it moves to new channel, sap again moves its state
11051 * machine from disconnected to started and set this event.
11052 * wait for 10 secs to finish this.
11053 */
11054 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11055 if (!QDF_IS_STATUS_SUCCESS(status)) {
11056 hdd_err("wait for qdf_event failed, STA not allowed!!");
11057 return false;
11058 }
11059
11060 return true;
11061}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011062
Krunal Soni31949422016-07-29 17:17:53 -070011063/**
11064 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011065 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011066 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011067 * @ssid_len: Length of ssid
11068 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011069 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011070 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011071 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011072 *
11073 * This function is used to start the association process
11074 *
11075 * Return: 0 for success, non-zero for failure
11076 */
Krunal Soni31949422016-07-29 17:17:53 -070011077static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011078 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011079 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011080 u8 operatingChannel,
11081 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011082{
11083 int status = 0;
11084 hdd_wext_state_t *pWextState;
11085 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011086 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011087 uint32_t roamId;
11088 tCsrRoamProfile *pRoamProfile;
11089 eCsrAuthType RSNAuthType;
11090 tSmeConfigParams *sme_config;
11091
11092 ENTER();
11093
11094 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11095 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011096 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011097
11098 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011099 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011100 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011101
11102 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011103 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011104 return -EINVAL;
11105 }
11106
11107 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011108 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11109 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011110
11111 if (pRoamProfile) {
11112 hdd_station_ctx_t *pHddStaCtx;
11113 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11114
11115 if (HDD_WMM_USER_MODE_NO_QOS ==
11116 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11117 /*QoS not enabled in cfg file */
11118 pRoamProfile->uapsd_mask = 0;
11119 } else {
11120 /*QoS enabled, update uapsd mask from cfg file */
11121 pRoamProfile->uapsd_mask =
11122 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11123 }
11124
11125 pRoamProfile->SSIDs.numOfSSIDs = 1;
11126 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011127 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011128 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011129 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011130 ssid, ssid_len);
11131
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011132 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011133 if (bssid) {
11134 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011135 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011136 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011137 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011138 /*
11139 * Save BSSID in seperate variable as
11140 * pRoamProfile's BSSID is getting zeroed out in the
11141 * association process. In case of join failure
11142 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011143 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011144 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011145 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011146 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011147 } else if (bssid_hint) {
11148 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011149 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011150 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011151 /*
11152 * Save BSSID in a separate variable as
11153 * pRoamProfile's BSSID is getting zeroed out in the
11154 * association process. In case of join failure
11155 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011156 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011157 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011158 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011159 hdd_info("bssid_hint is given by upper layer %pM",
11160 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011161 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011162 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011163 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011164 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011165 }
11166
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011167 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011168 pRoamProfile->SSIDs.SSIDList->SSID.length,
11169 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11170 operatingChannel);
11171
11172 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11173 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011174 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011175 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11176 }
11177#ifdef FEATURE_WLAN_WAPI
11178 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011179 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011180 switch (pAdapter->wapi_info.wapiAuthMode) {
11181 case WAPI_AUTH_MODE_PSK:
11182 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011183 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011184 pAdapter->wapi_info.wapiAuthMode);
11185 pRoamProfile->AuthType.authType[0] =
11186 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11187 break;
11188 }
11189 case WAPI_AUTH_MODE_CERT:
11190 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011191 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011192 pAdapter->wapi_info.wapiAuthMode);
11193 pRoamProfile->AuthType.authType[0] =
11194 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11195 break;
11196 }
11197 } /* End of switch */
11198 if (pAdapter->wapi_info.wapiAuthMode ==
11199 WAPI_AUTH_MODE_PSK
11200 || pAdapter->wapi_info.wapiAuthMode ==
11201 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011202 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011203 pRoamProfile->AuthType.numEntries = 1;
11204 pRoamProfile->EncryptionType.numEntries = 1;
11205 pRoamProfile->EncryptionType.encryptionType[0] =
11206 eCSR_ENCRYPT_TYPE_WPI;
11207 pRoamProfile->mcEncryptionType.numEntries = 1;
11208 pRoamProfile->mcEncryptionType.
11209 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11210 }
11211 }
Krunal Soni31949422016-07-29 17:17:53 -070011212#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011213#ifdef WLAN_FEATURE_GTK_OFFLOAD
11214 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011215 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11216 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011217 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11218 sizeof(tSirGtkOffloadParams));
11219 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11220 GTK_OFFLOAD_DISABLE;
11221 }
11222#endif
11223 pRoamProfile->csrPersona = pAdapter->device_mode;
11224
11225 if (operatingChannel) {
11226 pRoamProfile->ChannelInfo.ChannelList =
11227 &operatingChannel;
11228 pRoamProfile->ChannelInfo.numOfChannels = 1;
11229 } else {
11230 pRoamProfile->ChannelInfo.ChannelList = NULL;
11231 pRoamProfile->ChannelInfo.numOfChannels = 0;
11232 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011233 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011234 && operatingChannel) {
11235 /*
11236 * Need to post the IBSS power save parameters
11237 * to WMA. WMA will configure this parameters
11238 * to firmware if power save is enabled by the
11239 * firmware.
11240 */
11241 status = hdd_set_ibss_power_save_params(pAdapter);
11242
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011243 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011244 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011245 return -EINVAL;
11246 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011247 pRoamProfile->ch_params.ch_width =
11248 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011249 /*
11250 * In IBSS mode while operating in 2.4 GHz,
11251 * the device supports only 20 MHz.
11252 */
11253 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11254 pRoamProfile->ch_params.ch_width =
11255 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011256 hdd_select_cbmode(pAdapter, operatingChannel,
11257 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011258 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011259 /*
11260 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11261 * or pmf=2 is an explicit configuration in the supplicant
11262 * configuration, drop the connection request.
11263 */
11264 if (pWextState->roamProfile.MFPEnabled &&
11265 !(pWextState->roamProfile.MFPRequired ||
11266 pWextState->roamProfile.MFPCapable)) {
11267 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11268 pWextState->roamProfile.MFPEnabled,
11269 pWextState->roamProfile.MFPRequired,
11270 pWextState->roamProfile.MFPCapable);
11271 return -EINVAL;
11272 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011273
Krunal Soni3091bcc2016-06-23 12:28:21 -070011274 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011275 hdd_err("Connection refused: conn in progress");
11276 return -EINVAL;
11277 }
11278
Krunal Soni31949422016-07-29 17:17:53 -070011279 /*
11280 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011281 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011282 * enhancements, the supplicant is not issuing the scan command
11283 * now. So the unicast frames which are sent from the host are
11284 * not having the additional IEs. If it is P2P CLIENT and there
11285 * is no additional IE present in roamProfile, then use the
11286 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011287 */
11288
Krunal Sonib4326f22016-03-10 13:05:51 -080011289 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011290 (!pRoamProfile->pAddIEScan)) {
11291 pRoamProfile->pAddIEScan =
11292 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11293 pRoamProfile->nAddIEScanLength =
11294 pAdapter->scan_info.scanAddIE.length;
11295 }
11296 /*
11297 * When policy manager is enabled from ini file, we shouldn't
11298 * check for other concurrency rules.
11299 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011300 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011301 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011302 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011303 pAdapter, pRoamProfile, &roamId))
11304 return 0;
11305 }
11306
Krunal Soni3091bcc2016-06-23 12:28:21 -070011307 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011308 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11309 pRoamProfile))) {
11310 hdd_err("sap-sta conc will fail, can't allow sta");
11311 hdd_conn_set_connection_state(pAdapter,
11312 eConnectionState_NotConnected);
11313 return -ENOMEM;
11314 }
11315
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011316 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011317 if (!sme_config) {
11318 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011319 hdd_conn_set_connection_state(pAdapter,
11320 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011321 return -ENOMEM;
11322 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011323 qdf_mem_zero(sme_config, sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011324 sme_get_config_param(pHddCtx->hHal, sme_config);
11325 /* These values are not sessionized. So, any change in these SME
11326 * configs on an older or parallel interface will affect the
11327 * cb mode. So, restoring the default INI params before starting
11328 * interfaces such as sta, cli etc.,
11329 */
11330 sme_config->csrConfig.channelBondingMode5GHz =
11331 pHddCtx->config->nChannelBondingMode5GHz;
11332 sme_config->csrConfig.channelBondingMode24GHz =
11333 pHddCtx->config->nChannelBondingMode24GHz;
11334 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011335 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011336 /*
11337 * Change conn_state to connecting before sme_roam_connect(),
11338 * because sme_roam_connect() has a direct path to call
11339 * hdd_sme_roam_callback(), which will change the conn_state
11340 * If direct path, conn_state will be accordingly changed to
11341 * NotConnected or Associated by either
11342 * hdd_association_completion_handler() or
11343 * hdd_dis_connect_handler() in sme_RoamCallback()if
11344 * sme_RomConnect is to be queued,
11345 * Connecting state will remain until it is completed.
11346 *
11347 * If connection state is not changed, connection state will
11348 * remain in eConnectionState_NotConnected state.
11349 * In hdd_association_completion_handler, "hddDisconInProgress"
11350 * is set to true if conn state is
11351 * eConnectionState_NotConnected.
11352 * If "hddDisconInProgress" is set to true then cfg80211 layer
11353 * is not informed of connect result indication which
11354 * is an issue.
11355 */
11356 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011357 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011358 hdd_conn_set_connection_state(pAdapter,
11359 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011360
11361 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11362 pAdapter->sessionId, pRoamProfile,
11363 &roamId);
11364
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011365 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011366 (QDF_STA_MODE == pAdapter->device_mode ||
11367 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011368 hdd_err("sme_roam_connect (session %d) failed with "
11369 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011370 pAdapter->sessionId, status);
11371 /* change back to NotAssociated */
11372 hdd_conn_set_connection_state(pAdapter,
11373 eConnectionState_NotConnected);
11374 }
11375
11376 pRoamProfile->ChannelInfo.ChannelList = NULL;
11377 pRoamProfile->ChannelInfo.numOfChannels = 0;
11378
11379 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011380 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011381 return -EINVAL;
11382 }
11383 EXIT();
11384 return status;
11385}
11386
11387/**
11388 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11389 * @pAdapter: Pointer to adapter
11390 * @auth_type: Auth type
11391 *
11392 * This function is used to set the authentication type (OPEN/SHARED).
11393 *
11394 * Return: 0 for success, non-zero for failure
11395 */
11396static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11397 enum nl80211_auth_type auth_type)
11398{
11399 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11400 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11401
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011402 /*set authentication type */
11403 switch (auth_type) {
11404 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011405 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011406 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11407 break;
11408
11409 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011410 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011411 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011412 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11413 break;
11414
11415 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011416 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011417 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11418 break;
11419#ifdef FEATURE_WLAN_ESE
11420 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011421 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011422 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11423 break;
11424#endif
11425
11426 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011427 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011428 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11429 return -EINVAL;
11430 }
11431
11432 pWextState->roamProfile.AuthType.authType[0] =
11433 pHddStaCtx->conn_info.authType;
11434 return 0;
11435}
11436
11437/**
11438 * wlan_hdd_set_akm_suite() - set key management type
11439 * @pAdapter: Pointer to adapter
11440 * @key_mgmt: Key management type
11441 *
11442 * This function is used to set the key mgmt type(PSK/8021x).
11443 *
11444 * Return: 0 for success, non-zero for failure
11445 */
11446static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11447{
11448 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11449
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011450#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11451#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11452 /*set key mgmt type */
11453 switch (key_mgmt) {
11454 case WLAN_AKM_SUITE_PSK:
11455 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011456 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011457 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011458 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11459 break;
11460
11461 case WLAN_AKM_SUITE_8021X_SHA256:
11462 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011463 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011464 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011465 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11466 break;
11467#ifdef FEATURE_WLAN_ESE
11468#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11469#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11470 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011471 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011472 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11473 break;
11474#endif
11475#ifndef WLAN_AKM_SUITE_OSEN
11476#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11477#endif
11478 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011479 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011480 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11481 break;
11482
11483 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011484 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011485 return -EINVAL;
11486
11487 }
11488 return 0;
11489}
11490
11491/**
11492 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11493 * @pAdapter: Pointer to adapter
11494 * @cipher: Cipher type
11495 * @ucast: Unicast flag
11496 *
11497 * This function is used to set the encryption type
11498 * (NONE/WEP40/WEP104/TKIP/CCMP).
11499 *
11500 * Return: 0 for success, non-zero for failure
11501 */
11502static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11503 u32 cipher, bool ucast)
11504{
11505 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11506 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11507 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11508
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011509 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011510 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011511 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11512 } else {
11513
11514 /*set encryption method */
11515 switch (cipher) {
11516 case IW_AUTH_CIPHER_NONE:
11517 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11518 break;
11519
11520 case WLAN_CIPHER_SUITE_WEP40:
11521 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11522 break;
11523
11524 case WLAN_CIPHER_SUITE_WEP104:
11525 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11526 break;
11527
11528 case WLAN_CIPHER_SUITE_TKIP:
11529 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11530 break;
11531
11532 case WLAN_CIPHER_SUITE_CCMP:
11533 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11534 break;
11535#ifdef FEATURE_WLAN_WAPI
11536 case WLAN_CIPHER_SUITE_SMS4:
11537 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11538 break;
11539#endif
11540
11541#ifdef FEATURE_WLAN_ESE
11542 case WLAN_CIPHER_SUITE_KRK:
11543 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11544 break;
11545#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11546 case WLAN_CIPHER_SUITE_BTK:
11547 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11548 break;
11549#endif
11550#endif
11551 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011552 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011553 return -EOPNOTSUPP;
11554 }
11555 }
11556
11557 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011558 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011559 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11560 pWextState->roamProfile.EncryptionType.numEntries = 1;
11561 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11562 encryptionType;
11563 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011564 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011565 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11566 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11567 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11568 encryptionType;
11569 }
11570
11571 return 0;
11572}
11573
11574/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011575 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11576 * @wext_state: Pointer to wext state
11577 * @gen_ie: Pointer to IE data
11578 * @len: length of IE data
11579 *
11580 * Return: 0 for success, non-zero for failure
11581 */
11582static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11583 const uint8_t *gen_ie, uint16_t len)
11584{
11585 uint16_t cur_add_ie_len =
11586 wext_state->assocAddIE.length;
11587
11588 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11589 (wext_state->assocAddIE.length + len)) {
11590 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11591 QDF_ASSERT(0);
11592 return -ENOMEM;
11593 }
11594 memcpy(wext_state->assocAddIE.addIEdata +
11595 cur_add_ie_len, gen_ie, len);
11596 wext_state->assocAddIE.length += len;
11597
11598 wext_state->roamProfile.pAddIEAssoc =
11599 wext_state->assocAddIE.addIEdata;
11600 wext_state->roamProfile.nAddIEAssocLength =
11601 wext_state->assocAddIE.length;
11602 return 0;
11603}
11604
11605/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011606 * wlan_hdd_cfg80211_set_ie() - set IEs
11607 * @pAdapter: Pointer to adapter
11608 * @ie: Pointer ot ie
11609 * @ie: IE length
11610 *
11611 * Return: 0 for success, non-zero for failure
11612 */
11613int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
11614 size_t ie_len)
11615{
11616 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11617 const uint8_t *genie = ie;
11618 uint16_t remLen = ie_len;
11619#ifdef FEATURE_WLAN_WAPI
11620 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
11621 u16 *tmp;
11622 uint16_t akmsuiteCount;
11623 int *akmlist;
11624#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011625 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011626
11627 /* clear previous assocAddIE */
11628 pWextState->assocAddIE.length = 0;
11629 pWextState->roamProfile.bWPSAssociation = false;
11630 pWextState->roamProfile.bOSENAssociation = false;
11631
11632 while (remLen >= 2) {
11633 uint16_t eLen = 0;
11634 uint8_t elementId;
11635 elementId = *genie++;
11636 eLen = *genie++;
11637 remLen -= 2;
11638
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011639 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011640
11641 switch (elementId) {
11642 case DOT11F_EID_WPA:
11643 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 -070011644 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011645 return -EINVAL;
11646 } else if (0 ==
11647 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
11648 uint16_t curAddIELen =
11649 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011650 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011651
11652 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11653 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011654 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011655 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011656 return -ENOMEM;
11657 }
11658 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11659 memcpy(pWextState->assocAddIE.addIEdata +
11660 curAddIELen, genie - 2, eLen + 2);
11661 pWextState->assocAddIE.length += eLen + 2;
11662
11663 pWextState->roamProfile.bWPSAssociation = true;
11664 pWextState->roamProfile.pAddIEAssoc =
11665 pWextState->assocAddIE.addIEdata;
11666 pWextState->roamProfile.nAddIEAssocLength =
11667 pWextState->assocAddIE.length;
11668 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011669 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011670 memset(pWextState->WPARSNIE, 0,
11671 MAX_WPA_RSN_IE_LEN);
11672 memcpy(pWextState->WPARSNIE, genie - 2,
11673 (eLen + 2));
11674 pWextState->roamProfile.pWPAReqIE =
11675 pWextState->WPARSNIE;
11676 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
11677 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
11678 P2P_OUI_TYPE_SIZE))) {
11679 uint16_t curAddIELen =
11680 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011681 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011682
11683 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11684 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011685 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011686 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011687 return -ENOMEM;
11688 }
11689 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11690 memcpy(pWextState->assocAddIE.addIEdata +
11691 curAddIELen, genie - 2, eLen + 2);
11692 pWextState->assocAddIE.length += eLen + 2;
11693
11694 pWextState->roamProfile.pAddIEAssoc =
11695 pWextState->assocAddIE.addIEdata;
11696 pWextState->roamProfile.nAddIEAssocLength =
11697 pWextState->assocAddIE.length;
11698 }
11699#ifdef WLAN_FEATURE_WFD
11700 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
11701 WFD_OUI_TYPE_SIZE)) &&
11702 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080011703 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011704 pAdapter->device_mode)) {
11705 uint16_t curAddIELen =
11706 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011707 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011708
11709 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11710 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011711 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011712 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011713 return -ENOMEM;
11714 }
11715 /* WFD IE is saved to Additional IE ; it should
11716 * be accumulated to handle WPS IE + P2P IE +
11717 * WFD IE */
11718 memcpy(pWextState->assocAddIE.addIEdata +
11719 curAddIELen, genie - 2, eLen + 2);
11720 pWextState->assocAddIE.length += eLen + 2;
11721
11722 pWextState->roamProfile.pAddIEAssoc =
11723 pWextState->assocAddIE.addIEdata;
11724 pWextState->roamProfile.nAddIEAssocLength =
11725 pWextState->assocAddIE.length;
11726 }
11727#endif
11728 /* Appending HS 2.0 Indication Element in Assiciation Request */
11729 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
11730 HS20_OUI_TYPE_SIZE))) {
11731 uint16_t curAddIELen =
11732 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011733 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011734
11735 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11736 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011737 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011738 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011739 return -ENOMEM;
11740 }
11741 memcpy(pWextState->assocAddIE.addIEdata +
11742 curAddIELen, genie - 2, eLen + 2);
11743 pWextState->assocAddIE.length += eLen + 2;
11744
11745 pWextState->roamProfile.pAddIEAssoc =
11746 pWextState->assocAddIE.addIEdata;
11747 pWextState->roamProfile.nAddIEAssocLength =
11748 pWextState->assocAddIE.length;
11749 }
11750 /* Appending OSEN Information Element in Assiciation Request */
11751 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
11752 OSEN_OUI_TYPE_SIZE))) {
11753 uint16_t curAddIELen =
11754 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011755 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011756
11757 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11758 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011759 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011760 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011761 return -ENOMEM;
11762 }
11763 memcpy(pWextState->assocAddIE.addIEdata +
11764 curAddIELen, genie - 2, eLen + 2);
11765 pWextState->assocAddIE.length += eLen + 2;
11766
11767 pWextState->roamProfile.bOSENAssociation = true;
11768 pWextState->roamProfile.pAddIEAssoc =
11769 pWextState->assocAddIE.addIEdata;
11770 pWextState->roamProfile.nAddIEAssocLength =
11771 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011772 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
11773 MBO_OUI_TYPE_SIZE))){
11774 hdd_info("Set MBO IE(len %d)", eLen + 2);
11775 status = wlan_hdd_add_assoc_ie(pWextState,
11776 genie - 2, eLen + 2);
11777 if (status)
11778 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011779 } else {
11780 uint16_t add_ie_len =
11781 pWextState->assocAddIE.length;
11782
11783 hdd_info("Set OSEN IE(len %d)", eLen + 2);
11784
11785 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11786 (pWextState->assocAddIE.length + eLen)) {
11787 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011788 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011789 return -ENOMEM;
11790 }
11791
11792 memcpy(pWextState->assocAddIE.addIEdata +
11793 add_ie_len, genie - 2, eLen + 2);
11794 pWextState->assocAddIE.length += eLen + 2;
11795
11796 pWextState->roamProfile.pAddIEAssoc =
11797 pWextState->assocAddIE.addIEdata;
11798 pWextState->roamProfile.nAddIEAssocLength =
11799 pWextState->assocAddIE.length;
11800 }
11801 break;
11802 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011803 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011804 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
11805 memcpy(pWextState->WPARSNIE, genie - 2,
11806 (eLen + 2));
11807 pWextState->roamProfile.pRSNReqIE =
11808 pWextState->WPARSNIE;
11809 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
11810 break;
11811 /*
11812 * Appending Extended Capabilities with Interworking bit set
11813 * in Assoc Req.
11814 *
11815 * In assoc req this EXT Cap will only be taken into account if
11816 * interworkingService bit is set to 1. Currently
11817 * driver is only interested in interworkingService capability
11818 * from supplicant. If in future any other EXT Cap info is
11819 * required from supplicat, it needs to be handled while
11820 * sending Assoc Req in LIM.
11821 */
11822 case DOT11F_EID_EXTCAP:
11823 {
11824 uint16_t curAddIELen =
11825 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011826 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011827
11828 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11829 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011830 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011831 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011832 return -ENOMEM;
11833 }
11834 memcpy(pWextState->assocAddIE.addIEdata +
11835 curAddIELen, genie - 2, eLen + 2);
11836 pWextState->assocAddIE.length += eLen + 2;
11837
11838 pWextState->roamProfile.pAddIEAssoc =
11839 pWextState->assocAddIE.addIEdata;
11840 pWextState->roamProfile.nAddIEAssocLength =
11841 pWextState->assocAddIE.length;
11842 break;
11843 }
11844#ifdef FEATURE_WLAN_WAPI
11845 case WLAN_EID_WAPI:
11846 /* Setting WAPI Mode to ON=1 */
11847 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011848 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011849 tmp = (u16 *) ie;
11850 tmp = tmp + 2; /* Skip element Id and Len, Version */
11851 akmsuiteCount = WPA_GET_LE16(tmp);
11852 tmp = tmp + 1;
11853 akmlist = (int *)(tmp);
11854 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
11855 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
11856 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011857 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011858 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011859 return -EINVAL;
11860 }
11861
11862 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011863 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011864 pAdapter->wapi_info.wapiAuthMode =
11865 WAPI_AUTH_MODE_PSK;
11866 }
11867 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011868 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011869 pAdapter->wapi_info.wapiAuthMode =
11870 WAPI_AUTH_MODE_CERT;
11871 }
11872 break;
11873#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011874 case DOT11F_EID_SUPPOPERATINGCLASSES:
11875 {
11876 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
11877 status = wlan_hdd_add_assoc_ie(pWextState,
11878 genie - 2, eLen + 2);
11879 if (status)
11880 return status;
11881 break;
11882 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011883 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011884 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011885 /* when Unknown IE is received we should break and continue
11886 * to the next IE in the buffer instead we were returning
11887 * so changing this to break */
11888 break;
11889 }
11890 genie += eLen;
11891 remLen -= eLen;
11892 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011893 return 0;
11894}
11895
11896/**
11897 * hdd_is_wpaie_present() - check for WPA ie
11898 * @ie: Pointer to ie
11899 * @ie_len: Ie length
11900 *
11901 * Parse the received IE to find the WPA IE
11902 *
11903 * Return: true if wpa ie is found else false
11904 */
11905static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
11906{
11907 uint8_t eLen = 0;
11908 uint16_t remLen = ie_len;
11909 uint8_t elementId = 0;
11910
11911 while (remLen >= 2) {
11912 elementId = *ie++;
11913 eLen = *ie++;
11914 remLen -= 2;
11915 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011916 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011917 return false;
11918 }
11919 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
11920 /* OUI - 0x00 0X50 0XF2
11921 * WPA Information Element - 0x01
11922 * WPA version - 0x01
11923 */
11924 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
11925 return true;
11926 }
11927 ie += eLen;
11928 remLen -= eLen;
11929 }
11930 return false;
11931}
11932
11933/**
11934 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
11935 * @pAdapter: Pointer to adapter
11936 * @req: Pointer to security parameters
11937 *
11938 * Return: 0 for success, non-zero for failure
11939 */
11940int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
11941 struct cfg80211_connect_params *req)
11942{
11943 int status = 0;
11944 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11945 ENTER();
11946
11947 /*set wpa version */
11948 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
11949
11950 if (req->crypto.wpa_versions) {
11951 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
11952 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
11953 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
11954 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
11955 }
11956 }
11957
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011958 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011959
11960 /*set authentication type */
11961 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
11962
11963 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011964 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011965 return status;
11966 }
11967
11968 /*set key mgmt type */
11969 if (req->crypto.n_akm_suites) {
11970 status =
11971 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
11972 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011973 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011974 return status;
11975 }
11976 }
11977
11978 /*set pairwise cipher type */
11979 if (req->crypto.n_ciphers_pairwise) {
11980 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
11981 req->crypto.
11982 ciphers_pairwise[0],
11983 true);
11984 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011985 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011986 return status;
11987 }
11988 } else {
11989 /*Reset previous cipher suite to none */
11990 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
11991 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011992 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011993 return status;
11994 }
11995 }
11996
11997 /*set group cipher type */
11998 status =
11999 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12000 false);
12001
12002 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012003 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012004 return status;
12005 }
12006#ifdef WLAN_FEATURE_11W
12007 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12008#endif
12009
12010 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12011 if (req->ie_len) {
12012 status =
12013 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12014 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012015 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012016 return status;
12017 }
12018 }
12019
12020 /*incase of WEP set default key information */
12021 if (req->key && req->key_len) {
12022 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12023 || (WLAN_CIPHER_SUITE_WEP104 ==
12024 req->crypto.ciphers_pairwise[0])
12025 ) {
12026 if (IW_AUTH_KEY_MGMT_802_1X
12027 ==
12028 (pWextState->
12029 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012030 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012031 return -EOPNOTSUPP;
12032 } else {
12033 u8 key_len = req->key_len;
12034 u8 key_idx = req->key_idx;
12035
12036 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12037 key_len)
12038 && (CSR_MAX_NUM_KEY > key_idx)
12039 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012040 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012041 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012042 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012043 Keys.
12044 KeyMaterial[key_idx][0],
12045 req->key, key_len);
12046 pWextState->roamProfile.Keys.
12047 KeyLength[key_idx] = (u8) key_len;
12048 pWextState->roamProfile.Keys.
12049 defaultIndex = (u8) key_idx;
12050 }
12051 }
12052 }
12053 }
12054
12055 return status;
12056}
12057
12058/**
12059 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12060 * @pAdapter: Pointer to adapter
12061 *
12062 * This function is used to disconnect from previous connection
12063 *
12064 * Return: 0 for success, non-zero for failure
12065 */
12066static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12067{
12068 unsigned long rc;
12069 hdd_station_ctx_t *pHddStaCtx;
12070 eMib_dot11DesiredBssType connectedBssType;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012071 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012072
12073 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12074
12075 hdd_conn_get_connected_bss_type(pHddStaCtx, &connectedBssType);
12076
12077 if ((eMib_dot11DesiredBssType_independent == connectedBssType) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012078 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12079 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12080 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012081 hdd_conn_set_connection_state(pAdapter,
12082 eConnectionState_Disconnecting);
12083 /* Issue disconnect to CSR */
12084 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012085
12086 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12087 pAdapter->sessionId,
12088 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12089 /*
12090 * Wait here instead of returning directly, this will block the
12091 * next connect command and allow processing of the scan for
12092 * ssid and the previous connect command in CSR. Else we might
12093 * hit some race conditions leading to SME and HDD out of sync.
12094 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012095 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012096 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12097 } else if (0 != status) {
12098 hdd_err("csrRoamDisconnect failure, returned %d",
12099 (int)status);
12100 pHddStaCtx->staDebugState = status;
12101 result = -EINVAL;
12102 goto disconnected;
12103 }
12104
12105 rc = wait_for_completion_timeout(
12106 &pAdapter->disconnect_comp_var,
12107 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012108 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012109 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12110 pAdapter->sessionId, pHddStaCtx->staDebugState);
12111 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012112 }
12113 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012114 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012115 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012116 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012117 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012118 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012119 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012120 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012121 }
12122 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012123disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012124 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12125 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012126}
12127
12128/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012129 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12130 * @adapter: Pointer to the HDD adapter
12131 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012132 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012133 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012134 * This function will start reassociation if prev_bssid is set and bssid/
12135 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012136 *
Naveen Rawat07332902016-07-27 09:13:17 -070012137 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012138 */
12139#ifdef CFG80211_CONNECT_PREV_BSSID
Naveen Rawat07332902016-07-27 09:13:17 -070012140static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12141 struct cfg80211_connect_params *req,
12142 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012143{
Naveen Rawat07332902016-07-27 09:13:17 -070012144 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012145 const uint8_t *bssid = NULL;
12146 uint16_t channel = 0;
12147
12148 if (req->bssid)
12149 bssid = req->bssid;
12150 else if (req->bssid_hint)
12151 bssid = req->bssid_hint;
12152
12153 if (req->channel)
12154 channel = req->channel->hw_value;
12155 else if (req->channel_hint)
12156 channel = req->channel_hint->hw_value;
12157
12158 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012159 reassoc = true;
12160 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012161 channel, MAC_ADDR_ARRAY(bssid));
12162 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012163 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012164 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012165 }
Naveen Rawat07332902016-07-27 09:13:17 -070012166 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012167}
12168#else
Naveen Rawat07332902016-07-27 09:13:17 -070012169static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12170 struct cfg80211_connect_params *req,
12171 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012172{
Naveen Rawat07332902016-07-27 09:13:17 -070012173 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012174}
12175#endif
12176
12177/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012178 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12179 * @wiphy: Pointer to wiphy
12180 * @dev: Pointer to network device
12181 * @req: Pointer to cfg80211 connect request
12182 *
12183 * This function is used to start the association process
12184 *
12185 * Return: 0 for success, non-zero for failure
12186 */
12187static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12188 struct net_device *ndev,
12189 struct cfg80211_connect_params *req)
12190{
12191 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012192 u16 channel;
12193#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12194 const u8 *bssid_hint = req->bssid_hint;
12195#else
12196 const u8 *bssid_hint = NULL;
12197#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012198 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12199 hdd_context_t *pHddCtx;
12200
12201 ENTER();
12202
Anurag Chouhan6d760662016-02-20 16:05:43 +053012203 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012204 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012205 return -EINVAL;
12206 }
12207
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012208 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012209 TRACE_CODE_HDD_CFG80211_CONNECT,
12210 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012211 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012212 hdd_device_mode_to_string(pAdapter->device_mode),
12213 pAdapter->device_mode);
12214
Krunal Sonib4326f22016-03-10 13:05:51 -080012215 if (pAdapter->device_mode != QDF_STA_MODE &&
12216 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012217 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012218 hdd_device_mode_to_string(pAdapter->device_mode),
12219 pAdapter->device_mode);
12220 return -EINVAL;
12221 }
12222
12223 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12224 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012225 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012226 return -EINVAL;
12227 }
12228
12229 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012230 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012231 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012232
Naveen Rawat07332902016-07-27 09:13:17 -070012233 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012234 return status;
12235
Agrawal Ashishf156e942016-08-04 14:54:47 +053012236 wlan_hdd_disable_roaming(pAdapter);
12237
12238 /* Try disconnecting if already in connected state */
12239 status = wlan_hdd_try_disconnect(pAdapter);
12240 if (0 > status) {
12241 hdd_err("Failed to disconnect the existing connection");
12242 return -EALREADY;
12243 }
12244
12245 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012246 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012247 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012248 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012249 pAdapter->device_mode),
12250 req->channel->hw_value, HW_MODE_20_MHZ)) {
12251 hdd_err("This concurrency combination is not allowed");
12252 return -ECONNREFUSED;
12253 }
12254 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012255 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012256 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012257 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12258 hdd_err("This concurrency combination is not allowed");
12259 return -ECONNREFUSED;
12260 }
12261 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012262
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012263 /*initialise security parameters */
12264 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12265
12266 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012267 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012268 return status;
12269 }
12270
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012271 if (req->channel)
12272 channel = req->channel->hw_value;
12273 else
12274 channel = 0;
12275 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12276 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012277 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012278 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012279 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012280 return status;
12281 }
12282 EXIT();
12283 return status;
12284}
12285
12286/**
12287 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12288 * @wiphy: Pointer to wiphy
12289 * @dev: Pointer to network device
12290 * @req: Pointer to cfg80211 connect request
12291 *
12292 * Return: 0 for success, non-zero for failure
12293 */
12294static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12295 struct net_device *ndev,
12296 struct cfg80211_connect_params *req)
12297{
12298 int ret;
12299 cds_ssr_protect(__func__);
12300 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12301 cds_ssr_unprotect(__func__);
12302
12303 return ret;
12304}
12305
12306/**
12307 * wlan_hdd_disconnect() - hdd disconnect api
12308 * @pAdapter: Pointer to adapter
12309 * @reason: Disconnect reason code
12310 *
12311 * This function is used to issue a disconnect request to SME
12312 *
12313 * Return: 0 for success, non-zero for failure
12314 */
12315int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
12316{
12317 int status, result = 0;
12318 unsigned long rc;
12319 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12320 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12321
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012322 ENTER();
12323
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324 status = wlan_hdd_validate_context(pHddCtx);
12325
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012326 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012327 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012328
12329 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012330 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012331 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12332 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012333 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12335 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12336
12337 /*issue disconnect */
12338
12339 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12340 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012341 /*
12342 * Wait here instead of returning directly, this will block the next
12343 * connect command and allow processing of the scan for ssid and
12344 * the previous connect command in CSR. Else we might hit some
12345 * race conditions leading to SME and HDD out of sync.
12346 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012347 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012348 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012349 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012350 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012351 (int)status);
12352 pHddStaCtx->staDebugState = status;
12353 result = -EINVAL;
12354 goto disconnected;
12355 }
12356 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12357 msecs_to_jiffies
12358 (WLAN_WAIT_TIME_DISCONNECT));
12359
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012360 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012361 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012362 result = -ETIMEDOUT;
12363 }
12364disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012365 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12366#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12367 /* Sending disconnect event to userspace for kernel version < 3.11
12368 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12369 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012370 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012371 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12372 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012373#endif
12374
12375 return result;
12376}
12377
12378/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012379 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12380 * @reason: ieee80211 reason code.
12381 *
12382 * This utility function helps log string conversion of reason code.
12383 *
12384 * Return: string conversion of reason code, if match found;
12385 * "Unknown" otherwise.
12386 */
12387static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12388{
12389 switch (reason) {
12390 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12391 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12392 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12393 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12394 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12395 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12396 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12397 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12398 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12399 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12400 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12401 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12402 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12403 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12404 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12405 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12406 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12407 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12408 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12409 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12410 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12411 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12412 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12413 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12414 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12415 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12416 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12417 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12418 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12419 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12420 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12421 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12422 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12423 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12424 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12425 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12426 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12427 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12428 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12429 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12430 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12431 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12432 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12433 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12434 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12435 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12436 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12437 default:
12438 return "Unknown";
12439 }
12440}
12441
12442/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012443 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12444 * @wiphy: Pointer to wiphy
12445 * @dev: Pointer to network device
12446 * @reason: Disconnect reason code
12447 *
12448 * This function is used to issue a disconnect request to SME
12449 *
12450 * Return: 0 for success, non-zero for failure
12451 */
12452static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12453 struct net_device *dev, u16 reason)
12454{
12455 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12456 int status;
12457 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12458 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12459#ifdef FEATURE_WLAN_TDLS
12460 uint8_t staIdx;
12461#endif
12462
12463 ENTER();
12464
Anurag Chouhan6d760662016-02-20 16:05:43 +053012465 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012466 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012467 return -EINVAL;
12468 }
12469
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012470 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012471 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12472 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012473 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012474 hdd_device_mode_to_string(pAdapter->device_mode),
12475 pAdapter->device_mode, reason);
12476
12477 status = wlan_hdd_validate_context(pHddCtx);
12478
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012479 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012480 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012481
12482 /* Issue disconnect request to SME, if station is in connected state */
12483 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12484 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12485 eCsrRoamDisconnectReason reasonCode =
12486 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12487 hdd_scaninfo_t *pScanInfo;
12488
12489 switch (reason) {
12490 case WLAN_REASON_MIC_FAILURE:
12491 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12492 break;
12493
12494 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12495 case WLAN_REASON_DISASSOC_AP_BUSY:
12496 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12497 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12498 break;
12499
12500 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12501 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12502 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12503 break;
12504
12505 case WLAN_REASON_DEAUTH_LEAVING:
12506 reasonCode =
12507 pHddCtx->config->
12508 gEnableDeauthToDisassocMap ?
12509 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12510 eCSR_DISCONNECT_REASON_DEAUTH;
12511 break;
12512 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12513 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12514 break;
12515 default:
12516 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12517 break;
12518 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012519 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012520 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012521 pScanInfo = &pAdapter->scan_info;
12522 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012523 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012524 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12525 eCSR_SCAN_ABORT_DEFAULT);
12526 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012527 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012528#ifdef FEATURE_WLAN_TDLS
12529 /* First clean up the tdls peers if any */
12530 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12531 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12532 pAdapter->sessionId)
12533 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12534 uint8_t *mac;
12535 mac =
12536 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012537 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12538 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012539 pHddCtx->tdlsConnInfo[staIdx].staId,
12540 pAdapter->sessionId,
12541 MAC_ADDR_ARRAY(mac));
12542 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12543 (pAdapter),
12544 pAdapter->sessionId, mac);
12545 }
12546 }
12547#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012548 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012549 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012550 hdd_info("Disconnect request from user space with reason: %s",
12551 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012552 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12553 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012554 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012555 return -EINVAL;
12556 }
12557 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012558 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012559 pHddStaCtx->conn_info.connState);
12560 }
12561
12562 return status;
12563}
12564
12565/**
12566 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12567 * @wiphy: Pointer to wiphy
12568 * @dev: Pointer to network device
12569 * @reason: Disconnect reason code
12570 *
12571 * Return: 0 for success, non-zero for failure
12572 */
12573static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12574 struct net_device *dev, u16 reason)
12575{
12576 int ret;
12577 cds_ssr_protect(__func__);
12578 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12579 cds_ssr_unprotect(__func__);
12580
12581 return ret;
12582}
12583
12584/**
12585 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12586 * @pAdapter: Pointer to adapter
12587 * @param: Pointer to IBSS parameters
12588 *
12589 * This function is used to initialize the security settings in IBSS mode
12590 *
12591 * Return: 0 for success, non-zero for failure
12592 */
12593static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12594 struct cfg80211_ibss_params
12595 *params)
12596{
12597 int status = 0;
12598 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12599 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12600 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12601
12602 ENTER();
12603
12604 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012605 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012606 pHddStaCtx->ibss_enc_key_installed = 0;
12607
12608 if (params->ie_len && (NULL != params->ie)) {
12609 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12610 params->ie_len, WLAN_EID_RSN)) {
12611 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12612 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12613 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
12614 tDot11fIEWPA dot11WPAIE;
12615 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12616 u8 *ie;
12617
12618 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12619 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12620 params->ie_len,
12621 DOT11F_EID_WPA);
12622 if (NULL != ie) {
12623 pWextState->wpaVersion =
12624 IW_AUTH_WPA_VERSION_WPA;
12625 /* Unpack the WPA IE */
12626 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
12627 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
12628 &ie[2 + 4],
12629 ie[1] - 4, &dot11WPAIE);
12630 /*Extract the multicast cipher, the encType for unicast
12631 cipher for wpa-none is none */
12632 encryptionType =
12633 hdd_translate_wpa_to_csr_encryption_type
12634 (dot11WPAIE.multicast_cipher);
12635 }
12636 }
12637
12638 status =
12639 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
12640 params->ie_len);
12641
12642 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012643 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012644 return status;
12645 }
12646 }
12647
12648 pWextState->roamProfile.AuthType.authType[0] =
12649 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12650
12651 if (params->privacy) {
12652 /* Security enabled IBSS, At this time there is no information
12653 * available about the security paramters, so initialise the
12654 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
12655 * The correct security parameters will be updated later in
12656 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
12657 * set inorder enable privacy bit in beacons
12658 */
12659
12660 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12661 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012662 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012663 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12664 pWextState->roamProfile.EncryptionType.numEntries = 1;
12665 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12666 encryptionType;
12667 return status;
12668}
12669
12670/**
12671 * __wlan_hdd_cfg80211_join_ibss() - join ibss
12672 * @wiphy: Pointer to wiphy
12673 * @dev: Pointer to network device
12674 * @param: Pointer to IBSS join parameters
12675 *
12676 * This function is used to create/join an IBSS network
12677 *
12678 * Return: 0 for success, non-zero for failure
12679 */
12680static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12681 struct net_device *dev,
12682 struct cfg80211_ibss_params *params)
12683{
12684 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12685 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12686 tCsrRoamProfile *pRoamProfile;
12687 int status;
12688 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12689 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053012690 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012691 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012692
12693 ENTER();
12694
Anurag Chouhan6d760662016-02-20 16:05:43 +053012695 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012696 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012697 return -EINVAL;
12698 }
12699
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012700 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012701 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
12702 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012703 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012704 hdd_device_mode_to_string(pAdapter->device_mode),
12705 pAdapter->device_mode);
12706
12707 status = wlan_hdd_validate_context(pHddCtx);
12708
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012709 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012710 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012711
12712 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053012713 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012714 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12715 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
12716 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12717 int indx;
12718
12719 /* Get channel number */
12720 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012721 params->
12722 chandef.
12723 chan->
12724 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012725
12726 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12727 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012728 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012729 return -EOPNOTSUPP;
12730 }
12731
12732 for (indx = 0; indx < numChans; indx++) {
12733 if (channelNum == validChan[indx]) {
12734 break;
12735 }
12736 }
12737 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012738 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012739 return -EINVAL;
12740 }
12741 }
12742
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012743 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012744 HW_MODE_20_MHZ)) {
12745 hdd_err("This concurrency combination is not allowed");
12746 return -ECONNREFUSED;
12747 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012748
Krunal Soni3091bcc2016-06-23 12:28:21 -070012749 status = qdf_reset_connection_update();
12750 if (!QDF_IS_STATUS_SUCCESS(status))
12751 hdd_err("ERR: clear event failed");
12752
12753 status = cds_current_connections_update(pAdapter->sessionId,
12754 channelNum,
12755 SIR_UPDATE_REASON_JOIN_IBSS);
12756 if (QDF_STATUS_E_FAILURE == status) {
12757 hdd_err("ERROR: connections update failed!!");
12758 return -EINVAL;
12759 }
12760
12761 if (QDF_STATUS_SUCCESS == status) {
12762 status = qdf_wait_for_connection_update();
12763 if (!QDF_IS_STATUS_SUCCESS(status)) {
12764 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012765 return -EINVAL;
12766 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012767 }
12768
12769 /*Try disconnecting if already in connected state */
12770 status = wlan_hdd_try_disconnect(pAdapter);
12771 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012772 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012773 return -EALREADY;
12774 }
12775
12776 pRoamProfile = &pWextState->roamProfile;
12777
12778 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012779 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012780 return -EINVAL;
12781 }
12782
12783 /* enable selected protection checks in IBSS mode */
12784 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
12785
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012786 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012787 WNI_CFG_IBSS_ATIM_WIN_SIZE,
12788 pHddCtx->config->
12789 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012790 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012791 }
12792
12793 /* BSSID is provided by upper layers hence no need to AUTO generate */
12794 if (NULL != params->bssid) {
12795 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012796 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012797 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012798 return -EIO;
12799 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012800 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012801 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
12802 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012803 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012804 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012805 return -EIO;
12806 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053012807 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012808 }
12809 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
12810 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
12811 pRoamProfile->beaconInterval = params->beacon_interval;
12812 else {
12813 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012814 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012815 params->beacon_interval, pRoamProfile->beaconInterval);
12816 }
12817
12818 /* Set Channel */
12819 if (channelNum) {
12820 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012821 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012822 pRoamProfile->ChannelInfo.numOfChannels = 1;
12823 pHddStaCtx->conn_info.operationChannel = channelNum;
12824 pRoamProfile->ChannelInfo.ChannelList =
12825 &pHddStaCtx->conn_info.operationChannel;
12826 }
12827
12828 /* Initialize security parameters */
12829 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
12830 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012831 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012832 return status;
12833 }
12834
12835 /* Issue connect start */
12836 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
12837 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012838 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012839 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012840 operationChannel,
12841 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012842
12843 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012844 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012845 return status;
12846 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012847 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012848 return 0;
12849}
12850
12851/**
12852 * wlan_hdd_cfg80211_join_ibss() - join ibss
12853 * @wiphy: Pointer to wiphy
12854 * @dev: Pointer to network device
12855 * @param: Pointer to IBSS join parameters
12856 *
12857 * This function is used to create/join an IBSS network
12858 *
12859 * Return: 0 for success, non-zero for failure
12860 */
12861static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12862 struct net_device *dev,
12863 struct cfg80211_ibss_params *params)
12864{
12865 int ret = 0;
12866
12867 cds_ssr_protect(__func__);
12868 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
12869 cds_ssr_unprotect(__func__);
12870
12871 return ret;
12872}
12873
12874/**
12875 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
12876 * @wiphy: Pointer to wiphy
12877 * @dev: Pointer to network device
12878 *
12879 * This function is used to leave an IBSS network
12880 *
12881 * Return: 0 for success, non-zero for failure
12882 */
12883static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
12884 struct net_device *dev)
12885{
12886 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12887 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12888 tCsrRoamProfile *pRoamProfile;
12889 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12890 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012891 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053012892 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012893 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012894
12895 ENTER();
12896
Anurag Chouhan6d760662016-02-20 16:05:43 +053012897 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012898 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012899 return -EINVAL;
12900 }
12901
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012902 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012903 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
12904 pAdapter->sessionId,
12905 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
12906 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012907 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012908 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012909
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012910 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012911 hdd_device_mode_to_string(pAdapter->device_mode),
12912 pAdapter->device_mode);
12913 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012914 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012915 return -EIO;
12916 }
12917
12918 pRoamProfile = &pWextState->roamProfile;
12919
12920 /* Issue disconnect only if interface type is set to IBSS */
12921 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012922 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012923 return -EINVAL;
12924 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012925 /* Clearing add IE of beacon */
12926 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
12927 sizeof(tSirMacAddr));
12928 updateIE.smeSessionId = pAdapter->sessionId;
12929 updateIE.ieBufferlength = 0;
12930 updateIE.pAdditionIEBuffer = NULL;
12931 updateIE.append = true;
12932 updateIE.notify = true;
12933 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
12934 &updateIE,
12935 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012936 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012937 }
12938
12939 /* Reset WNI_CFG_PROBE_RSP Flags */
12940 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012941
12942 /* Issue Disconnect request */
12943 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12944 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12945 pAdapter->sessionId,
12946 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012947 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012948 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012949 hal_status);
12950 return -EAGAIN;
12951 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053012952
12953 /* wait for mc thread to cleanup and then return to upper stack
12954 * so by the time upper layer calls the change interface, we are
12955 * all set to proceed further
12956 */
12957 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12958 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
12959 if (!rc) {
12960 hdd_err("Failed to disconnect, timed out");
12961 return -ETIMEDOUT;
12962 }
12963
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012964 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012965 return 0;
12966}
12967
12968/**
12969 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
12970 * @wiphy: Pointer to wiphy
12971 * @dev: Pointer to network device
12972 *
12973 * This function is used to leave an IBSS network
12974 *
12975 * Return: 0 for success, non-zero for failure
12976 */
12977static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
12978 struct net_device *dev)
12979{
12980 int ret = 0;
12981
12982 cds_ssr_protect(__func__);
12983 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
12984 cds_ssr_unprotect(__func__);
12985
12986 return ret;
12987}
12988
12989/**
12990 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
12991 * @wiphy: Pointer to wiphy
12992 * @changed: Parameters changed
12993 *
12994 * This function is used to set the phy parameters. RTS Threshold/FRAG
12995 * Threshold/Retry Count etc.
12996 *
12997 * Return: 0 for success, non-zero for failure
12998 */
12999static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13000 u32 changed)
13001{
13002 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13003 tHalHandle hHal = pHddCtx->hHal;
13004 int status;
13005
13006 ENTER();
13007
Anurag Chouhan6d760662016-02-20 16:05:43 +053013008 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013009 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013010 return -EINVAL;
13011 }
13012
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013013 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013014 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13015 NO_SESSION, wiphy->rts_threshold));
13016 status = wlan_hdd_validate_context(pHddCtx);
13017
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013018 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013019 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013020
13021 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13022 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13023 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13024
13025 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13026 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013027 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013028 rts_threshold);
13029 return -EINVAL;
13030 }
13031
13032 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13033 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013034 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013035 rts_threshold);
13036 return -EIO;
13037 }
13038
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013039 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013040 }
13041
13042 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13043 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13044 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13045 wiphy->frag_threshold;
13046
13047 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13048 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013049 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013050 frag_threshold);
13051 return -EINVAL;
13052 }
13053
13054 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13055 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013056 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013057 frag_threshold);
13058 return -EIO;
13059 }
13060
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013061 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013062 }
13063
13064 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13065 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13066 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13067 wiphy->retry_short : wiphy->retry_long;
13068
13069 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13070 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013071 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013072 return -EINVAL;
13073 }
13074
13075 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13076 if (0 != sme_cfg_set_int(hHal,
13077 WNI_CFG_LONG_RETRY_LIMIT,
13078 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013079 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013080 retry_value);
13081 return -EIO;
13082 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013083 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013084 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13085 if (0 != sme_cfg_set_int(hHal,
13086 WNI_CFG_SHORT_RETRY_LIMIT,
13087 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013088 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013089 retry_value);
13090 return -EIO;
13091 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013092 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013093 }
13094 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013095 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013096 return 0;
13097}
13098
13099/**
13100 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13101 * @wiphy: Pointer to wiphy
13102 * @changed: Parameters changed
13103 *
13104 * Return: 0 for success, non-zero for failure
13105 */
13106static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13107{
13108 int ret;
13109
13110 cds_ssr_protect(__func__);
13111 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13112 cds_ssr_unprotect(__func__);
13113
13114 return ret;
13115}
13116
13117/**
13118 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13119 * key
13120 * @wiphy: Pointer to wiphy
13121 * @dev: Pointer to network device
13122 * @key_index: Key index
13123 *
13124 * Return: 0
13125 */
13126static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13127 struct net_device *netdev,
13128 u8 key_index)
13129{
13130 ENTER();
13131 return 0;
13132}
13133
13134/**
13135 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13136 * wlan_hdd_set_default_mgmt_key
13137 * @wiphy: pointer to wiphy
13138 * @netdev: pointer to net_device structure
13139 * @key_index: key index
13140 *
13141 * Return: 0 on success, error number on failure
13142 */
13143static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13144 struct net_device *netdev,
13145 u8 key_index)
13146{
13147 int ret;
13148
13149 cds_ssr_protect(__func__);
13150 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13151 cds_ssr_unprotect(__func__);
13152
13153 return ret;
13154}
13155
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013156/**
13157 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13158 * @wiphy: Pointer to wiphy
13159 * @dev: Pointer to network device
13160 * @params: Pointer to tx queue parameters
13161 *
13162 * Return: 0
13163 */
13164static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13165 struct net_device *dev,
13166 struct ieee80211_txq_params *params)
13167{
13168 ENTER();
13169 return 0;
13170}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013171
13172/**
13173 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13174 * @wiphy: pointer to wiphy
13175 * @netdev: pointer to net_device structure
13176 * @params: pointer to ieee80211_txq_params
13177 *
13178 * Return: 0 on success, error number on failure
13179 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013180static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13181 struct net_device *dev,
13182 struct ieee80211_txq_params *params)
13183{
13184 int ret;
13185
13186 cds_ssr_protect(__func__);
13187 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13188 cds_ssr_unprotect(__func__);
13189
13190 return ret;
13191}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013192
13193/**
13194 * __wlan_hdd_cfg80211_del_station() - delete station v2
13195 * @wiphy: Pointer to wiphy
13196 * @param: Pointer to delete station parameter
13197 *
13198 * Return: 0 for success, non-zero for failure
13199 */
13200static
13201int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13202 struct net_device *dev,
13203 struct tagCsrDelStaParams *pDelStaParams)
13204{
13205 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13206 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013207 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013208 hdd_hostapd_state_t *hapd_state;
13209 int status;
13210 uint8_t staId;
13211 uint8_t *mac;
13212
13213 ENTER();
13214
Anurag Chouhan6d760662016-02-20 16:05:43 +053013215 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013216 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013217 return -EINVAL;
13218 }
13219
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013220 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013221 TRACE_CODE_HDD_CFG80211_DEL_STA,
13222 pAdapter->sessionId, pAdapter->device_mode));
13223
13224 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13225 status = wlan_hdd_validate_context(pHddCtx);
13226
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013227 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013228 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013229
13230 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13231
Krunal Sonib4326f22016-03-10 13:05:51 -080013232 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13233 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013234
13235 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13236 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013237 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013238 return 0;
13239 }
13240
Anurag Chouhanc5548422016-02-24 18:33:27 +053013241 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013242 uint16_t i;
13243 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13244 if ((pAdapter->aStaInfo[i].isUsed) &&
13245 (!pAdapter->aStaInfo[i].
13246 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013247 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013248 mac,
13249 pAdapter->aStaInfo[i].
13250 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013251 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013252 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13253 hdd_ipa_wlan_evt(pAdapter,
13254 pAdapter->
13255 aStaInfo[i].
13256 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013257 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013258 mac);
13259 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013260 hdd_notice("Delete STA with MAC::"
13261 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013262 MAC_ADDR_ARRAY(mac));
13263
13264 if (pHddCtx->dev_dfs_cac_status ==
13265 DFS_CAC_IN_PROGRESS)
13266 goto fn_end;
13267
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013268 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013269 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013270 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013271 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013272 hdd_softap_sta_deauth(pAdapter,
13273 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013274 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013275 pAdapter->aStaInfo[i].
13276 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013277 qdf_status =
13278 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013279 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013280 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013281 if (!QDF_IS_STATUS_SUCCESS(
13282 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013283 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013284 }
13285 }
13286 }
13287 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013288 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013289 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013290 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013291 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013292 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013293 hdd_notice("Skip DEL STA as this is not used::"
13294 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013295 MAC_ADDR_ARRAY(mac));
13296 return -ENOENT;
13297 }
13298
13299 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13300 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013301 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013302 }
13303
13304 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13305 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013306 hdd_notice("Skip DEL STA as deauth is in progress::"
13307 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013308 MAC_ADDR_ARRAY(mac));
13309 return -ENOENT;
13310 }
13311
13312 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13313
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013314 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013315 MAC_ADDR_ARRAY(mac));
13316
13317 /* Case: SAP in ACS selected DFS ch and client connected
13318 * Now Radar detected. Then if random channel is another
13319 * DFS ch then new CAC is initiated and no TX allowed.
13320 * So do not send any mgmt frames as it will timeout
13321 * during CAC.
13322 */
13323
13324 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13325 goto fn_end;
13326
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013327 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013328 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13329 (pAdapter), pAdapter->sessionId,
13330 (uint8_t *)&pDelStaParams->peerMacAddr,
13331 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013332 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013333 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013334 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013335 pAdapter->aStaInfo[staId].isDeauthInProgress =
13336 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013337 hdd_notice("STA removal failed for ::"
13338 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013339 MAC_ADDR_ARRAY(mac));
13340 return -ENOENT;
13341 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013342 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013343 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013344 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013345 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013346 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013347 }
13348 }
13349 }
13350
13351fn_end:
13352 EXIT();
13353 return 0;
13354}
13355
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013356#if defined(USE_CFG80211_DEL_STA_V2)
13357/**
13358 * wlan_hdd_del_station() - delete station wrapper
13359 * @adapter: pointer to the hdd adapter
13360 *
13361 * Return: None
13362 */
13363void wlan_hdd_del_station(hdd_adapter_t *adapter)
13364{
13365 struct station_del_parameters del_sta;
13366 del_sta.mac = NULL;
13367 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13368 del_sta.reason_code = eCsrForcedDeauthSta;
13369
13370 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13371 &del_sta);
13372}
13373#else
13374void wlan_hdd_del_station(hdd_adapter_t *adapter)
13375{
13376 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13377}
13378#endif
13379
13380#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013381/**
13382 * wlan_hdd_cfg80211_del_station() - delete station v2
13383 * @wiphy: Pointer to wiphy
13384 * @param: Pointer to delete station parameter
13385 *
13386 * Return: 0 for success, non-zero for failure
13387 */
13388int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13389 struct net_device *dev,
13390 struct station_del_parameters *param)
13391#else
13392/**
13393 * wlan_hdd_cfg80211_del_station() - delete station
13394 * @wiphy: Pointer to wiphy
13395 * @mac: Pointer to station mac address
13396 *
13397 * Return: 0 for success, non-zero for failure
13398 */
13399#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13400int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13401 struct net_device *dev,
13402 const uint8_t *mac)
13403#else
13404int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13405 struct net_device *dev,
13406 uint8_t *mac)
13407#endif
13408#endif
13409{
13410 int ret;
13411 struct tagCsrDelStaParams delStaParams;
13412
13413 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013414#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013415 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013416 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013417 return -EINVAL;
13418 }
13419 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13420 param->subtype, &delStaParams);
13421#else
13422 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13423 (SIR_MAC_MGMT_DEAUTH >> 4),
13424 &delStaParams);
13425#endif
13426 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13427 cds_ssr_unprotect(__func__);
13428
13429 return ret;
13430}
13431
13432/**
13433 * __wlan_hdd_cfg80211_add_station() - add station
13434 * @wiphy: Pointer to wiphy
13435 * @mac: Pointer to station mac address
13436 * @pmksa: Pointer to add station parameter
13437 *
13438 * Return: 0 for success, non-zero for failure
13439 */
13440static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13441 struct net_device *dev,
13442 const uint8_t *mac,
13443 struct station_parameters *params)
13444{
13445 int status = -EPERM;
13446#ifdef FEATURE_WLAN_TDLS
13447 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13448 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13449 u32 mask, set;
13450
13451 ENTER();
13452
Anurag Chouhan6d760662016-02-20 16:05:43 +053013453 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013454 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013455 return -EINVAL;
13456 }
13457
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013458 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013459 TRACE_CODE_HDD_CFG80211_ADD_STA,
13460 pAdapter->sessionId, params->listen_interval));
13461
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013462 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013463 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013464
13465 mask = params->sta_flags_mask;
13466
13467 set = params->sta_flags_set;
13468
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013469 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013470 MAC_ADDR_ARRAY(mac));
13471
13472 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13473 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13474 status =
13475 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13476 }
13477 }
13478#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013479 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013480 return status;
13481}
13482
13483/**
13484 * wlan_hdd_cfg80211_add_station() - add station
13485 * @wiphy: Pointer to wiphy
13486 * @mac: Pointer to station mac address
13487 * @pmksa: Pointer to add station parameter
13488 *
13489 * Return: 0 for success, non-zero for failure
13490 */
13491#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13492static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13493 struct net_device *dev,
13494 const uint8_t *mac,
13495 struct station_parameters *params)
13496#else
13497static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13498 struct net_device *dev, uint8_t *mac,
13499 struct station_parameters *params)
13500#endif
13501{
13502 int ret;
13503
13504 cds_ssr_protect(__func__);
13505 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13506 cds_ssr_unprotect(__func__);
13507
13508 return ret;
13509}
13510
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013511/**
13512 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13513 * @wiphy: Pointer to wiphy
13514 * @dev: Pointer to network device
13515 * @pmksa: Pointer to set pmksa parameter
13516 *
13517 * Return: 0 for success, non-zero for failure
13518 */
13519static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13520 struct net_device *dev,
13521 struct cfg80211_pmksa *pmksa)
13522{
13523 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13524 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13525 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013526 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013527 int status;
13528 tPmkidCacheInfo pmk_id;
13529
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013530 ENTER();
13531
Anurag Chouhan6d760662016-02-20 16:05:43 +053013532 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013533 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013534 return -EINVAL;
13535 }
13536
13537 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013538 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013539 return -EINVAL;
13540 }
13541
13542 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013543 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013544 pmksa->bssid, pmksa->pmkid);
13545 return -EINVAL;
13546 }
13547
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013548 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013549 MAC_ADDR_ARRAY(pmksa->bssid));
13550
13551 status = wlan_hdd_validate_context(pHddCtx);
13552
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013553 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013554 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013555
13556 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13557
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013558 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13559 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013560
13561 /* Add to the PMKSA ID Cache in CSR */
13562 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13563 &pmk_id, 1, false);
13564
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013565 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013566 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
13567 pAdapter->sessionId, result));
13568
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013569 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013570 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013571}
13572
13573/**
13574 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13575 * @wiphy: Pointer to wiphy
13576 * @dev: Pointer to network device
13577 * @pmksa: Pointer to set pmksa parameter
13578 *
13579 * Return: 0 for success, non-zero for failure
13580 */
13581static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13582 struct net_device *dev,
13583 struct cfg80211_pmksa *pmksa)
13584{
13585 int ret;
13586
13587 cds_ssr_protect(__func__);
13588 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
13589 cds_ssr_unprotect(__func__);
13590
13591 return ret;
13592}
13593
13594/**
13595 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13596 * @wiphy: Pointer to wiphy
13597 * @dev: Pointer to network device
13598 * @pmksa: Pointer to pmksa parameter
13599 *
13600 * Return: 0 for success, non-zero for failure
13601 */
13602static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13603 struct net_device *dev,
13604 struct cfg80211_pmksa *pmksa)
13605{
13606 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13607 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13608 tHalHandle halHandle;
13609 int status = 0;
13610
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013611 ENTER();
13612
Anurag Chouhan6d760662016-02-20 16:05:43 +053013613 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013614 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013615 return -EINVAL;
13616 }
13617
13618 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013619 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013620 return -EINVAL;
13621 }
13622
13623 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013624 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013625 return -EINVAL;
13626 }
13627
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013628 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013629 MAC_ADDR_ARRAY(pmksa->bssid));
13630
13631 status = wlan_hdd_validate_context(pHddCtx);
13632
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013633 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013634 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013635
13636 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13637
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013638 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053013639 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
13640 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013641 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013642 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013643 sme_roam_del_pmkid_from_cache(halHandle,
13644 pAdapter->sessionId, pmksa->bssid,
13645 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013646 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013647 MAC_ADDR_ARRAY(pmksa->bssid));
13648 status = -EINVAL;
13649 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013650 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013651 return status;
13652}
13653
13654/**
13655 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13656 * @wiphy: Pointer to wiphy
13657 * @dev: Pointer to network device
13658 * @pmksa: Pointer to pmksa parameter
13659 *
13660 * Return: 0 for success, non-zero for failure
13661 */
13662static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13663 struct net_device *dev,
13664 struct cfg80211_pmksa *pmksa)
13665{
13666 int ret;
13667
13668 cds_ssr_protect(__func__);
13669 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
13670 cds_ssr_unprotect(__func__);
13671
13672 return ret;
13673
13674}
13675
13676/**
13677 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13678 * @wiphy: Pointer to wiphy
13679 * @dev: Pointer to network device
13680 *
13681 * Return: 0 for success, non-zero for failure
13682 */
13683static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13684 struct net_device *dev)
13685{
13686 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13687 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13688 tHalHandle halHandle;
13689 int status = 0;
13690
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013691 ENTER();
13692
Anurag Chouhan6d760662016-02-20 16:05:43 +053013693 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013694 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013695 return -EINVAL;
13696 }
13697
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013698 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013699
13700 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13701 status = wlan_hdd_validate_context(pHddCtx);
13702
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013703 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013704 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013705
13706 /* Retrieve halHandle */
13707 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13708
13709 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013710 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013711 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
13712 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013713 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013714 status = -EINVAL;
13715 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013716 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013717 return status;
13718}
13719
13720/**
13721 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13722 * @wiphy: Pointer to wiphy
13723 * @dev: Pointer to network device
13724 *
13725 * Return: 0 for success, non-zero for failure
13726 */
13727static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13728 struct net_device *dev)
13729{
13730 int ret;
13731
13732 cds_ssr_protect(__func__);
13733 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
13734 cds_ssr_unprotect(__func__);
13735
13736 return ret;
13737}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013738
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080013739#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013740/**
13741 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13742 * @wiphy: Pointer to wiphy
13743 * @dev: Pointer to network device
13744 * @ftie: Pointer to fast transition ie parameter
13745 *
13746 * Return: 0 for success, non-zero for failure
13747 */
13748static int
13749__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13750 struct net_device *dev,
13751 struct cfg80211_update_ft_ies_params *ftie)
13752{
13753 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
13754 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13755 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13756 int status;
13757
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013758 ENTER();
13759
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013760 status = wlan_hdd_validate_context(hdd_ctx);
13761 if (status)
13762 return status;
13763
Anurag Chouhan6d760662016-02-20 16:05:43 +053013764 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013765 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013766 return -EINVAL;
13767 }
13768
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013769 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013770 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
13771 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
13772 /* Added for debug on reception of Re-assoc Req. */
13773 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013774 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013775 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013776 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013777 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013778 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013779 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013780
13781 /* Pass the received FT IEs to SME */
13782 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
13783 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013784 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013785 return 0;
13786}
13787
13788/**
13789 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13790 * @wiphy: Pointer to wiphy
13791 * @dev: Pointer to network device
13792 * @ftie: Pointer to fast transition ie parameter
13793 *
13794 * Return: 0 for success, non-zero for failure
13795 */
13796static int
13797wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13798 struct net_device *dev,
13799 struct cfg80211_update_ft_ies_params *ftie)
13800{
13801 int ret;
13802
13803 cds_ssr_protect(__func__);
13804 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
13805 cds_ssr_unprotect(__func__);
13806
13807 return ret;
13808}
13809#endif
13810
13811#ifdef WLAN_FEATURE_GTK_OFFLOAD
13812/**
13813 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
13814 * @callbackContext: Callback context
13815 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
13816 *
13817 * Callback rountine called upon receiving response for get offload info
13818 *
13819 * Return: none
13820 */
13821void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
13822 tpSirGtkOffloadGetInfoRspParams
13823 pGtkOffloadGetInfoRsp)
13824{
13825 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
13826 uint8_t tempReplayCounter[8];
13827 hdd_station_ctx_t *pHddStaCtx;
13828
13829 ENTER();
13830
13831 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013832 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013833 return;
13834 }
13835
13836 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013837 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013838 return;
13839 }
13840
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013841 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013842 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013843 return;
13844 }
13845
13846 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13847 /* Update replay counter */
13848 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
13849 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13850
13851 {
13852 /* changing from little to big endian since supplicant
13853 * works on big endian format
13854 */
13855 int i;
13856 uint8_t *p =
13857 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13858
13859 for (i = 0; i < 8; i++) {
13860 tempReplayCounter[7 - i] = (uint8_t) p[i];
13861 }
13862 }
13863
13864 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080013865 cfg80211_gtk_rekey_notify(pAdapter->dev,
13866 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013867 tempReplayCounter, GFP_KERNEL);
13868}
13869
13870/**
13871 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
13872 * @wiphy: Pointer to wiphy
13873 * @dev: Pointer to network device
13874 * @data: Pointer to rekey data
13875 *
13876 * This function is used to offload GTK rekeying job to the firmware.
13877 *
13878 * Return: 0 for success, non-zero for failure
13879 */
13880int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
13881 struct net_device *dev,
13882 struct cfg80211_gtk_rekey_data *data)
13883{
13884 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13885 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13886 hdd_station_ctx_t *pHddStaCtx;
13887 tHalHandle hHal;
13888 int result;
13889 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013890 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013891
13892 ENTER();
13893
Anurag Chouhan6d760662016-02-20 16:05:43 +053013894 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013895 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013896 return -EINVAL;
13897 }
13898
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013899 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013900 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
13901 pAdapter->sessionId, pAdapter->device_mode));
13902
13903 result = wlan_hdd_validate_context(pHddCtx);
13904
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013905 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013906 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013907
13908 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13909 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13910 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013911 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013912 return -EAGAIN;
13913 }
13914
13915 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
13916 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
13917 NL80211_KCK_LEN);
13918 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
13919 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053013920 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080013921 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013922 {
13923 /* changing from big to little endian since driver
13924 * works on little endian format
13925 */
13926 uint8_t *p =
13927 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
13928 ullKeyReplayCounter;
13929 int i;
13930
13931 for (i = 0; i < 8; i++) {
13932 p[7 - i] = data->replay_ctr[i];
13933 }
13934 }
13935
13936 if (true == pHddCtx->hdd_wlan_suspended) {
13937 /* if wlan is suspended, enable GTK offload directly from here */
13938 memcpy(&hddGtkOffloadReqParams,
13939 &pHddStaCtx->gtkOffloadReqParams,
13940 sizeof(tSirGtkOffloadParams));
13941 status =
13942 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
13943 pAdapter->sessionId);
13944
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013945 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013946 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013947 status);
13948 return -EINVAL;
13949 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013950 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013951 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013952 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013953 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013954 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013955 return result;
13956}
13957
13958/**
13959 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
13960 * @wiphy: Pointer to wiphy
13961 * @dev: Pointer to network device
13962 * @data: Pointer to rekey data
13963 *
13964 * This function is used to offload GTK rekeying job to the firmware.
13965 *
13966 * Return: 0 for success, non-zero for failure
13967 */
13968int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
13969 struct net_device *dev,
13970 struct cfg80211_gtk_rekey_data *data)
13971{
13972 int ret;
13973
13974 cds_ssr_protect(__func__);
13975 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
13976 cds_ssr_unprotect(__func__);
13977
13978 return ret;
13979}
13980#endif /*WLAN_FEATURE_GTK_OFFLOAD */
13981
13982/**
13983 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
13984 * @wiphy: Pointer to wiphy
13985 * @dev: Pointer to network device
13986 * @param: Pointer to access control parameter
13987 *
13988 * Return: 0 for success, non-zero for failure
13989 */
13990static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
13991 struct net_device *dev,
13992 const struct cfg80211_acl_data *params)
13993{
13994 int i;
13995 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13996 hdd_hostapd_state_t *pHostapdState;
13997 tsap_Config_t *pConfig;
13998 v_CONTEXT_t p_cds_context = NULL;
13999 hdd_context_t *pHddCtx;
14000 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014001 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014002
14003 ENTER();
14004
Anurag Chouhan6d760662016-02-20 16:05:43 +053014005 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014006 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014007 return -EINVAL;
14008 }
14009
14010 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014011 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014012 return -EINVAL;
14013 }
14014
14015 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14016 status = wlan_hdd_validate_context(pHddCtx);
14017
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014018 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014019 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014020
14021 p_cds_context = pHddCtx->pcds_context;
14022 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14023
14024 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014025 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014026 return -EINVAL;
14027 }
14028
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014029 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014030 params->n_acl_entries);
14031
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014032 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014033 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14034 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014035 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014036 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14037
14038 /* default value */
14039 pConfig->num_accept_mac = 0;
14040 pConfig->num_deny_mac = 0;
14041
14042 /**
14043 * access control policy
14044 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14045 * listed in hostapd.deny file.
14046 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14047 * listed in hostapd.accept file.
14048 */
14049 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14050 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14051 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14052 params->acl_policy) {
14053 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14054 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014055 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014056 params->acl_policy);
14057 return -ENOTSUPP;
14058 }
14059
14060 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14061 pConfig->num_accept_mac = params->n_acl_entries;
14062 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014063 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14064 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014065 MAC_ADDR_ARRAY(
14066 params->mac_addrs[i].addr));
14067
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014068 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014069 params->mac_addrs[i].addr,
14070 sizeof(qcmacaddr));
14071 }
14072 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14073 pConfig->num_deny_mac = params->n_acl_entries;
14074 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014075 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14076 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014077 MAC_ADDR_ARRAY(
14078 params->mac_addrs[i].addr));
14079
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014080 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014081 params->mac_addrs[i].addr,
14082 sizeof(qcmacaddr));
14083 }
14084 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014085 qdf_status = wlansap_set_mac_acl(
14086 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014087 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014088 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014089 return -EINVAL;
14090 }
14091 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014092 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014093 hdd_device_mode_to_string(pAdapter->device_mode),
14094 pAdapter->device_mode);
14095 return -EINVAL;
14096 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014097 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014098 return 0;
14099}
14100
14101/**
14102 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14103 * __wlan_hdd_cfg80211_set_mac_acl
14104 * @wiphy: pointer to wiphy structure
14105 * @dev: pointer to net_device
14106 * @params: pointer to cfg80211_acl_data
14107 *
14108 * Return; 0 on success, error number otherwise
14109 */
14110static int
14111wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14112 struct net_device *dev,
14113 const struct cfg80211_acl_data *params)
14114{
14115 int ret;
14116
14117 cds_ssr_protect(__func__);
14118 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14119 cds_ssr_unprotect(__func__);
14120
14121 return ret;
14122}
14123
14124#ifdef WLAN_NL80211_TESTMODE
14125#ifdef FEATURE_WLAN_LPHB
14126/**
14127 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14128 * @pHddCtx: Pointer to hdd context
14129 * @lphbInd: Pointer to low power heart beat indication parameter
14130 *
14131 * Return: none
14132 */
14133void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx, tSirLPHBInd *lphbInd)
14134{
14135 struct sk_buff *skb;
14136
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014137 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014138
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014139 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014140 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014141
14142 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014143 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014144 return;
14145 }
14146
14147 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14148 wiphy, sizeof(tSirLPHBInd),
14149 GFP_ATOMIC);
14150 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014151 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014152 return;
14153 }
14154
14155 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014156 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014157 goto nla_put_failure;
14158 }
14159 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014160 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014161 goto nla_put_failure;
14162 }
14163 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014164 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014165 goto nla_put_failure;
14166 }
14167 cfg80211_testmode_event(skb, GFP_ATOMIC);
14168 return;
14169
14170nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014171 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014172 kfree_skb(skb);
14173
14174 return;
14175}
14176#endif /* FEATURE_WLAN_LPHB */
14177
14178/**
14179 * __wlan_hdd_cfg80211_testmode() - test mode
14180 * @wiphy: Pointer to wiphy
14181 * @data: Data pointer
14182 * @len: Data length
14183 *
14184 * Return: 0 for success, non-zero for failure
14185 */
14186static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14187 void *data, int len)
14188{
14189 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14190 int err;
14191 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14192
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014193 ENTER();
14194
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014195 err = wlan_hdd_validate_context(pHddCtx);
14196 if (err)
14197 return err;
14198
14199 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14200 len, wlan_hdd_tm_policy);
14201 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014202 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014203 return err;
14204 }
14205
14206 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014207 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014208 return -EINVAL;
14209 }
14210
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014211 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014212 TRACE_CODE_HDD_CFG80211_TESTMODE,
14213 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014214 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14215#ifdef FEATURE_WLAN_LPHB
14216 /* Low Power Heartbeat configuration request */
14217 case WLAN_HDD_TM_CMD_WLAN_HB:
14218 {
14219 int buf_len;
14220 void *buf;
14221 tSirLPHBReq *hb_params = NULL;
14222 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014223 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014224
14225 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014226 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014227 return -EINVAL;
14228 }
14229
14230 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14231 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14232
14233 hb_params_temp = (tSirLPHBReq *) buf;
14234 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14235 && (hb_params_temp->params.lphbTcpParamReq.
14236 timePeriodSec == 0))
14237 return -EINVAL;
14238
14239 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014240 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014241 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014242 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014243 return -ENOMEM;
14244 }
14245
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014246 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014247 smeStatus =
14248 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14249 hb_params,
14250 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014251 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014252 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014253 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014254 }
14255 return 0;
14256 }
14257#endif /* FEATURE_WLAN_LPHB */
14258
14259#if defined(QCA_WIFI_FTM)
14260 case WLAN_HDD_TM_CMD_WLAN_FTM:
14261 {
14262 int buf_len;
14263 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014264 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014265 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014266 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014267 return -EINVAL;
14268 }
14269
14270 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14271 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14272
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014273 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014274
14275 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14276
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014277 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014278 err = -EBUSY;
14279 break;
14280 }
14281#endif
14282
14283 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014284 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014285 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14286 return -EOPNOTSUPP;
14287 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014288 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014289 return err;
14290}
14291
14292/**
14293 * wlan_hdd_cfg80211_testmode() - test mode
14294 * @wiphy: Pointer to wiphy
14295 * @dev: Pointer to network device
14296 * @data: Data pointer
14297 * @len: Data length
14298 *
14299 * Return: 0 for success, non-zero for failure
14300 */
14301static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14302#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14303 struct wireless_dev *wdev,
14304#endif
14305 void *data, int len)
14306{
14307 int ret;
14308
14309 cds_ssr_protect(__func__);
14310 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14311 cds_ssr_unprotect(__func__);
14312
14313 return ret;
14314}
14315
14316#if defined(QCA_WIFI_FTM)
14317/**
14318 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14319 * @buf: Pointer to buffer
14320 * @buf_len: Buffer length
14321 *
14322 * Return: none
14323 */
14324void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14325{
14326 struct sk_buff *skb;
14327 hdd_context_t *hdd_ctx;
14328
14329 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014330 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014331 return;
14332 }
14333
Anurag Chouhan6d760662016-02-20 16:05:43 +053014334 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014335 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014336 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014337 return;
14338 }
14339
14340 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14341 buf_len, GFP_KERNEL);
14342 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014343 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014344 return;
14345 }
14346
14347 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14348 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14349 goto nla_put_failure;
14350
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014351 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014352
14353 cfg80211_testmode_event(skb, GFP_KERNEL);
14354 return;
14355
14356nla_put_failure:
14357 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014358 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014359}
14360#endif
14361#endif /* CONFIG_NL80211_TESTMODE */
14362
14363#ifdef QCA_HT_2040_COEX
14364/**
14365 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14366 * @wiphy: Pointer to wiphy
14367 * @dev: Pointer to network device
14368 * @chandef: Pointer to channel definition parameter
14369 *
14370 * Return: 0 for success, non-zero for failure
14371 */
14372static int
14373__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14374 struct net_device *dev,
14375 struct cfg80211_chan_def *chandef)
14376{
14377 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14378 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014379 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014380 tSmeConfigParams sme_config;
14381 bool cbModeChange;
14382
Anurag Chouhan6d760662016-02-20 16:05:43 +053014383 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014384 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014385 return -EINVAL;
14386 }
14387
14388 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14389 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014390 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014391 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014392
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014393 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014394 sme_get_config_param(pHddCtx->hHal, &sme_config);
14395 switch (chandef->width) {
14396 case NL80211_CHAN_WIDTH_20:
14397 if (sme_config.csrConfig.channelBondingMode24GHz !=
14398 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14399 sme_config.csrConfig.channelBondingMode24GHz =
14400 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14401 sme_update_config(pHddCtx->hHal, &sme_config);
14402 cbModeChange = true;
14403 }
14404 break;
14405
14406 case NL80211_CHAN_WIDTH_40:
14407 if (sme_config.csrConfig.channelBondingMode24GHz ==
14408 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14409 if (NL80211_CHAN_HT40MINUS ==
14410 cfg80211_get_chandef_type(chandef))
14411 sme_config.csrConfig.channelBondingMode24GHz =
14412 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14413 else
14414 sme_config.csrConfig.channelBondingMode24GHz =
14415 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14416 sme_update_config(pHddCtx->hHal, &sme_config);
14417 cbModeChange = true;
14418 }
14419 break;
14420
14421 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014422 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014423 return -EINVAL;
14424 }
14425
14426 if (!cbModeChange)
14427 return 0;
14428
Krunal Sonib4326f22016-03-10 13:05:51 -080014429 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014430 return 0;
14431
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014432 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014433 sme_config.csrConfig.channelBondingMode24GHz);
14434
14435 /* Change SAP ht2040 mode */
14436 status = hdd_set_sap_ht2040_mode(pAdapter,
14437 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014438 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014439 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014440 return -EINVAL;
14441 }
14442
14443 return 0;
14444}
14445
14446/**
14447 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14448 * @wiphy: Pointer to wiphy
14449 * @dev: Pointer to network device
14450 * @chandef: Pointer to channel definition parameter
14451 *
14452 * Return: 0 for success, non-zero for failure
14453 */
14454static int
14455wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14456 struct net_device *dev,
14457 struct cfg80211_chan_def *chandef)
14458{
14459 int ret;
14460
14461 cds_ssr_protect(__func__);
14462 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14463 cds_ssr_unprotect(__func__);
14464
14465 return ret;
14466}
14467#endif
14468
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014469#ifdef CHANNEL_SWITCH_SUPPORTED
14470/**
14471 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14472 * channel in SAP/GO
14473 * @wiphy: wiphy pointer
14474 * @dev: dev pointer.
14475 * @csa_params: Change channel params
14476 *
14477 * This function is called to switch channel in SAP/GO
14478 *
14479 * Return: 0 if success else return non zero
14480 */
14481static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14482 struct net_device *dev,
14483 struct cfg80211_csa_settings *csa_params)
14484{
14485 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14486 hdd_context_t *hdd_ctx;
14487 uint8_t channel;
14488 uint16_t freq;
14489 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014490 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014491
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014492 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014493 csa_params->chandef.chan->center_freq);
14494
14495 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14496 ret = wlan_hdd_validate_context(hdd_ctx);
14497
14498 if (0 != ret)
14499 return ret;
14500
Krunal Sonib4326f22016-03-10 13:05:51 -080014501 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14502 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014503 return -ENOTSUPP;
14504
14505 freq = csa_params->chandef.chan->center_freq;
14506 channel = cds_freq_to_chan(freq);
14507
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014508 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14509
14510 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014511 return ret;
14512}
14513
14514/**
14515 * wlan_hdd_cfg80211_channel_switch()- function to switch
14516 * channel in SAP/GO
14517 * @wiphy: wiphy pointer
14518 * @dev: dev pointer.
14519 * @csa_params: Change channel params
14520 *
14521 * This function is called to switch channel in SAP/GO
14522 *
14523 * Return: 0 if success else return non zero
14524 */
14525static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14526 struct net_device *dev,
14527 struct cfg80211_csa_settings *csa_params)
14528{
14529 int ret;
14530
14531 cds_ssr_protect(__func__);
14532 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14533 cds_ssr_unprotect(__func__);
14534 return ret;
14535}
14536#endif
14537
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014538/**
14539 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14540 * translation from NL to policy manager type
14541 * @type: Generic connection mode type defined in NL
14542 *
14543 *
14544 * This function provides the type translation
14545 *
14546 * Return: cds_con_mode enum
14547 */
14548enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
14549 enum nl80211_iftype type)
14550{
14551 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
14552 switch (type) {
14553 case NL80211_IFTYPE_STATION:
14554 mode = CDS_STA_MODE;
14555 break;
14556 case NL80211_IFTYPE_P2P_CLIENT:
14557 mode = CDS_P2P_CLIENT_MODE;
14558 break;
14559 case NL80211_IFTYPE_P2P_GO:
14560 mode = CDS_P2P_GO_MODE;
14561 break;
14562 case NL80211_IFTYPE_AP:
14563 mode = CDS_SAP_MODE;
14564 break;
14565 case NL80211_IFTYPE_ADHOC:
14566 mode = CDS_IBSS_MODE;
14567 break;
14568 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014569 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014570 type);
14571 }
14572 return mode;
14573}
14574
14575/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014576 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14577 * @wiphy: Handle to struct wiphy to get handle to module context.
14578 * @chandef: Contains information about the capture channel to be set.
14579 *
14580 * This interface is called if and only if monitor mode interface alone is
14581 * active.
14582 *
14583 * Return: 0 success or error code on failure.
14584 */
14585static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14586 struct cfg80211_chan_def *chandef)
14587{
14588 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14589 hdd_adapter_t *adapter;
14590 hdd_station_ctx_t *sta_ctx;
14591 struct hdd_mon_set_ch_info *ch_info;
14592 QDF_STATUS status;
14593 tHalHandle hal_hdl;
14594 struct qdf_mac_addr bssid;
14595 tCsrRoamProfile roam_profile;
14596 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014597 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014598 int ret;
14599 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
14600
14601 ENTER();
14602
14603 ret = wlan_hdd_validate_context(hdd_ctx);
14604 if (ret)
14605 return ret;
14606
14607 hal_hdl = hdd_ctx->hHal;
14608
14609 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
14610 if (!adapter)
14611 return -EIO;
14612
14613 hdd_info("%s: set monitor mode Channel %d and freq %d",
14614 adapter->dev->name, chan_num, chandef->chan->center_freq);
14615
14616 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14617 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014618 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
14619 roam_profile.ChannelInfo.numOfChannels = 1;
14620 roam_profile.phyMode = ch_info->phy_mode;
14621 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014622 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014623
14624 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
14625 QDF_MAC_ADDR_SIZE);
14626
14627 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014628 /*
14629 * CDS api expects secondary channel for calculating
14630 * the channel params
14631 */
14632 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
14633 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
14634 if (chan_num >= 1 && chan_num <= 5)
14635 sec_ch = chan_num + 4;
14636 else if (chan_num >= 6 && chan_num <= 13)
14637 sec_ch = chan_num - 4;
14638 }
14639 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014640 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
14641 &roam_profile);
14642 if (status) {
14643 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
14644 status);
14645 ret = qdf_status_to_os_return(status);
14646 return ret;
14647 }
14648 EXIT();
14649 return 0;
14650}
14651
14652/**
14653 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14654 * @wiphy: Handle to struct wiphy to get handle to module context.
14655 * @chandef: Contains information about the capture channel to be set.
14656 *
14657 * This interface is called if and only if monitor mode interface alone is
14658 * active.
14659 *
14660 * Return: 0 success or error code on failure.
14661 */
14662static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14663 struct cfg80211_chan_def *chandef)
14664{
14665 int ret;
14666
14667 cds_ssr_protect(__func__);
14668 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
14669 cds_ssr_unprotect(__func__);
14670 return ret;
14671}
14672
14673/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014674 * struct cfg80211_ops - cfg80211_ops
14675 *
14676 * @add_virtual_intf: Add virtual interface
14677 * @del_virtual_intf: Delete virtual interface
14678 * @change_virtual_intf: Change virtual interface
14679 * @change_station: Change station
14680 * @add_beacon: Add beacon in sap mode
14681 * @del_beacon: Delete beacon in sap mode
14682 * @set_beacon: Set beacon in sap mode
14683 * @start_ap: Start ap
14684 * @change_beacon: Change beacon
14685 * @stop_ap: Stop ap
14686 * @change_bss: Change bss
14687 * @add_key: Add key
14688 * @get_key: Get key
14689 * @del_key: Delete key
14690 * @set_default_key: Set default key
14691 * @set_channel: Set channel
14692 * @scan: Scan
14693 * @connect: Connect
14694 * @disconnect: Disconnect
14695 * @join_ibss = Join ibss
14696 * @leave_ibss = Leave ibss
14697 * @set_wiphy_params = Set wiphy params
14698 * @set_tx_power = Set tx power
14699 * @get_tx_power = get tx power
14700 * @remain_on_channel = Remain on channel
14701 * @cancel_remain_on_channel = Cancel remain on channel
14702 * @mgmt_tx = Tx management frame
14703 * @mgmt_tx_cancel_wait = Cancel management tx wait
14704 * @set_default_mgmt_key = Set default management key
14705 * @set_txq_params = Set tx queue parameters
14706 * @get_station = Get station
14707 * @set_power_mgmt = Set power management
14708 * @del_station = Delete station
14709 * @add_station = Add station
14710 * @set_pmksa = Set pmksa
14711 * @del_pmksa = Delete pmksa
14712 * @flush_pmksa = Flush pmksa
14713 * @update_ft_ies = Update FT IEs
14714 * @tdls_mgmt = Tdls management
14715 * @tdls_oper = Tdls operation
14716 * @set_rekey_data = Set rekey data
14717 * @sched_scan_start = Scheduled scan start
14718 * @sched_scan_stop = Scheduled scan stop
14719 * @resume = Resume wlan
14720 * @suspend = Suspend wlan
14721 * @set_mac_acl = Set mac acl
14722 * @testmode_cmd = Test mode command
14723 * @set_ap_chanwidth = Set AP channel bandwidth
14724 * @dump_survey = Dump survey
14725 * @key_mgmt_set_pmk = Set pmk key management
14726 */
14727static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
14728 .add_virtual_intf = wlan_hdd_add_virtual_intf,
14729 .del_virtual_intf = wlan_hdd_del_virtual_intf,
14730 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
14731 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014732 .start_ap = wlan_hdd_cfg80211_start_ap,
14733 .change_beacon = wlan_hdd_cfg80211_change_beacon,
14734 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014735 .change_bss = wlan_hdd_cfg80211_change_bss,
14736 .add_key = wlan_hdd_cfg80211_add_key,
14737 .get_key = wlan_hdd_cfg80211_get_key,
14738 .del_key = wlan_hdd_cfg80211_del_key,
14739 .set_default_key = wlan_hdd_cfg80211_set_default_key,
14740 .scan = wlan_hdd_cfg80211_scan,
14741 .connect = wlan_hdd_cfg80211_connect,
14742 .disconnect = wlan_hdd_cfg80211_disconnect,
14743 .join_ibss = wlan_hdd_cfg80211_join_ibss,
14744 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
14745 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
14746 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
14747 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
14748 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
14749 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
14750 .mgmt_tx = wlan_hdd_mgmt_tx,
14751 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
14752 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
14753 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053014754 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014755 .get_station = wlan_hdd_cfg80211_get_station,
14756 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
14757 .del_station = wlan_hdd_cfg80211_del_station,
14758 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014759 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
14760 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
14761 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014762#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014763 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
14764#endif
14765#ifdef FEATURE_WLAN_TDLS
14766 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
14767 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
14768#endif
14769#ifdef WLAN_FEATURE_GTK_OFFLOAD
14770 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
14771#endif /* WLAN_FEATURE_GTK_OFFLOAD */
14772#ifdef FEATURE_WLAN_SCAN_PNO
14773 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
14774 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
14775#endif /*FEATURE_WLAN_SCAN_PNO */
14776 .resume = wlan_hdd_cfg80211_resume_wlan,
14777 .suspend = wlan_hdd_cfg80211_suspend_wlan,
14778 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
14779#ifdef WLAN_NL80211_TESTMODE
14780 .testmode_cmd = wlan_hdd_cfg80211_testmode,
14781#endif
14782#ifdef QCA_HT_2040_COEX
14783 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
14784#endif
14785 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014786#ifdef CHANNEL_SWITCH_SUPPORTED
14787 .channel_switch = wlan_hdd_cfg80211_channel_switch,
14788#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014789 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053014790#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
14791 defined(CFG80211_ABORT_SCAN)
14792 .abort_scan = wlan_hdd_cfg80211_abort_scan,
14793#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014794};