blob: a0874fd14656e134aed3ba0a27aafa9ea5cd5c0e [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
Jeff Johnson9c50e782016-06-29 15:28:56 -070035/* denote that this file does not allow legacy hddLog */
36#define HDD_DISALLOW_LEGACY_HDDLOG 1
37
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080038#include <linux/version.h>
39#include <linux/module.h>
40#include <linux/kernel.h>
41#include <linux/init.h>
42#include <linux/etherdevice.h>
43#include <linux/wireless.h>
44#include <wlan_hdd_includes.h>
45#include <net/arp.h>
46#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053047#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048#include <wlan_hdd_wowl.h>
49#include <ani_global.h>
50#include "sir_params.h"
51#include "dot11f.h"
52#include "wlan_hdd_assoc.h"
53#include "wlan_hdd_wext.h"
54#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070055#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080056#include "wlan_hdd_p2p.h"
57#include "wlan_hdd_cfg80211.h"
58#include "wlan_hdd_hostapd.h"
59#include "wlan_hdd_softap_tx_rx.h"
60#include "wlan_hdd_main.h"
61#include "wlan_hdd_power.h"
62#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053063#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053064#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080065#include "cds_utils.h"
66#include "cds_sched.h"
67#include "wlan_hdd_scan.h"
68#include <qc_sap_ioctl.h>
69#include "wlan_hdd_tdls.h"
70#include "wlan_hdd_wmm.h"
71#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053072#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080073#include "wlan_hdd_misc.h"
74#include "wlan_hdd_nan.h"
75#include <wlan_hdd_ipa.h>
76#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053077#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053078#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053079#include "pld_common.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053080
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081
82#ifdef FEATURE_WLAN_EXTSCAN
83#include "wlan_hdd_ext_scan.h"
84#endif
85
86#ifdef WLAN_FEATURE_LINK_LAYER_STATS
87#include "wlan_hdd_stats.h"
88#endif
89#include "cds_concurrency.h"
90#include "qwlan_version.h"
91#include "wlan_hdd_memdump.h"
92
93#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070094#include "wlan_hdd_tsf.h"
Manikandan Mohanb6315dd2016-05-10 16:16:36 -070095#include "ol_txrx.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080096
Ravi Joshideb5a8d2015-11-09 19:11:43 -080097#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053098#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070099#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700100#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530101#include "wlan_hdd_disa.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800102
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800103#define g_mode_rates_size (12)
104#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
106 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
107
108/*
109 * Android CTS verifier needs atleast this much wait time (in msec)
110 */
111#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
112
113/*
114 * Refer @tCfgProtection structure for definition of the bit map.
115 * below value is obtained by setting the following bit-fields.
116 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
117 */
118#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
119
120#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700121 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800122 .center_freq = (freq), \
123 .hw_value = (chan), \
124 .flags = (flag), \
125 .max_antenna_gain = 0, \
126 .max_power = 30, \
127}
128
129#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700130 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800131 .center_freq = (freq), \
132 .hw_value = (chan), \
133 .flags = (flag), \
134 .max_antenna_gain = 0, \
135 .max_power = 30, \
136}
137
138#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
139 { \
140 .bitrate = rate, \
141 .hw_value = rate_id, \
142 .flags = flag, \
143 }
144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800145#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
146#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147
148#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149
Agrawal Ashish65634612016-08-18 13:24:32 +0530150#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
151 mode <= DFS_MODE_DEPRIORITIZE))
152#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
153 || (channel >= 36 && channel <= 184))
154
Peng Xu4d67c8f2015-10-16 16:02:26 -0700155#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530156#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700157
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158static const u32 hdd_cipher_suites[] = {
159 WLAN_CIPHER_SUITE_WEP40,
160 WLAN_CIPHER_SUITE_WEP104,
161 WLAN_CIPHER_SUITE_TKIP,
162#ifdef FEATURE_WLAN_ESE
163#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
164#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
165 WLAN_CIPHER_SUITE_BTK,
166 WLAN_CIPHER_SUITE_KRK,
167 WLAN_CIPHER_SUITE_CCMP,
168#else
169 WLAN_CIPHER_SUITE_CCMP,
170#endif
171#ifdef FEATURE_WLAN_WAPI
172 WLAN_CIPHER_SUITE_SMS4,
173#endif
174#ifdef WLAN_FEATURE_11W
175 WLAN_CIPHER_SUITE_AES_CMAC,
176#endif
177};
178
Abhishek Singhf512bf32016-05-04 16:47:46 +0530179static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 HDD2GHZCHAN(2412, 1, 0),
181 HDD2GHZCHAN(2417, 2, 0),
182 HDD2GHZCHAN(2422, 3, 0),
183 HDD2GHZCHAN(2427, 4, 0),
184 HDD2GHZCHAN(2432, 5, 0),
185 HDD2GHZCHAN(2437, 6, 0),
186 HDD2GHZCHAN(2442, 7, 0),
187 HDD2GHZCHAN(2447, 8, 0),
188 HDD2GHZCHAN(2452, 9, 0),
189 HDD2GHZCHAN(2457, 10, 0),
190 HDD2GHZCHAN(2462, 11, 0),
191 HDD2GHZCHAN(2467, 12, 0),
192 HDD2GHZCHAN(2472, 13, 0),
193 HDD2GHZCHAN(2484, 14, 0),
194};
195
Abhishek Singhf512bf32016-05-04 16:47:46 +0530196static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800197 HDD5GHZCHAN(5180, 36, 0),
198 HDD5GHZCHAN(5200, 40, 0),
199 HDD5GHZCHAN(5220, 44, 0),
200 HDD5GHZCHAN(5240, 48, 0),
201 HDD5GHZCHAN(5260, 52, 0),
202 HDD5GHZCHAN(5280, 56, 0),
203 HDD5GHZCHAN(5300, 60, 0),
204 HDD5GHZCHAN(5320, 64, 0),
205 HDD5GHZCHAN(5500, 100, 0),
206 HDD5GHZCHAN(5520, 104, 0),
207 HDD5GHZCHAN(5540, 108, 0),
208 HDD5GHZCHAN(5560, 112, 0),
209 HDD5GHZCHAN(5580, 116, 0),
210 HDD5GHZCHAN(5600, 120, 0),
211 HDD5GHZCHAN(5620, 124, 0),
212 HDD5GHZCHAN(5640, 128, 0),
213 HDD5GHZCHAN(5660, 132, 0),
214 HDD5GHZCHAN(5680, 136, 0),
215 HDD5GHZCHAN(5700, 140, 0),
216 HDD5GHZCHAN(5720, 144, 0),
217 HDD5GHZCHAN(5745, 149, 0),
218 HDD5GHZCHAN(5765, 153, 0),
219 HDD5GHZCHAN(5785, 157, 0),
220 HDD5GHZCHAN(5805, 161, 0),
221 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222 HDD5GHZCHAN(5852, 170, 0),
223 HDD5GHZCHAN(5855, 171, 0),
224 HDD5GHZCHAN(5860, 172, 0),
225 HDD5GHZCHAN(5865, 173, 0),
226 HDD5GHZCHAN(5870, 174, 0),
227 HDD5GHZCHAN(5875, 175, 0),
228 HDD5GHZCHAN(5880, 176, 0),
229 HDD5GHZCHAN(5885, 177, 0),
230 HDD5GHZCHAN(5890, 178, 0),
231 HDD5GHZCHAN(5895, 179, 0),
232 HDD5GHZCHAN(5900, 180, 0),
233 HDD5GHZCHAN(5905, 181, 0),
234 HDD5GHZCHAN(5910, 182, 0),
235 HDD5GHZCHAN(5915, 183, 0),
236 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800237};
238
239static struct ieee80211_rate g_mode_rates[] = {
240 HDD_G_MODE_RATETAB(10, 0x1, 0),
241 HDD_G_MODE_RATETAB(20, 0x2, 0),
242 HDD_G_MODE_RATETAB(55, 0x4, 0),
243 HDD_G_MODE_RATETAB(110, 0x8, 0),
244 HDD_G_MODE_RATETAB(60, 0x10, 0),
245 HDD_G_MODE_RATETAB(90, 0x20, 0),
246 HDD_G_MODE_RATETAB(120, 0x40, 0),
247 HDD_G_MODE_RATETAB(180, 0x80, 0),
248 HDD_G_MODE_RATETAB(240, 0x100, 0),
249 HDD_G_MODE_RATETAB(360, 0x200, 0),
250 HDD_G_MODE_RATETAB(480, 0x400, 0),
251 HDD_G_MODE_RATETAB(540, 0x800, 0),
252};
253
254static struct ieee80211_rate a_mode_rates[] = {
255 HDD_G_MODE_RATETAB(60, 0x10, 0),
256 HDD_G_MODE_RATETAB(90, 0x20, 0),
257 HDD_G_MODE_RATETAB(120, 0x40, 0),
258 HDD_G_MODE_RATETAB(180, 0x80, 0),
259 HDD_G_MODE_RATETAB(240, 0x100, 0),
260 HDD_G_MODE_RATETAB(360, 0x200, 0),
261 HDD_G_MODE_RATETAB(480, 0x400, 0),
262 HDD_G_MODE_RATETAB(540, 0x800, 0),
263};
264
265static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530266 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800267 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700268 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800269 .bitrates = g_mode_rates,
270 .n_bitrates = g_mode_rates_size,
271 .ht_cap.ht_supported = 1,
272 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
273 | IEEE80211_HT_CAP_GRN_FLD
274 | IEEE80211_HT_CAP_DSSSCCK40
275 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
276 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
277 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
278 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
279 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
280 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
281 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
282};
283
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800284static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530285 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700287 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288 .bitrates = a_mode_rates,
289 .n_bitrates = a_mode_rates_size,
290 .ht_cap.ht_supported = 1,
291 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
292 | IEEE80211_HT_CAP_GRN_FLD
293 | IEEE80211_HT_CAP_DSSSCCK40
294 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
295 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
296 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
297 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
298 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
299 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
300 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
301 .vht_cap.vht_supported = 1,
302};
303
304/* This structure contain information what kind of frame are expected in
305 TX/RX direction for each kind of interface */
306static const struct ieee80211_txrx_stypes
307 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
308 [NL80211_IFTYPE_STATION] = {
309 .tx = 0xffff,
310 .rx = BIT(SIR_MAC_MGMT_ACTION) |
311 BIT(SIR_MAC_MGMT_PROBE_REQ),
312 },
313 [NL80211_IFTYPE_AP] = {
314 .tx = 0xffff,
315 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
316 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
317 BIT(SIR_MAC_MGMT_PROBE_REQ) |
318 BIT(SIR_MAC_MGMT_DISASSOC) |
319 BIT(SIR_MAC_MGMT_AUTH) |
320 BIT(SIR_MAC_MGMT_DEAUTH) |
321 BIT(SIR_MAC_MGMT_ACTION),
322 },
323 [NL80211_IFTYPE_ADHOC] = {
324 .tx = 0xffff,
325 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
326 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
327 BIT(SIR_MAC_MGMT_PROBE_REQ) |
328 BIT(SIR_MAC_MGMT_DISASSOC) |
329 BIT(SIR_MAC_MGMT_AUTH) |
330 BIT(SIR_MAC_MGMT_DEAUTH) |
331 BIT(SIR_MAC_MGMT_ACTION),
332 },
333 [NL80211_IFTYPE_P2P_CLIENT] = {
334 .tx = 0xffff,
335 .rx = BIT(SIR_MAC_MGMT_ACTION) |
336 BIT(SIR_MAC_MGMT_PROBE_REQ),
337 },
338 [NL80211_IFTYPE_P2P_GO] = {
339 /* This is also same as for SoftAP */
340 .tx = 0xffff,
341 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
342 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
343 BIT(SIR_MAC_MGMT_PROBE_REQ) |
344 BIT(SIR_MAC_MGMT_DISASSOC) |
345 BIT(SIR_MAC_MGMT_AUTH) |
346 BIT(SIR_MAC_MGMT_DEAUTH) |
347 BIT(SIR_MAC_MGMT_ACTION),
348 },
349};
350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351/* Interface limits and combinations registered by the driver */
352
353/* STA ( + STA ) combination */
354static const struct ieee80211_iface_limit
355 wlan_hdd_sta_iface_limit[] = {
356 {
357 .max = 3, /* p2p0 is a STA as well */
358 .types = BIT(NL80211_IFTYPE_STATION),
359 },
360};
361
362/* ADHOC (IBSS) limit */
363static const struct ieee80211_iface_limit
364 wlan_hdd_adhoc_iface_limit[] = {
365 {
366 .max = 1,
367 .types = BIT(NL80211_IFTYPE_STATION),
368 },
369 {
370 .max = 1,
371 .types = BIT(NL80211_IFTYPE_ADHOC),
372 },
373};
374
375/* AP ( + AP ) combination */
376static const struct ieee80211_iface_limit
377 wlan_hdd_ap_iface_limit[] = {
378 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530379 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800380 .types = BIT(NL80211_IFTYPE_AP),
381 },
382};
383
384/* P2P limit */
385static const struct ieee80211_iface_limit
386 wlan_hdd_p2p_iface_limit[] = {
387 {
388 .max = 1,
389 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
390 },
391 {
392 .max = 1,
393 .types = BIT(NL80211_IFTYPE_P2P_GO),
394 },
395};
396
397static const struct ieee80211_iface_limit
398 wlan_hdd_sta_ap_iface_limit[] = {
399 {
400 /* We need 1 extra STA interface for OBSS scan when SAP starts
401 * with HT40 in STA+SAP concurrency mode
402 */
403 .max = (1 + SAP_MAX_OBSS_STA_CNT),
404 .types = BIT(NL80211_IFTYPE_STATION),
405 },
406 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530407 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408 .types = BIT(NL80211_IFTYPE_AP),
409 },
410};
411
412/* STA + P2P combination */
413static const struct ieee80211_iface_limit
414 wlan_hdd_sta_p2p_iface_limit[] = {
415 {
416 /* One reserved for dedicated P2PDEV usage */
417 .max = 2,
418 .types = BIT(NL80211_IFTYPE_STATION)
419 },
420 {
421 /* Support for two identical (GO + GO or CLI + CLI)
422 * or dissimilar (GO + CLI) P2P interfaces
423 */
424 .max = 2,
425 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
426 },
427};
428
429/* STA + AP + P2PGO combination */
430static const struct ieee80211_iface_limit
431wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
432 /* Support for AP+P2PGO interfaces */
433 {
434 .max = 2,
435 .types = BIT(NL80211_IFTYPE_STATION)
436 },
437 {
438 .max = 1,
439 .types = BIT(NL80211_IFTYPE_P2P_GO)
440 },
441 {
442 .max = 1,
443 .types = BIT(NL80211_IFTYPE_AP)
444 }
445};
446
447/* SAP + P2P combination */
448static const struct ieee80211_iface_limit
449wlan_hdd_sap_p2p_iface_limit[] = {
450 {
451 /* 1 dedicated for p2p0 which is a STA type */
452 .max = 1,
453 .types = BIT(NL80211_IFTYPE_STATION)
454 },
455 {
456 /* The p2p interface in SAP+P2P can be GO/CLI.
457 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
458 */
459 .max = 1,
460 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
461 },
462 {
463 /* SAP+GO to support only one SAP interface */
464 .max = 1,
465 .types = BIT(NL80211_IFTYPE_AP)
466 }
467};
468
469/* P2P + P2P combination */
470static const struct ieee80211_iface_limit
471wlan_hdd_p2p_p2p_iface_limit[] = {
472 {
473 /* 1 dedicated for p2p0 which is a STA type */
474 .max = 1,
475 .types = BIT(NL80211_IFTYPE_STATION)
476 },
477 {
478 /* The p2p interface in P2P+P2P can be GO/CLI.
479 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
480 */
481 .max = 2,
482 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
483 },
484};
485
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700486static const struct ieee80211_iface_limit
487 wlan_hdd_mon_iface_limit[] = {
488 {
489 .max = 3, /* Monitor interface */
490 .types = BIT(NL80211_IFTYPE_MONITOR),
491 },
492};
493
494static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800495 wlan_hdd_iface_combination[] = {
496 /* STA */
497 {
498 .limits = wlan_hdd_sta_iface_limit,
499 .num_different_channels = 2,
500 .max_interfaces = 3,
501 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
502 },
503 /* ADHOC */
504 {
505 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700506 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800507 .max_interfaces = 2,
508 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
509 },
510 /* AP */
511 {
512 .limits = wlan_hdd_ap_iface_limit,
513 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530514 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800515 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
516 },
517 /* P2P */
518 {
519 .limits = wlan_hdd_p2p_iface_limit,
520 .num_different_channels = 2,
521 .max_interfaces = 2,
522 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
523 },
524 /* STA + AP */
525 {
526 .limits = wlan_hdd_sta_ap_iface_limit,
527 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530528 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
530 .beacon_int_infra_match = true,
531 },
532 /* STA + P2P */
533 {
534 .limits = wlan_hdd_sta_p2p_iface_limit,
535 .num_different_channels = 2,
536 /* one interface reserved for P2PDEV dedicated usage */
537 .max_interfaces = 4,
538 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
539 .beacon_int_infra_match = true,
540 },
541 /* STA + P2P GO + SAP */
542 {
543 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
544 /* we can allow 3 channels for three different persona
545 * but due to firmware limitation, allow max 2 concrnt channels.
546 */
547 .num_different_channels = 2,
548 /* one interface reserved for P2PDEV dedicated usage */
549 .max_interfaces = 4,
550 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
551 .beacon_int_infra_match = true,
552 },
553 /* SAP + P2P */
554 {
555 .limits = wlan_hdd_sap_p2p_iface_limit,
556 .num_different_channels = 2,
557 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
558 .max_interfaces = 3,
559 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
560 .beacon_int_infra_match = true,
561 },
562 /* P2P + P2P */
563 {
564 .limits = wlan_hdd_p2p_p2p_iface_limit,
565 .num_different_channels = 2,
566 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
567 .max_interfaces = 3,
568 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
569 .beacon_int_infra_match = true,
570 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530571 /* Monitor */
572 {
573 .limits = wlan_hdd_mon_iface_limit,
574 .max_interfaces = 3,
575 .num_different_channels = 2,
576 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
577 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800579
580static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530581struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582
583#ifdef WLAN_NL80211_TESTMODE
584enum wlan_hdd_tm_attr {
585 WLAN_HDD_TM_ATTR_INVALID = 0,
586 WLAN_HDD_TM_ATTR_CMD = 1,
587 WLAN_HDD_TM_ATTR_DATA = 2,
588 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
589 WLAN_HDD_TM_ATTR_TYPE = 4,
590 /* keep last */
591 WLAN_HDD_TM_ATTR_AFTER_LAST,
592 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
593};
594
595enum wlan_hdd_tm_cmd {
596 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
597 WLAN_HDD_TM_CMD_WLAN_HB = 1,
598};
599
600#define WLAN_HDD_TM_DATA_MAX_LEN 5000
601
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530602enum wlan_hdd_vendor_ie_access_policy {
603 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
604 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
605};
606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
608 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
609 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
610 .len = WLAN_HDD_TM_DATA_MAX_LEN},
611};
612#endif /* WLAN_NL80211_TESTMODE */
613
614#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
615static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
616 .flags = WIPHY_WOWLAN_MAGIC_PKT,
617 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
618 .pattern_min_len = 1,
619 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
620};
621#endif
622
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800623/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530624 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
625 * @flags: Pointer to the flags to Add channel switch flag.
626 *
627 * This Function adds Channel Switch support flag, if channel switch is
628 * supported by kernel.
629 * Return: void.
630 */
631#ifdef CHANNEL_SWITCH_SUPPORTED
632static inline void hdd_add_channel_switch_support(uint32_t *flags)
633{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800634 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530635 return;
636}
637#else
638static inline void hdd_add_channel_switch_support(uint32_t *flags)
639{
640 return;
641}
642#endif
643
Manikandan Mohan22b83722015-12-15 15:03:23 -0800644#ifdef FEATURE_WLAN_TDLS
645
646/* TDLS capabilities params */
647#define PARAM_MAX_TDLS_SESSION \
648 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
649#define PARAM_TDLS_FEATURE_SUPPORT \
650 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
651
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530652/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800653 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
654 * @wiphy: WIPHY structure pointer
655 * @wdev: Wireless device structure pointer
656 * @data: Pointer to the data received
657 * @data_len: Length of the data received
658 *
659 * This function provides TDLS capabilities
660 *
661 * Return: 0 on success and errno on failure
662 */
663static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
664 struct wireless_dev *wdev,
665 const void *data,
666 int data_len)
667{
668 int status;
669 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
670 struct sk_buff *skb;
671 uint32_t set = 0;
672
Jeff Johnson1f61b612016-02-12 16:28:33 -0800673 ENTER_DEV(wdev->netdev);
674
Anurag Chouhan6d760662016-02-20 16:05:43 +0530675 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676 hdd_err("Command not allowed in FTM mode");
677 return -EPERM;
678 }
679
680 status = wlan_hdd_validate_context(hdd_ctx);
681 if (status)
682 return status;
683
684 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
685 NLMSG_HDRLEN);
686 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700687 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 goto fail;
689 }
690
691 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700692 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800693 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
694 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700695 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 goto fail;
697 }
698 } else {
699 set = set | WIFI_TDLS_SUPPORT;
700 set = set | (hdd_ctx->config->fTDLSExternalControl ?
701 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
702 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
703 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700704 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
706 hdd_ctx->max_num_tdls_sta) ||
707 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
708 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700709 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 goto fail;
711 }
712 }
713 return cfg80211_vendor_cmd_reply(skb);
714fail:
715 if (skb)
716 kfree_skb(skb);
717 return -EINVAL;
718}
719
720/**
721 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
722 * @wiphy: WIPHY structure pointer
723 * @wdev: Wireless device structure pointer
724 * @data: Pointer to the data received
725 * @data_len: Length of the data received
726 *
727 * This function provides TDLS capabilities
728 *
729 * Return: 0 on success and errno on failure
730 */
731static int
732wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
733 struct wireless_dev *wdev,
734 const void *data,
735 int data_len)
736{
737 int ret;
738
739 cds_ssr_protect(__func__);
740 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
741 data, data_len);
742 cds_ssr_unprotect(__func__);
743
744 return ret;
745}
746#endif
747
748#ifdef QCA_HT_2040_COEX
749static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
750#endif
751
752#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
753/*
754 * FUNCTION: wlan_hdd_send_avoid_freq_event
755 * This is called when wlan driver needs to send vendor specific
756 * avoid frequency range event to userspace
757 */
758int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
759 tHddAvoidFreqList *pAvoidFreqList)
760{
761 struct sk_buff *vendor_event;
762
763 ENTER();
764
765 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700766 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 return -EINVAL;
768 }
769
770 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700771 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772 return -EINVAL;
773 }
774
775 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
776 NULL,
777 sizeof(tHddAvoidFreqList),
778 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
779 GFP_KERNEL);
780 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700781 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782 return -EINVAL;
783 }
784
785 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
786 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
787
788 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
789
790 EXIT();
791 return 0;
792}
793#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
794
795/* vendor specific events */
796static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
797#ifdef FEATURE_WLAN_CH_AVOID
798 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
799 .vendor_id =
800 QCA_NL80211_VENDOR_ID,
801 .subcmd =
802 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
803 },
804#endif /* FEATURE_WLAN_CH_AVOID */
805
806#ifdef WLAN_FEATURE_NAN
807 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
808 .vendor_id =
809 QCA_NL80211_VENDOR_ID,
810 .subcmd =
811 QCA_NL80211_VENDOR_SUBCMD_NAN
812 },
813#endif
814
815#ifdef WLAN_FEATURE_STATS_EXT
816 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
817 .vendor_id =
818 QCA_NL80211_VENDOR_ID,
819 .subcmd =
820 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
821 },
822#endif /* WLAN_FEATURE_STATS_EXT */
823#ifdef FEATURE_WLAN_EXTSCAN
824 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
825 .vendor_id =
826 QCA_NL80211_VENDOR_ID,
827 .subcmd =
828 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
829 },
830 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
831 .vendor_id =
832 QCA_NL80211_VENDOR_ID,
833 .subcmd =
834 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
835 },
836 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
837 .
838 vendor_id
839 =
840 QCA_NL80211_VENDOR_ID,
841 .subcmd =
842 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
843 },
844 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
845 .
846 vendor_id
847 =
848 QCA_NL80211_VENDOR_ID,
849 .
850 subcmd =
851 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
852 },
853 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
854 .
855 vendor_id
856 =
857 QCA_NL80211_VENDOR_ID,
858 .
859 subcmd
860 =
861 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
862 },
863 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
864 .
865 vendor_id
866 =
867 QCA_NL80211_VENDOR_ID,
868 .subcmd =
869 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
870 },
871 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
872 .vendor_id =
873 QCA_NL80211_VENDOR_ID,
874 .subcmd =
875 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
876 },
877 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
878 .
879 vendor_id
880 =
881 QCA_NL80211_VENDOR_ID,
882 .subcmd =
883 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
884 },
885 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
886 .
887 vendor_id
888 =
889 QCA_NL80211_VENDOR_ID,
890 .subcmd =
891 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
892 },
893 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
894 .
895 vendor_id
896 =
897 QCA_NL80211_VENDOR_ID,
898 .
899 subcmd
900 =
901 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
902 },
903 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
904 .
905 vendor_id
906 =
907 QCA_NL80211_VENDOR_ID,
908 .
909 subcmd =
910 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
911 },
912 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
913 .
914 vendor_id
915 =
916 QCA_NL80211_VENDOR_ID,
917 .
918 subcmd
919 =
920 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
921 },
922 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
923 .
924 vendor_id
925 =
926 QCA_NL80211_VENDOR_ID,
927 .
928 subcmd
929 =
930 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
931 },
932 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
933 .vendor_id = QCA_NL80211_VENDOR_ID,
934 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
935 },
936 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
937 .vendor_id = QCA_NL80211_VENDOR_ID,
938 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
939 },
940#endif /* FEATURE_WLAN_EXTSCAN */
941
942#ifdef WLAN_FEATURE_LINK_LAYER_STATS
943 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
944 .vendor_id =
945 QCA_NL80211_VENDOR_ID,
946 .subcmd =
947 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
948 },
949 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
950 .vendor_id =
951 QCA_NL80211_VENDOR_ID,
952 .subcmd =
953 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
954 },
955 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
956 .vendor_id =
957 QCA_NL80211_VENDOR_ID,
958 .subcmd =
959 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
960 },
961 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
962 .vendor_id =
963 QCA_NL80211_VENDOR_ID,
964 .subcmd =
965 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
966 },
967 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
968 .vendor_id =
969 QCA_NL80211_VENDOR_ID,
970 .subcmd =
971 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
972 },
973 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
974 .vendor_id =
975 QCA_NL80211_VENDOR_ID,
976 .subcmd =
977 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
978 },
979#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
980 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
981 .vendor_id =
982 QCA_NL80211_VENDOR_ID,
983 .subcmd =
984 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
985 },
986 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
987 .vendor_id = QCA_NL80211_VENDOR_ID,
988 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
989 },
990#ifdef WLAN_FEATURE_ROAM_OFFLOAD
991 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
992 .vendor_id =
993 QCA_NL80211_VENDOR_ID,
994 .subcmd =
995 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
996 },
997#endif
998 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
999 .vendor_id =
1000 QCA_NL80211_VENDOR_ID,
1001 .subcmd =
1002 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1003 },
1004 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1005 .vendor_id =
1006 QCA_NL80211_VENDOR_ID,
1007 .subcmd =
1008 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1009 },
1010 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1011 .vendor_id =
1012 QCA_NL80211_VENDOR_ID,
1013 .subcmd =
1014 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1015 },
1016 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1017 .vendor_id =
1018 QCA_NL80211_VENDOR_ID,
1019 .subcmd =
1020 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1021 },
1022 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1023 .vendor_id =
1024 QCA_NL80211_VENDOR_ID,
1025 .subcmd =
1026 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1027 },
1028#ifdef FEATURE_WLAN_EXTSCAN
1029 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1030 .vendor_id = QCA_NL80211_VENDOR_ID,
1031 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1032 },
1033 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1034 .vendor_id = QCA_NL80211_VENDOR_ID,
1035 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1036 },
1037 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1038 .vendor_id = QCA_NL80211_VENDOR_ID,
1039 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1040 },
1041 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1042 .vendor_id = QCA_NL80211_VENDOR_ID,
1043 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1044 },
1045 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1046 .vendor_id = QCA_NL80211_VENDOR_ID,
1047 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1048 },
1049#endif /* FEATURE_WLAN_EXTSCAN */
1050 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1051 .vendor_id = QCA_NL80211_VENDOR_ID,
1052 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1053 },
1054#ifdef WLAN_FEATURE_MEMDUMP
1055 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1056 .vendor_id = QCA_NL80211_VENDOR_ID,
1057 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1058 },
1059#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001060#ifdef WLAN_FEATURE_TSF
1061 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1062 .vendor_id = QCA_NL80211_VENDOR_ID,
1063 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1064 },
1065#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001066 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1067 .vendor_id = QCA_NL80211_VENDOR_ID,
1068 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1069 },
1070 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1071 .vendor_id = QCA_NL80211_VENDOR_ID,
1072 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1073 },
1074 /* OCB events */
1075 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1076 .vendor_id = QCA_NL80211_VENDOR_ID,
1077 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1078 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001079#ifdef FEATURE_LFR_SUBNET_DETECTION
1080 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1081 .vendor_id = QCA_NL80211_VENDOR_ID,
1082 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1083 },
1084#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001085
1086#ifdef WLAN_FEATURE_NAN_DATAPATH
1087 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1088 .vendor_id = QCA_NL80211_VENDOR_ID,
1089 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1090 },
1091#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001092
1093 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1094 .vendor_id = QCA_NL80211_VENDOR_ID,
1095 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1096 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301097 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1098 .vendor_id = QCA_NL80211_VENDOR_ID,
1099 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1100 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001101};
1102
1103/**
1104 * __is_driver_dfs_capable() - get driver DFS capability
1105 * @wiphy: pointer to wireless wiphy structure.
1106 * @wdev: pointer to wireless_dev structure.
1107 * @data: Pointer to the data to be passed via vendor interface
1108 * @data_len:Length of the data to be passed
1109 *
1110 * This function is called by userspace to indicate whether or not
1111 * the driver supports DFS offload.
1112 *
1113 * Return: 0 on success, negative errno on failure
1114 */
1115static int __is_driver_dfs_capable(struct wiphy *wiphy,
1116 struct wireless_dev *wdev,
1117 const void *data,
1118 int data_len)
1119{
1120 u32 dfs_capability = 0;
1121 struct sk_buff *temp_skbuff;
1122 int ret_val;
1123 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1124
Jeff Johnson1f61b612016-02-12 16:28:33 -08001125 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001126
1127 ret_val = wlan_hdd_validate_context(hdd_ctx);
1128 if (ret_val)
1129 return ret_val;
1130
Anurag Chouhan6d760662016-02-20 16:05:43 +05301131 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 hdd_err("Command not allowed in FTM mode");
1133 return -EPERM;
1134 }
1135
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137
1138 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1139 NLMSG_HDRLEN);
1140
1141 if (temp_skbuff != NULL) {
1142 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1143 dfs_capability);
1144 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001145 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146 kfree_skb(temp_skbuff);
1147
1148 return ret_val;
1149 }
1150
1151 return cfg80211_vendor_cmd_reply(temp_skbuff);
1152 }
1153
Jeff Johnson020db452016-06-29 14:37:26 -07001154 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001155 return -ENOMEM;
1156}
1157
1158/**
1159 * is_driver_dfs_capable() - get driver DFS capability
1160 * @wiphy: pointer to wireless wiphy structure.
1161 * @wdev: pointer to wireless_dev structure.
1162 * @data: Pointer to the data to be passed via vendor interface
1163 * @data_len:Length of the data to be passed
1164 *
1165 * This function is called by userspace to indicate whether or not
1166 * the driver supports DFS offload. This is an SSR-protected
1167 * wrapper function.
1168 *
1169 * Return: 0 on success, negative errno on failure
1170 */
1171static int is_driver_dfs_capable(struct wiphy *wiphy,
1172 struct wireless_dev *wdev,
1173 const void *data,
1174 int data_len)
1175{
1176 int ret;
1177
1178 cds_ssr_protect(__func__);
1179 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1180 cds_ssr_unprotect(__func__);
1181
1182 return ret;
1183}
1184
1185/**
1186 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1187 *
1188 * @adapter: SAP adapter pointer
1189 *
1190 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1191 * radio. So in case of DFS MCC scenario override current SAP given config
1192 * to follow concurrent SAP DFS config
1193 *
1194 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1195 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001196int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1197{
1198 hdd_adapter_t *con_sap_adapter;
1199 tsap_Config_t *sap_config, *con_sap_config;
1200 int con_ch;
1201
1202 /*
1203 * Check if AP+AP case, once primary AP chooses a DFS
1204 * channel secondary AP should always follow primary APs channel
1205 */
1206 if (!cds_concurrent_beaconing_sessions_running())
1207 return 0;
1208
1209 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1210 if (!con_sap_adapter)
1211 return 0;
1212
1213 sap_config = &adapter->sessionCtx.ap.sapConfig;
1214 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1215 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1216
1217 if (!CDS_IS_DFS_CH(con_ch))
1218 return 0;
1219
Jeff Johnson020db452016-06-29 14:37:26 -07001220 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001222 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223 sap_config->channel = con_ch;
1224
1225 if (con_sap_config->acs_cfg.acs_mode == true) {
1226 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1227 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001228 hdd_err("Primary AP channel config error");
1229 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230 con_ch, con_sap_config->acs_cfg.pri_ch,
1231 con_sap_config->acs_cfg.ht_sec_ch);
1232 return -EINVAL;
1233 }
1234 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1235 * MCC restriction. So free ch list allocated in do_acs
1236 * func for Sec AP and realloc for Pri AP ch list size
1237 */
1238 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301239 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301241 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242 &con_sap_config->acs_cfg,
1243 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301244 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001245 sizeof(uint8_t) *
1246 con_sap_config->acs_cfg.ch_list_count);
1247 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001248 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249 return -ENOMEM;
1250 }
1251
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301252 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253 con_sap_config->acs_cfg.ch_list,
1254 con_sap_config->acs_cfg.ch_list_count);
1255
1256 } else {
1257 sap_config->acs_cfg.pri_ch = con_ch;
1258 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1259 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1260 }
1261
1262 return con_ch;
1263}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264
1265/**
1266 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1267 * @sap_cfg: pointer to SAP config struct
1268 *
1269 * This function sets the default ACS start and end channel for the given band
1270 * and also parses the given ACS channel list.
1271 *
1272 * Return: None
1273 */
1274
1275static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1276 bool vht_enabled)
1277{
1278 int i;
1279 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1280 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001281 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1282 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001283 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1284 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001285 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1286 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001287 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1288 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001289 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1290 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1292 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001293 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1294 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295 }
1296
1297 if (ht_enabled)
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1299
1300 if (vht_enabled)
1301 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1302
1303
1304 /* Parse ACS Chan list from hostapd */
1305 if (!sap_cfg->acs_cfg.ch_list)
1306 return;
1307
1308 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1309 sap_cfg->acs_cfg.end_ch =
1310 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1311 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301312 /* avoid channel as start channel */
1313 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1314 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001315 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1316 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1317 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1318 }
1319}
1320
1321
1322static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1323
1324/**
1325 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1326 * @adapter: pointer to SAP adapter struct
1327 *
1328 * This function starts the ACS procedure if there are no
1329 * constraints like MBSSID DFS restrictions.
1330 *
1331 * Return: Status of ACS Start procedure
1332 */
1333
1334static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1335{
1336
1337 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1338 tsap_Config_t *sap_config;
1339 tpWLAN_SAPEventCB acs_event_callback;
1340 int status;
1341
1342 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301343 if (hdd_ctx->acs_policy.acs_channel)
1344 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1345 else
1346 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347
1348 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1349 if (status < 0) {
1350 return status;
1351 } else {
1352 if (status > 0) {
1353 /*notify hostapd about channel override */
1354 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1355 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1356 return 0;
1357 }
1358 }
1359 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1360 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001361 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362 return -EINVAL;
1363 }
1364
1365 acs_event_callback = hdd_hostapd_sap_event_cb;
1366
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301367 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301368 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001369 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 acs_event_callback, sap_config, adapter->dev);
1373
1374
1375 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001376 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 return -EINVAL;
1378 }
1379 sap_config->acs_cfg.acs_mode = true;
1380 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1381
1382 return 0;
1383}
1384
1385/**
1386 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1387 * @wiphy: Linux wiphy struct pointer
1388 * @wdev: Linux wireless device struct pointer
1389 * @data: ACS information from hostapd
1390 * @data_len: ACS information length
1391 *
1392 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1393 * and starts ACS procedure.
1394 *
1395 * Return: ACS procedure start status
1396 */
1397
1398static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1399 struct wireless_dev *wdev,
1400 const void *data, int data_len)
1401{
1402 struct net_device *ndev = wdev->netdev;
1403 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1404 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1405 tsap_Config_t *sap_config;
1406 struct sk_buff *temp_skbuff;
1407 int status = -EINVAL, i = 0;
1408 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1409 bool ht_enabled, ht40_enabled, vht_enabled;
1410 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301411 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001412
1413 /* ***Note*** Donot set SME config related to ACS operation here because
1414 * ACS operation is not synchronouse and ACS for Second AP may come when
1415 * ACS operation for first AP is going on. So only do_acs is split to
1416 * seperate start_acs routine. Also SME-PMAC struct that is used to
1417 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1418 * config shall be set only from start_acs.
1419 */
1420
1421 /* nla_policy Policy template. Policy not applied as some attributes are
1422 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1423 *
1424 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1425 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1426 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1427 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1428 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1429 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1430 */
1431
Jeff Johnson1f61b612016-02-12 16:28:33 -08001432 ENTER_DEV(ndev);
1433
Anurag Chouhan6d760662016-02-20 16:05:43 +05301434 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001435 hdd_err("Command not allowed in FTM mode");
1436 return -EPERM;
1437 }
1438
1439 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001440 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001441 return -EPERM;
1442 }
1443
1444 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301445 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001446 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301447
Naveen Rawat64e477e2016-05-20 10:34:56 -07001448 if (cds_is_sub_20_mhz_enabled()) {
1449 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1450 status = -EINVAL;
1451 goto out;
1452 }
1453
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001454 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301455 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456
1457 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1458 NULL);
1459 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001460 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001461 goto out;
1462 }
1463
1464 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001465 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001466 goto out;
1467 }
1468 sap_config->acs_cfg.hw_mode = nla_get_u8(
1469 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1470
1471 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1472 ht_enabled =
1473 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1474 else
1475 ht_enabled = 0;
1476
1477 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1478 ht40_enabled =
1479 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1480 else
1481 ht40_enabled = 0;
1482
1483 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1484 vht_enabled =
1485 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1486 else
1487 vht_enabled = 0;
1488
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301489 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1490 vht_enabled = 0;
1491 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1492 }
1493
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001494 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1495 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1496 } else {
1497 if (ht_enabled && ht40_enabled)
1498 ch_width = 40;
1499 else
1500 ch_width = 20;
1501 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301502
1503 /* this may be possible, when sap_force_11n_for_11ac is set */
1504 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1505 if (ht_enabled && ht40_enabled)
1506 ch_width = 40;
1507 else
1508 ch_width = 20;
1509 }
1510
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511 if (ch_width == 80)
1512 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1513 else if (ch_width == 40)
1514 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1515 else
1516 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1517
1518 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1519 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1520 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1521 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1522 * since it contains the frequency values of the channels in
1523 * the channel list.
1524 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1525 * is present
1526 */
1527 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1528 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1529 sap_config->acs_cfg.ch_list_count = nla_len(
1530 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1531 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301532 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533 sizeof(uint8_t) *
1534 sap_config->acs_cfg.ch_list_count);
1535 if (sap_config->acs_cfg.ch_list == NULL)
1536 goto out;
1537
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301538 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001539 sap_config->acs_cfg.ch_list_count);
1540 }
1541 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1542 uint32_t *freq =
1543 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1544 sap_config->acs_cfg.ch_list_count = nla_len(
1545 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1546 sizeof(uint32_t);
1547 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301548 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001549 sap_config->acs_cfg.ch_list_count);
1550 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001551 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001552 status = -ENOMEM;
1553 goto out;
1554 }
1555
1556 /* convert frequency to channel */
1557 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1558 sap_config->acs_cfg.ch_list[i] =
1559 ieee80211_frequency_to_channel(freq[i]);
1560 }
1561 }
1562
1563 hdd_debug("get pcl for DO_ACS vendor command");
1564
1565 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001566 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301567 sap_config->acs_cfg.pcl_channels,
1568 &sap_config->acs_cfg.pcl_ch_count,
1569 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301570 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001571 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001572
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001573 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301574 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
1575 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07001576 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001577 vht_enabled = 1;
1578 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1579 sap_config->acs_cfg.ch_width =
1580 hdd_ctx->config->vhtChannelWidth;
1581 /* No VHT80 in 2.4G so perform ACS accordingly */
1582 if (sap_config->acs_cfg.end_ch <= 14 &&
1583 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1584 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1585 }
1586
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301587 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1588
Jeff Johnson020db452016-06-29 14:37:26 -07001589 hdd_notice("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001590 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1591 ch_width, ht_enabled, vht_enabled,
1592 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1593
1594 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001595 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001596 sap_config->acs_cfg.ch_list_count);
1597 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001598 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001599 }
1600 sap_config->acs_cfg.acs_mode = true;
1601 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001602 /* ***Note*** Completion variable usage is not allowed
1603 * here since ACS scan operation may take max 2.2 sec
1604 * for 5G band:
1605 * 9 Active channel X 40 ms active scan time +
1606 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001607 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1608 * for this long. So we split up the scanning part.
1609 */
1610 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001611 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001612 status = 0;
1613 } else {
1614 status = wlan_hdd_cfg80211_start_acs(adapter);
1615 }
1616
1617out:
1618 if (0 == status) {
1619 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1620 NLMSG_HDRLEN);
1621 if (temp_skbuff != NULL)
1622 return cfg80211_vendor_cmd_reply(temp_skbuff);
1623 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001624 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001625 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1626
1627 return status;
1628}
1629
1630 /**
1631 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1632 * @wiphy: Linux wiphy struct pointer
1633 * @wdev: Linux wireless device struct pointer
1634 * @data: ACS information from hostapd
1635 * @data_len: ACS information len
1636 *
1637 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1638 * and starts ACS procedure.
1639 *
1640 * Return: ACS procedure start status
1641 */
1642
1643static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1644 struct wireless_dev *wdev,
1645 const void *data, int data_len)
1646{
1647 int ret;
1648
1649 cds_ssr_protect(__func__);
1650 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1651 cds_ssr_unprotect(__func__);
1652
1653 return ret;
1654}
1655
1656/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001657 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
1658 * @adapter: Pointer to adapter struct
1659 *
1660 * This function handle cleanup of what was done in DO_ACS, including free
1661 * memory.
1662 *
1663 * Return: void
1664 */
1665
1666void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
1667{
1668 if (adapter == NULL)
1669 return;
1670 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
1671 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
1672 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
1673 }
1674}
1675
1676/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001677 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1678 * @work: Linux workqueue struct pointer for ACS work
1679 *
1680 * This function starts the ACS procedure which was marked pending when an ACS
1681 * procedure was in progress for a concurrent SAP interface.
1682 *
1683 * Return: None
1684 */
1685
1686static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1687{
1688 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1689 acs_pending_work.work);
1690 wlan_hdd_cfg80211_start_acs(adapter);
1691}
1692
1693/**
1694 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1695 * @adapter: Pointer to SAP adapter struct
1696 * @pri_channel: SAP ACS procedure selected Primary channel
1697 * @sec_channel: SAP ACS procedure selected secondary channel
1698 *
1699 * This is a callback function from SAP module on ACS procedure is completed.
1700 * This function send the ACS selected channel information to hostapd
1701 *
1702 * Return: None
1703 */
1704
1705void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1706{
1707 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1708 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1709 struct sk_buff *vendor_event;
1710 int ret_val;
1711 hdd_adapter_t *con_sap_adapter;
1712 uint16_t ch_width;
1713
1714 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001715 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001716 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1717 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1718 GFP_KERNEL);
1719
1720 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001721 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001722 return;
1723 }
1724
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001725 ret_val = nla_put_u8(vendor_event,
1726 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1727 sap_cfg->acs_cfg.pri_ch);
1728 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001729 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001730 kfree_skb(vendor_event);
1731 return;
1732 }
1733
1734 ret_val = nla_put_u8(vendor_event,
1735 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1736 sap_cfg->acs_cfg.ht_sec_ch);
1737 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001738 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001739 kfree_skb(vendor_event);
1740 return;
1741 }
1742
1743 ret_val = nla_put_u8(vendor_event,
1744 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1745 sap_cfg->acs_cfg.vht_seg0_center_ch);
1746 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001747 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001748 kfree_skb(vendor_event);
1749 return;
1750 }
1751
1752 ret_val = nla_put_u8(vendor_event,
1753 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1754 sap_cfg->acs_cfg.vht_seg1_center_ch);
1755 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001756 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001757 kfree_skb(vendor_event);
1758 return;
1759 }
1760
1761 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1762 ch_width = 80;
1763 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1764 ch_width = 40;
1765 else
1766 ch_width = 20;
1767
1768 ret_val = nla_put_u16(vendor_event,
1769 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1770 ch_width);
1771 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001772 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001773 kfree_skb(vendor_event);
1774 return;
1775 }
1776 if (sap_cfg->acs_cfg.pri_ch > 14)
1777 ret_val = nla_put_u8(vendor_event,
1778 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1779 QCA_ACS_MODE_IEEE80211A);
1780 else
1781 ret_val = nla_put_u8(vendor_event,
1782 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1783 QCA_ACS_MODE_IEEE80211G);
1784
1785 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001786 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001787 kfree_skb(vendor_event);
1788 return;
1789 }
1790
Jeff Johnson46b40792016-06-29 14:03:14 -07001791 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 -08001792 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1793 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1794 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1795
1796 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1797 /* ***Note*** As already mentioned Completion variable usage is not
1798 * allowed here since ACS scan operation may take max 2.2 sec.
1799 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1800 * operation.
1801 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1802 * when Primary AP ACS is complete and secondary AP ACS is started here
1803 * immediately, Primary AP start_bss may come inbetween ACS operation
1804 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1805 * delay. This path and below constraint will be removed on sessionizing
1806 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1807 * As per design constraint user space control application must take
1808 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1809 * this code path. Sec AP hostapd should be started after Primary AP
1810 * start beaconing which can be confirmed by getchannel iwpriv command
1811 */
1812
1813 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1814 if (con_sap_adapter &&
1815 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001816 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1817 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001818 /* Lets give 500ms for OBSS + START_BSS to complete */
1819 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1820 msecs_to_jiffies(500));
1821 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1822 }
1823
1824 return;
1825}
1826
1827static int
1828__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1829 struct wireless_dev *wdev,
1830 const void *data,
1831 int data_len)
1832{
1833 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1834 struct sk_buff *skb = NULL;
1835 uint32_t fset = 0;
1836 int ret;
1837
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001838 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301839
Anurag Chouhan6d760662016-02-20 16:05:43 +05301840 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001841 hdd_err("Command not allowed in FTM mode");
1842 return -EPERM;
1843 }
1844
1845 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301846 if (ret)
1847 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001848
1849 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001850 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001851 fset |= WIFI_FEATURE_INFRA;
1852 }
1853 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001854 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001855 fset |= WIFI_FEATURE_INFRA_5G;
1856 }
1857#ifdef WLAN_FEATURE_P2P
1858 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1859 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001860 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001861 fset |= WIFI_FEATURE_P2P;
1862 }
1863#endif
1864 fset |= WIFI_FEATURE_SOFT_AP;
1865
1866 /* HOTSPOT is a supplicant feature, enable it by default */
1867 fset |= WIFI_FEATURE_HOTSPOT;
1868
1869#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301870 if (pHddCtx->config->extscan_enabled &&
1871 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001872 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001873 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1874 }
1875#endif
1876 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001877 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001878 fset |= WIFI_FEATURE_NAN;
1879 }
1880 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001881 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001882 fset |= WIFI_FEATURE_D2D_RTT;
1883 fset |= WIFI_FEATURE_D2AP_RTT;
1884 }
1885#ifdef FEATURE_WLAN_SCAN_PNO
1886 if (pHddCtx->config->configPNOScanSupport &&
1887 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001888 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001889 fset |= WIFI_FEATURE_PNO;
1890 }
1891#endif
1892 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1893#ifdef FEATURE_WLAN_TDLS
1894 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1895 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001896 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897 fset |= WIFI_FEATURE_TDLS;
1898 }
1899 if (sme_is_feature_supported_by_fw(TDLS) &&
1900 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1901 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001902 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1904 }
1905#endif
1906#ifdef WLAN_AP_STA_CONCURRENCY
1907 fset |= WIFI_FEATURE_AP_STA;
1908#endif
1909 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07001910 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001911
1912 if (hdd_link_layer_stats_supported())
1913 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1914
1915 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1916 NLMSG_HDRLEN);
1917 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001918 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919 return -EINVAL;
1920 }
Jeff Johnson020db452016-06-29 14:37:26 -07001921 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001922 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001923 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001924 goto nla_put_failure;
1925 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301926 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301927 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001928nla_put_failure:
1929 kfree_skb(skb);
1930 return -EINVAL;
1931}
1932
1933/**
1934 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1935 * @wiphy: pointer to wireless wiphy structure.
1936 * @wdev: pointer to wireless_dev structure.
1937 * @data: Pointer to the data to be passed via vendor interface
1938 * @data_len:Length of the data to be passed
1939 *
1940 * Return: Return the Success or Failure code.
1941 */
1942static int
1943wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1944 struct wireless_dev *wdev,
1945 const void *data, int data_len)
1946{
1947 int ret = 0;
1948
1949 cds_ssr_protect(__func__);
1950 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1951 data, data_len);
1952 cds_ssr_unprotect(__func__);
1953
1954 return ret;
1955}
1956
1957/**
1958 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1959 * @wiphy: pointer to wireless wiphy structure.
1960 * @wdev: pointer to wireless_dev structure.
1961 * @data: Pointer to the data to be passed via vendor interface
1962 * @data_len:Length of the data to be passed
1963 *
1964 * Set the MAC address that is to be used for scanning.
1965 *
1966 * Return: Return the Success or Failure code.
1967 */
1968static int
1969__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1970 struct wireless_dev *wdev,
1971 const void *data,
1972 int data_len)
1973{
1974 tpSirScanMacOui pReqMsg = NULL;
1975 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1976 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301977 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 int ret;
1979
Jeff Johnson1f61b612016-02-12 16:28:33 -08001980 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981
Anurag Chouhan6d760662016-02-20 16:05:43 +05301982 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983 hdd_err("Command not allowed in FTM mode");
1984 return -EPERM;
1985 }
1986
1987 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301988 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001990
1991 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001992 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993 return -ENOTSUPP;
1994 }
1995
1996 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1997 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001998 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001999 return -EINVAL;
2000 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302001 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002002 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002003 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002004 return -ENOMEM;
2005 }
2006 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002007 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002008 goto fail;
2009 }
2010 nla_memcpy(&pReqMsg->oui[0],
2011 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2012 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002013 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002014 pReqMsg->oui[1], pReqMsg->oui[2]);
2015 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302016 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002017 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002018 goto fail;
2019 }
2020 return 0;
2021fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302022 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002023 return -EINVAL;
2024}
2025
2026/**
2027 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2028 * @wiphy: pointer to wireless wiphy structure.
2029 * @wdev: pointer to wireless_dev structure.
2030 * @data: Pointer to the data to be passed via vendor interface
2031 * @data_len:Length of the data to be passed
2032 *
2033 * Set the MAC address that is to be used for scanning. This is an
2034 * SSR-protecting wrapper function.
2035 *
2036 * Return: Return the Success or Failure code.
2037 */
2038static int
2039wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2040 struct wireless_dev *wdev,
2041 const void *data,
2042 int data_len)
2043{
2044 int ret;
2045
2046 cds_ssr_protect(__func__);
2047 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2048 data, data_len);
2049 cds_ssr_unprotect(__func__);
2050
2051 return ret;
2052}
2053
2054/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302055 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2056 * @wiphy: pointer phy adapter
2057 * @wdev: pointer to wireless device structure
2058 * @data: pointer to data buffer
2059 * @data_len: length of data
2060 *
2061 * This routine will give concurrency matrix
2062 *
2063 * Return: int status code
2064 */
2065static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2066 struct wireless_dev *wdev,
2067 const void *data,
2068 int data_len)
2069{
2070 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2071 uint8_t i, feature_sets, max_feature_sets;
2072 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2073 struct sk_buff *reply_skb;
2074 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2075 int ret;
2076
2077 ENTER_DEV(wdev->netdev);
2078
2079 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2080 hdd_err("Command not allowed in FTM mode");
2081 return -EPERM;
2082 }
2083
2084 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302085 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302086 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302087
2088 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2089 data, data_len, NULL)) {
2090 hdd_err("Invalid ATTR");
2091 return -EINVAL;
2092 }
2093
2094 /* Parse and fetch max feature set */
2095 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2096 hdd_err("Attr max feature set size failed");
2097 return -EINVAL;
2098 }
2099 max_feature_sets = nla_get_u32(tb[
2100 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2101 hdd_info("Max feature set size: %d", max_feature_sets);
2102
2103 /* Fill feature combination matrix */
2104 feature_sets = 0;
2105 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002106 WIFI_FEATURE_P2P;
2107 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2108 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302109 /* Add more feature combinations here */
2110
2111 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002112 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302113 hdd_info("Feature set matrix");
2114 for (i = 0; i < feature_sets; i++)
2115 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2116
2117 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2118 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2119 if (!reply_skb) {
2120 hdd_err("Feature set matrix: buffer alloc fail");
2121 return -ENOMEM;
2122 }
2123
2124 if (nla_put_u32(reply_skb,
2125 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2126 feature_sets) ||
2127 nla_put(reply_skb,
2128 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2129 sizeof(u32) * feature_sets,
2130 feature_set_matrix)) {
2131 hdd_err("nla put fail");
2132 kfree_skb(reply_skb);
2133 return -EINVAL;
2134 }
2135 return cfg80211_vendor_cmd_reply(reply_skb);
2136}
2137
2138/**
2139 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2140 * @wiphy: pointer to wireless wiphy structure.
2141 * @wdev: pointer to wireless_dev structure.
2142 * @data: Pointer to the data to be passed via vendor interface
2143 * @data_len:Length of the data to be passed
2144 *
2145 * Retrieves the concurrency feature set matrix
2146 *
2147 * Return: 0 on success, negative errno on failure
2148 */
2149static int
2150wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2151 struct wireless_dev *wdev,
2152 const void *data,
2153 int data_len)
2154{
2155 int ret;
2156
2157 cds_ssr_protect(__func__);
2158 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2159 data, data_len);
2160 cds_ssr_unprotect(__func__);
2161
2162 return ret;
2163}
2164
2165/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002166 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2167 * @feature_flags: pointer to the byte array of features.
2168 * @feature: Feature to be turned ON in the byte array.
2169 *
2170 * Return: None
2171 *
2172 * This is called to turn ON or SET the feature flag for the requested feature.
2173 **/
2174#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002175static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2176 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002177{
2178 uint32_t index;
2179 uint8_t bit_mask;
2180
2181 index = feature / NUM_BITS_IN_BYTE;
2182 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2183 feature_flags[index] |= bit_mask;
2184}
2185
2186/**
2187 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2188 * @wiphy: pointer to wireless wiphy structure.
2189 * @wdev: pointer to wireless_dev structure.
2190 * @data: Pointer to the data to be passed via vendor interface
2191 * @data_len:Length of the data to be passed
2192 *
2193 * This is called when wlan driver needs to send supported feature set to
2194 * supplicant upon a request/query from the supplicant.
2195 *
2196 * Return: Return the Success or Failure code.
2197 **/
2198#define MAX_CONCURRENT_CHAN_ON_24G 2
2199#define MAX_CONCURRENT_CHAN_ON_5G 2
2200static int
2201__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2202 struct wireless_dev *wdev,
2203 const void *data, int data_len)
2204{
2205 struct sk_buff *skb = NULL;
2206 uint32_t dbs_capability = 0;
2207 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302208 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002209 int ret_val;
2210
2211 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2212 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2213
Jeff Johnson1f61b612016-02-12 16:28:33 -08002214 ENTER_DEV(wdev->netdev);
2215
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002216 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2217 if (ret_val)
2218 return ret_val;
2219
Anurag Chouhan6d760662016-02-20 16:05:43 +05302220 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002221 hdd_err("Command not allowed in FTM mode");
2222 return -EPERM;
2223 }
2224
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002225 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002226 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002227 wlan_hdd_cfg80211_set_feature(feature_flags,
2228 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2229 }
2230
2231 wlan_hdd_cfg80211_set_feature(feature_flags,
2232 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2233 if (wma_is_scan_simultaneous_capable())
2234 wlan_hdd_cfg80211_set_feature(feature_flags,
2235 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002236
2237 if (wma_is_p2p_lo_capable())
2238 wlan_hdd_cfg80211_set_feature(feature_flags,
2239 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2240
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002241 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2242 NLMSG_HDRLEN);
2243
2244 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002245 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002246 return -ENOMEM;
2247 }
2248
2249 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2250 sizeof(feature_flags), feature_flags))
2251 goto nla_put_failure;
2252
2253 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302254 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002255 if (one_by_one_dbs)
2256 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2257
2258 if (two_by_two_dbs)
2259 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2260
2261 if (!one_by_one_dbs && !two_by_two_dbs)
2262 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2263 } else {
2264 hdd_err("wma_get_dbs_hw_mode failed");
2265 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2266 }
2267
2268 hdd_info("dbs_capability is %d", dbs_capability);
2269
2270 if (nla_put_u32(skb,
2271 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2272 MAX_CONCURRENT_CHAN_ON_24G))
2273 goto nla_put_failure;
2274
2275 if (nla_put_u32(skb,
2276 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2277 MAX_CONCURRENT_CHAN_ON_5G))
2278 goto nla_put_failure;
2279
2280 return cfg80211_vendor_cmd_reply(skb);
2281
2282nla_put_failure:
2283 kfree_skb(skb);
2284 return -EINVAL;
2285}
2286
2287/**
2288 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2289 * @wiphy: pointer to wireless wiphy structure.
2290 * @wdev: pointer to wireless_dev structure.
2291 * @data: Pointer to the data to be passed via vendor interface
2292 * @data_len:Length of the data to be passed
2293 *
2294 * This is called when wlan driver needs to send supported feature set to
2295 * supplicant upon a request/query from the supplicant.
2296 *
2297 * Return: Return the Success or Failure code.
2298 */
2299static int
2300wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2301 struct wireless_dev *wdev,
2302 const void *data, int data_len)
2303{
2304 int ret;
2305
2306 cds_ssr_protect(__func__);
2307 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2308 data, data_len);
2309 cds_ssr_unprotect(__func__);
2310
2311 return ret;
2312}
2313
2314
2315/**
2316 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2317 * @wiphy: The wiphy structure
2318 * @wdev: The wireless device
2319 * @data: Data passed by framework
2320 * @data_len: Parameters to be configured passed as data
2321 *
2322 * The roaming related parameters are configured by the framework
2323 * using this interface.
2324 *
2325 * Return: Return either success or failure code.
2326 */
2327static int
2328__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2329 struct wireless_dev *wdev, const void *data, int data_len)
2330{
2331 struct net_device *dev = wdev->netdev;
2332 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2333 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2334 uint8_t session_id;
2335 struct roam_ext_params roam_params;
2336 uint32_t cmd_type, req_id;
2337 struct nlattr *curr_attr;
2338 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2339 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2340 int rem, i;
2341 uint32_t buf_len = 0;
2342 int ret;
2343
Jeff Johnson1f61b612016-02-12 16:28:33 -08002344 ENTER_DEV(dev);
2345
Anurag Chouhan6d760662016-02-20 16:05:43 +05302346 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002347 hdd_err("Command not allowed in FTM mode");
2348 return -EPERM;
2349 }
2350
2351 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302352 if (ret)
2353 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002354
2355 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2356 data, data_len,
2357 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002358 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002359 return -EINVAL;
2360 }
2361 /* Parse and fetch Command Type*/
2362 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002363 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002364 goto fail;
2365 }
2366 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302367 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002368 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2369 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002370 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002371 goto fail;
2372 }
2373 req_id = nla_get_u32(
2374 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002375 hdd_debug("Req Id (%d)", req_id);
2376 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002377 switch (cmd_type) {
2378 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2379 i = 0;
2380 nla_for_each_nested(curr_attr,
2381 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2382 rem) {
2383 if (nla_parse(tb2,
2384 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2385 nla_data(curr_attr), nla_len(curr_attr),
2386 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002387 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002388 goto fail;
2389 }
2390 /* Parse and Fetch allowed SSID list*/
2391 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002392 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002393 goto fail;
2394 }
2395 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2396 /*
2397 * Upper Layers include a null termination character.
2398 * Check for the actual permissible length of SSID and
2399 * also ensure not to copy the NULL termination
2400 * character to the driver buffer.
2401 */
2402 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2403 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2404 nla_memcpy(
2405 roam_params.ssid_allowed_list[i].ssId,
2406 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2407 buf_len - 1);
2408 roam_params.ssid_allowed_list[i].length =
2409 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002410 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002411 roam_params.ssid_allowed_list[i].length,
2412 roam_params.ssid_allowed_list[i].ssId,
2413 roam_params.ssid_allowed_list[i].length);
2414 i++;
2415 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002416 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002417 }
2418 }
2419 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002420 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002421 roam_params.num_ssid_allowed_list);
2422 sme_update_roam_params(pHddCtx->hHal, session_id,
2423 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2424 break;
2425 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2426 /* Parse and fetch 5G Boost Threshold */
2427 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002428 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002429 goto fail;
2430 }
2431 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2432 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002433 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002434 roam_params.raise_rssi_thresh_5g);
2435 /* Parse and fetch 5G Penalty Threshold */
2436 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002437 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002438 goto fail;
2439 }
2440 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2441 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002442 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443 roam_params.drop_rssi_thresh_5g);
2444 /* Parse and fetch 5G Boost Factor */
2445 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002446 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002447 goto fail;
2448 }
2449 roam_params.raise_factor_5g = nla_get_u32(
2450 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002451 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452 roam_params.raise_factor_5g);
2453 /* Parse and fetch 5G Penalty factor */
2454 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002455 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002456 goto fail;
2457 }
2458 roam_params.drop_factor_5g = nla_get_u32(
2459 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002460 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002461 roam_params.drop_factor_5g);
2462 /* Parse and fetch 5G Max Boost */
2463 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002464 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002465 goto fail;
2466 }
2467 roam_params.max_raise_rssi_5g = nla_get_u32(
2468 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002469 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002470 roam_params.max_raise_rssi_5g);
2471 /* Parse and fetch Rssi Diff */
2472 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002473 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002474 goto fail;
2475 }
2476 roam_params.rssi_diff = nla_get_s32(
2477 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002478 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 roam_params.rssi_diff);
2480 /* Parse and fetch Alert Rssi Threshold */
2481 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002482 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002483 goto fail;
2484 }
2485 roam_params.alert_rssi_threshold = nla_get_u32(
2486 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002487 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002488 roam_params.alert_rssi_threshold);
2489 sme_update_roam_params(pHddCtx->hHal, session_id,
2490 roam_params,
2491 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2492 break;
2493 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2494 /* Parse and fetch Activate Good Rssi Roam */
2495 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002496 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002497 goto fail;
2498 }
2499 roam_params.good_rssi_roam = nla_get_s32(
2500 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002501 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002502 roam_params.good_rssi_roam);
2503 sme_update_roam_params(pHddCtx->hHal, session_id,
2504 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2505 break;
2506 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2507 /* Parse and fetch number of preferred BSSID */
2508 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002509 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002510 goto fail;
2511 }
2512 roam_params.num_bssid_favored = nla_get_u32(
2513 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002514 hdd_debug("Num of Preferred BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002515 roam_params.num_bssid_favored);
2516 i = 0;
2517 nla_for_each_nested(curr_attr,
2518 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2519 rem) {
2520 if (nla_parse(tb2,
2521 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2522 nla_data(curr_attr), nla_len(curr_attr),
2523 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002524 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002525 goto fail;
2526 }
2527 /* Parse and fetch MAC address */
2528 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002529 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002530 goto fail;
2531 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002532 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002533 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302534 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002535 hdd_debug(MAC_ADDRESS_STR,
2536 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002537 /* Parse and fetch preference factor*/
2538 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002539 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002540 goto fail;
2541 }
2542 roam_params.bssid_favored_factor[i] = nla_get_u32(
2543 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002544 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545 roam_params.bssid_favored_factor[i]);
2546 i++;
2547 }
2548 sme_update_roam_params(pHddCtx->hHal, session_id,
2549 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2550 break;
2551 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2552 /* Parse and fetch number of blacklist BSSID */
2553 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002554 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002555 goto fail;
2556 }
2557 roam_params.num_bssid_avoid_list = nla_get_u32(
2558 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002559 hdd_debug("Num of blacklist BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560 roam_params.num_bssid_avoid_list);
2561 i = 0;
2562 nla_for_each_nested(curr_attr,
2563 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2564 rem) {
2565 if (nla_parse(tb2,
2566 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2567 nla_data(curr_attr), nla_len(curr_attr),
2568 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002569 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002570 goto fail;
2571 }
2572 /* Parse and fetch MAC address */
2573 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002574 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002575 goto fail;
2576 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002577 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002578 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302579 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002580 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002581 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002582 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002583 i++;
2584 }
2585 sme_update_roam_params(pHddCtx->hHal, session_id,
2586 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2587 break;
2588 }
2589 return 0;
2590fail:
2591 return -EINVAL;
2592}
2593
2594/**
2595 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2596 * @wiphy: pointer to wireless wiphy structure.
2597 * @wdev: pointer to wireless_dev structure.
2598 * @data: Pointer to the data to be passed via vendor interface
2599 * @data_len:Length of the data to be passed
2600 *
2601 * Return: Return the Success or Failure code.
2602 */
2603static int
2604wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2605 struct wireless_dev *wdev,
2606 const void *data,
2607 int data_len)
2608{
2609 int ret;
2610
2611 cds_ssr_protect(__func__);
2612 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2613 data, data_len);
2614 cds_ssr_unprotect(__func__);
2615
2616 return ret;
2617}
2618
2619static const struct nla_policy
2620wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2621 +1] = {
2622 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2623};
2624
2625/**
2626 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2627 * @hdd_ctx: HDD context
2628 * @device_mode: device mode
2629 * Return: bool
2630 */
2631static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002632 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002633{
2634 hdd_adapter_t *adapter;
2635 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2636 hdd_ap_ctx_t *ap_ctx;
2637 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302638 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002639
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302640 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002641 &adapter_node);
2642
2643 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302644 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002645 adapter = adapter_node->pAdapter;
2646
2647 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002648 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002649 ap_ctx =
2650 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2651
2652 /*
2653 * if there is SAP already running on DFS channel,
2654 * do not disable scan on dfs channels. Note that
2655 * with SAP on DFS, there cannot be conurrency on
2656 * single radio. But then we can have multiple
2657 * radios !!
2658 */
2659 if (CHANNEL_STATE_DFS ==
2660 cds_get_channel_state(
2661 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002662 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002663 return true;
2664 }
2665 }
2666
2667 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002668 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669 sta_ctx =
2670 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2671
2672 /*
2673 * if STA is already connected on DFS channel,
2674 * do not disable scan on dfs channels
2675 */
2676 if (hdd_conn_is_connected(sta_ctx) &&
2677 (CHANNEL_STATE_DFS ==
2678 cds_get_channel_state(
2679 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002680 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681 return true;
2682 }
2683 }
2684
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302685 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002686 adapter_node,
2687 &next);
2688 adapter_node = next;
2689 }
2690
2691 return false;
2692}
2693
2694/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002695 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2696 * @hdd_ctx: HDD context within host driver
2697 * @adapter: Adapter pointer
2698 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2699 *
2700 * Loops through devices to see who is operating on DFS channels
2701 * and then disables/enables DFS channels by calling SME API.
2702 * Fails the disable request if any device is active on a DFS channel.
2703 *
2704 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002706
2707int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2708 hdd_adapter_t *adapter,
2709 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002710{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002711 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302712 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002713 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002714
2715 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2716 if (no_dfs_flag) {
2717 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002718 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002719
2720 if (true == status)
2721 return -EOPNOTSUPP;
2722
2723 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002724 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002725
2726 if (true == status)
2727 return -EOPNOTSUPP;
2728 }
2729
2730 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2731
2732 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2733
2734 /*
2735 * call the SME API to tunnel down the new channel list
2736 * to the firmware
2737 */
2738 status = sme_handle_dfs_chan_scan(
2739 h_hal, hdd_ctx->config->enableDFSChnlScan);
2740
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302741 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002742 ret_val = 0;
2743
2744 /*
2745 * Clear the SME scan cache also. Note that the
2746 * clearing of scan results is independent of session;
2747 * so no need to iterate over
2748 * all sessions
2749 */
2750 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302751 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002752 ret_val = -EPERM;
2753 }
2754
2755 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002756 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002757 ret_val = 0;
2758 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002759 return ret_val;
2760}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002762/**
2763 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2764 * @wiphy: corestack handler
2765 * @wdev: wireless device
2766 * @data: data
2767 * @data_len: data length
2768 * Return: success(0) or reason code for failure
2769 */
2770static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2771 struct wireless_dev *wdev,
2772 const void *data,
2773 int data_len)
2774{
2775 struct net_device *dev = wdev->netdev;
2776 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2777 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2778 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2779 int ret_val;
2780 uint32_t no_dfs_flag = 0;
2781
Jeff Johnson1f61b612016-02-12 16:28:33 -08002782 ENTER_DEV(dev);
2783
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002784 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302785 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002786 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002787
2788 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2789 data, data_len,
2790 wlan_hdd_set_no_dfs_flag_config_policy)) {
2791 hdd_err("invalid attr");
2792 return -EINVAL;
2793 }
2794
2795 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2796 hdd_err("attr dfs flag failed");
2797 return -EINVAL;
2798 }
2799
2800 no_dfs_flag = nla_get_u32(
2801 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2802
Jeff Johnson020db452016-06-29 14:37:26 -07002803 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002804
2805 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002806 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002807 return -EINVAL;
2808 }
2809
2810 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2811 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002812 return ret_val;
2813}
2814
2815/**
2816 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2817 *
2818 * @wiphy: wiphy device pointer
2819 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002820 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002821 * @data_len: Buffer length
2822 *
2823 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2824 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2825 *
2826 * Return: EOK or other error codes.
2827 */
2828
2829static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2830 struct wireless_dev *wdev,
2831 const void *data,
2832 int data_len)
2833{
2834 int ret;
2835
2836 cds_ssr_protect(__func__);
2837 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2838 data, data_len);
2839 cds_ssr_unprotect(__func__);
2840
2841 return ret;
2842}
2843
Manikandan Mohan80dea792016-04-28 16:36:48 -07002844static const struct nla_policy
2845wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2846 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2847};
2848
2849/**
2850 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2851 * @wiphy: wiphy device pointer
2852 * @wdev: wireless device pointer
2853 * @data: Vendor command data buffer
2854 * @data_len: Buffer length
2855 *
2856 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2857 * setup WISA Mode features.
2858 *
2859 * Return: Success(0) or reason code for failure
2860 */
2861static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2862 struct wireless_dev *wdev, const void *data, int data_len)
2863{
2864 struct net_device *dev = wdev->netdev;
2865 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2866 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2867 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2868 struct sir_wisa_params wisa;
2869 int ret_val;
2870 QDF_STATUS status;
2871 bool wisa_mode;
2872
2873 ENTER_DEV(dev);
2874 ret_val = wlan_hdd_validate_context(hdd_ctx);
2875 if (ret_val)
2876 goto err;
2877
2878 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2879 hdd_err("Command not allowed in FTM mode");
2880 return -EPERM;
2881 }
2882
2883 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2884 wlan_hdd_wisa_cmd_policy)) {
2885 hdd_err("Invalid WISA cmd attributes");
2886 ret_val = -EINVAL;
2887 goto err;
2888 }
2889 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2890 hdd_err("Invalid WISA mode");
2891 ret_val = -EINVAL;
2892 goto err;
2893 }
2894
2895 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2896 hdd_info("WISA Mode: %d", wisa_mode);
2897 wisa.mode = wisa_mode;
2898 wisa.vdev_id = adapter->sessionId;
2899 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002900 if (!QDF_IS_STATUS_SUCCESS(status)) {
2901 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002902 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002903 }
2904 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
2905 ol_txrx_set_wisa_mode(ol_txrx_get_vdev_from_vdev_id(
2906 adapter->sessionId), wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002907err:
2908 EXIT();
2909 return ret_val;
2910}
2911
2912/**
2913 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2914 * @wiphy: corestack handler
2915 * @wdev: wireless device
2916 * @data: data
2917 * @data_len: data length
2918 *
2919 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2920 * setup WISA mode features.
2921 *
2922 * Return: Success(0) or reason code for failure
2923 */
2924static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2925 struct wireless_dev *wdev,
2926 const void *data,
2927 int data_len)
2928{
2929 int ret;
2930
2931 cds_ssr_protect(__func__);
2932 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2933 cds_ssr_unprotect(__func__);
2934
2935 return ret;
2936}
2937
Anurag Chouhan96919482016-07-13 16:36:57 +05302938/*
2939 * define short names for the global vendor params
2940 * used by __wlan_hdd_cfg80211_get_station_cmd()
2941 */
2942#define STATION_INVALID \
2943 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2944#define STATION_INFO \
2945 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2946#define STATION_ASSOC_FAIL_REASON \
2947 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2948#define STATION_MAX \
2949 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2950
2951static const struct nla_policy
2952hdd_get_station_policy[STATION_MAX + 1] = {
2953 [STATION_INFO] = {.type = NLA_FLAG},
2954 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2955};
2956
2957/**
2958 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2959 * @hdd_ctx: HDD context within host driver
2960 * @wdev: wireless device
2961 *
2962 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
2963 * Validate cmd attributes and send the station info to upper layers.
2964 *
2965 * Return: Success(0) or reason code for failure
2966 */
2967static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
2968 hdd_adapter_t *adapter)
2969{
2970 struct sk_buff *skb = NULL;
2971 uint32_t nl_buf_len;
2972 hdd_station_ctx_t *hdd_sta_ctx;
2973
2974 nl_buf_len = NLMSG_HDRLEN;
2975 nl_buf_len += sizeof(uint32_t);
2976 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
2977
2978 if (!skb) {
2979 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
2980 return -ENOMEM;
2981 }
2982
2983 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2984
2985 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
2986 hdd_sta_ctx->conn_info.assoc_status_code)) {
2987 hdd_err("put fail");
2988 goto fail;
2989 }
2990 return cfg80211_vendor_cmd_reply(skb);
2991fail:
2992 if (skb)
2993 kfree_skb(skb);
2994 return -EINVAL;
2995}
2996
2997/**
2998 * hdd_map_auth_type() - transform auth type specific to
2999 * vendor command
3000 * @auth_type: csr auth type
3001 *
3002 * Return: Success(0) or reason code for failure
3003 */
3004static int hdd_convert_auth_type(uint32_t auth_type)
3005{
3006 uint32_t ret_val;
3007
3008 switch (auth_type) {
3009 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3010 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3011 break;
3012 case eCSR_AUTH_TYPE_SHARED_KEY:
3013 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3014 break;
3015 case eCSR_AUTH_TYPE_WPA:
3016 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3017 break;
3018 case eCSR_AUTH_TYPE_WPA_PSK:
3019 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3020 break;
3021 case eCSR_AUTH_TYPE_AUTOSWITCH:
3022 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3023 break;
3024 case eCSR_AUTH_TYPE_WPA_NONE:
3025 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3026 break;
3027 case eCSR_AUTH_TYPE_RSN:
3028 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3029 break;
3030 case eCSR_AUTH_TYPE_RSN_PSK:
3031 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3032 break;
3033 case eCSR_AUTH_TYPE_FT_RSN:
3034 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3035 break;
3036 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3037 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3038 break;
3039 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3040 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3041 break;
3042 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3043 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3044 break;
3045 case eCSR_AUTH_TYPE_CCKM_WPA:
3046 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3047 break;
3048 case eCSR_AUTH_TYPE_CCKM_RSN:
3049 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3050 break;
3051 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3052 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3053 break;
3054 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3055 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3056 break;
3057 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3058 case eCSR_AUTH_TYPE_FAILED:
3059 case eCSR_AUTH_TYPE_NONE:
3060 default:
3061 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3062 break;
3063 }
3064 return ret_val;
3065}
3066
3067/**
3068 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3069 * vendor command
3070 * @dot11mode: dot11mode
3071 *
3072 * Return: Success(0) or reason code for failure
3073 */
3074static int hdd_convert_dot11mode(uint32_t dot11mode)
3075{
3076 uint32_t ret_val;
3077
3078 switch (dot11mode) {
3079 case eCSR_CFG_DOT11_MODE_11A:
3080 ret_val = QCA_WLAN_802_11_MODE_11A;
3081 break;
3082 case eCSR_CFG_DOT11_MODE_11B:
3083 ret_val = QCA_WLAN_802_11_MODE_11B;
3084 break;
3085 case eCSR_CFG_DOT11_MODE_11G:
3086 ret_val = QCA_WLAN_802_11_MODE_11G;
3087 break;
3088 case eCSR_CFG_DOT11_MODE_11N:
3089 ret_val = QCA_WLAN_802_11_MODE_11N;
3090 break;
3091 case eCSR_CFG_DOT11_MODE_11AC:
3092 ret_val = QCA_WLAN_802_11_MODE_11AC;
3093 break;
3094 case eCSR_CFG_DOT11_MODE_AUTO:
3095 case eCSR_CFG_DOT11_MODE_ABG:
3096 default:
3097 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3098 }
3099 return ret_val;
3100}
3101
3102/**
3103 * hdd_add_tx_bitrate() - add tx bitrate attribute
3104 * @skb: pointer to sk buff
3105 * @hdd_sta_ctx: pointer to hdd station context
3106 * @idx: attribute index
3107 *
3108 * Return: Success(0) or reason code for failure
3109 */
3110static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3111 hdd_station_ctx_t *hdd_sta_ctx,
3112 int idx)
3113{
3114 struct nlattr *nla_attr;
3115 uint32_t bitrate, bitrate_compat;
3116
3117 nla_attr = nla_nest_start(skb, idx);
3118 if (!nla_attr)
3119 goto fail;
3120 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3121 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3122
3123 /* report 16-bit bitrate only if we can */
3124 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3125 if (bitrate > 0 &&
3126 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3127 hdd_err("put fail");
3128 goto fail;
3129 }
3130 if (bitrate_compat > 0 &&
3131 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3132 hdd_err("put fail");
3133 goto fail;
3134 }
3135 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3136 hdd_sta_ctx->conn_info.txrate.nss)) {
3137 hdd_err("put fail");
3138 goto fail;
3139 }
3140 nla_nest_end(skb, nla_attr);
3141 return 0;
3142fail:
3143 return -EINVAL;
3144}
3145
3146/**
3147 * hdd_add_sta_info() - add station info attribute
3148 * @skb: pointer to sk buff
3149 * @hdd_sta_ctx: pointer to hdd station context
3150 * @idx: attribute index
3151 *
3152 * Return: Success(0) or reason code for failure
3153 */
3154static int32_t hdd_add_sta_info(struct sk_buff *skb,
3155 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3156{
3157 struct nlattr *nla_attr;
3158
3159 nla_attr = nla_nest_start(skb, idx);
3160 if (!nla_attr)
3161 goto fail;
3162 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3163 (hdd_sta_ctx->conn_info.signal + 100))) {
3164 hdd_err("put fail");
3165 goto fail;
3166 }
3167 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3168 goto fail;
3169 nla_nest_end(skb, nla_attr);
3170 return 0;
3171fail:
3172 return -EINVAL;
3173}
3174
3175/**
3176 * hdd_add_survey_info() - add survey info attribute
3177 * @skb: pointer to sk buff
3178 * @hdd_sta_ctx: pointer to hdd station context
3179 * @idx: attribute index
3180 *
3181 * Return: Success(0) or reason code for failure
3182 */
3183static int32_t hdd_add_survey_info(struct sk_buff *skb,
3184 hdd_station_ctx_t *hdd_sta_ctx,
3185 int idx)
3186{
3187 struct nlattr *nla_attr;
3188
3189 nla_attr = nla_nest_start(skb, idx);
3190 if (!nla_attr)
3191 goto fail;
3192 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3193 hdd_sta_ctx->conn_info.freq) ||
3194 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3195 (hdd_sta_ctx->conn_info.noise + 100))) {
3196 hdd_err("put fail");
3197 goto fail;
3198 }
3199 nla_nest_end(skb, nla_attr);
3200 return 0;
3201fail:
3202 return -EINVAL;
3203}
3204
3205/**
3206 * hdd_add_link_standard_info() - add link info attribute
3207 * @skb: pointer to sk buff
3208 * @hdd_sta_ctx: pointer to hdd station context
3209 * @idx: attribute index
3210 *
3211 * Return: Success(0) or reason code for failure
3212 */
3213static int32_t
3214hdd_add_link_standard_info(struct sk_buff *skb,
3215 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3216{
3217 struct nlattr *nla_attr;
3218
3219 nla_attr = nla_nest_start(skb, idx);
3220 if (!nla_attr)
3221 goto fail;
3222 if (nla_put(skb,
3223 NL80211_ATTR_SSID,
3224 hdd_sta_ctx->conn_info.SSID.SSID.length,
3225 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3226 hdd_err("put fail");
3227 goto fail;
3228 }
3229 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3230 goto fail;
3231 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3232 goto fail;
3233 nla_nest_end(skb, nla_attr);
3234 return 0;
3235fail:
3236 return -EINVAL;
3237}
3238
3239/**
3240 * hdd_add_ap_standard_info() - add ap info attribute
3241 * @skb: pointer to sk buff
3242 * @hdd_sta_ctx: pointer to hdd station context
3243 * @idx: attribute index
3244 *
3245 * Return: Success(0) or reason code for failure
3246 */
3247static int32_t
3248hdd_add_ap_standard_info(struct sk_buff *skb,
3249 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3250{
3251 struct nlattr *nla_attr;
3252
3253 nla_attr = nla_nest_start(skb, idx);
3254 if (!nla_attr)
3255 goto fail;
3256 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3257 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3258 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3259 &hdd_sta_ctx->conn_info.vht_caps)) {
3260 hdd_err("put fail");
3261 goto fail;
3262 }
3263 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3264 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3265 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3266 &hdd_sta_ctx->conn_info.ht_caps)) {
3267 hdd_err("put fail");
3268 goto fail;
3269 }
3270 nla_nest_end(skb, nla_attr);
3271 return 0;
3272fail:
3273 return -EINVAL;
3274}
3275
3276/**
3277 * hdd_get_station_info() - send BSS information to supplicant
3278 * @hdd_ctx: pointer to hdd context
3279 * @adapter: pointer to adapter
3280 *
3281 * Return: 0 if success else error status
3282 */
3283static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3284 hdd_adapter_t *adapter)
3285{
3286 struct sk_buff *skb = NULL;
3287 uint8_t *tmp_hs20 = NULL;
3288 uint32_t nl_buf_len;
3289 hdd_station_ctx_t *hdd_sta_ctx;
3290
3291 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3292
3293 nl_buf_len = NLMSG_HDRLEN;
3294 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3295 sizeof(hdd_sta_ctx->conn_info.freq) +
3296 sizeof(hdd_sta_ctx->conn_info.noise) +
3297 sizeof(hdd_sta_ctx->conn_info.signal) +
3298 (sizeof(uint32_t) * 2) +
3299 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3300 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3301 sizeof(hdd_sta_ctx->conn_info.authType) +
3302 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3303 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3304 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3305 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3306 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3307 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3308 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3309 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3310 1);
3311 }
3312 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3313 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3314 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3315 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3316
3317
3318 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3319 if (!skb) {
3320 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3321 return -ENOMEM;
3322 }
3323
3324 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3325 LINK_INFO_STANDARD_NL80211_ATTR)) {
3326 hdd_err("put fail");
3327 goto fail;
3328 }
3329 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3330 AP_INFO_STANDARD_NL80211_ATTR)) {
3331 hdd_err("put fail");
3332 goto fail;
3333 }
3334 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3335 hdd_sta_ctx->conn_info.roam_count) ||
3336 nla_put_u32(skb, INFO_AKM,
3337 hdd_convert_auth_type(
3338 hdd_sta_ctx->conn_info.authType)) ||
3339 nla_put_u32(skb, WLAN802_11_MODE,
3340 hdd_convert_dot11mode(
3341 hdd_sta_ctx->conn_info.dot11Mode))) {
3342 hdd_err("put fail");
3343 goto fail;
3344 }
3345 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3346 if (nla_put(skb, HT_OPERATION,
3347 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3348 &hdd_sta_ctx->conn_info.ht_operation)) {
3349 hdd_err("put fail");
3350 goto fail;
3351 }
3352 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3353 if (nla_put(skb, VHT_OPERATION,
3354 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3355 &hdd_sta_ctx->conn_info.vht_operation)) {
3356 hdd_err("put fail");
3357 goto fail;
3358 }
3359 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3360 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3361 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3362 tmp_hs20 + 1)) {
3363 hdd_err("put fail");
3364 goto fail;
3365 }
3366
3367 return cfg80211_vendor_cmd_reply(skb);
3368fail:
3369 if (skb)
3370 kfree_skb(skb);
3371 return -EINVAL;
3372}
3373
3374/**
3375 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3376 * @wiphy: corestack handler
3377 * @wdev: wireless device
3378 * @data: data
3379 * @data_len: data length
3380 *
3381 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3382 * Validate cmd attributes and send the station info to upper layers.
3383 *
3384 * Return: Success(0) or reason code for failure
3385 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303386static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303387__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3388 struct wireless_dev *wdev,
3389 const void *data,
3390 int data_len)
3391{
3392 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3393 struct net_device *dev = wdev->netdev;
3394 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3395 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3396 int32_t status;
3397
3398 ENTER_DEV(dev);
3399 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3400 hdd_err("Command not allowed in FTM mode");
3401 status = -EPERM;
3402 goto out;
3403 }
3404
3405 status = wlan_hdd_validate_context(hdd_ctx);
3406 if (0 != status)
3407 goto out;
3408
3409
3410 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3411 data, data_len, NULL);
3412 if (status) {
3413 hdd_err("Invalid ATTR");
3414 goto out;
3415 }
3416
3417 /* Parse and fetch Command Type*/
3418 if (tb[STATION_INFO]) {
3419 status = hdd_get_station_info(hdd_ctx, adapter);
3420 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3421 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3422 } else {
3423 hdd_err("get station info cmd type failed");
3424 status = -EINVAL;
3425 goto out;
3426 }
3427 EXIT();
3428out:
3429 return status;
3430}
3431
3432/**
3433 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3434 * @wiphy: corestack handler
3435 * @wdev: wireless device
3436 * @data: data
3437 * @data_len: data length
3438 *
3439 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3440 * Validate cmd attributes and send the station info to upper layers.
3441 *
3442 * Return: Success(0) or reason code for failure
3443 */
3444static int32_t
3445hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3446 struct wireless_dev *wdev,
3447 const void *data,
3448 int data_len)
3449{
3450 int ret;
3451
3452 cds_ssr_protect(__func__);
3453 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3454 cds_ssr_unprotect(__func__);
3455
3456 return ret;
3457}
3458
3459/*
3460 * undef short names defined for get station command
3461 * used by __wlan_hdd_cfg80211_get_station_cmd()
3462 */
3463#undef STATION_INVALID
3464#undef STATION_INFO
3465#undef STATION_ASSOC_FAIL_REASON
3466#undef STATION_MAX
3467
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003468#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3469/**
3470 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3471 * @wiphy: pointer to wireless wiphy structure.
3472 * @wdev: pointer to wireless_dev structure.
3473 * @data: Pointer to the Key data
3474 * @data_len:Length of the data passed
3475 *
3476 * This is called when wlan driver needs to save the keys received via
3477 * vendor specific command.
3478 *
3479 * Return: Return the Success or Failure code.
3480 */
3481static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3482 struct wireless_dev *wdev,
3483 const void *data, int data_len)
3484{
3485 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3486 struct net_device *dev = wdev->netdev;
3487 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3488 hdd_context_t *hdd_ctx_ptr;
3489 int status;
3490
Jeff Johnson1f61b612016-02-12 16:28:33 -08003491 ENTER_DEV(dev);
3492
Anurag Chouhan6d760662016-02-20 16:05:43 +05303493 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003494 hdd_err("Command not allowed in FTM mode");
3495 return -EPERM;
3496 }
3497
3498 if ((data == NULL) || (data_len == 0) ||
3499 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003500 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003501 return -EINVAL;
3502 }
3503
3504 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3505 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003506 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003507 return -EINVAL;
3508 }
3509
3510 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303511 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003512 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003513 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3514 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003515 true,
3516 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303517 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3518 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003519 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3520 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3521 return 0;
3522}
3523
3524/**
3525 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3526 * @wiphy: pointer to wireless wiphy structure.
3527 * @wdev: pointer to wireless_dev structure.
3528 * @data: Pointer to the Key data
3529 * @data_len:Length of the data passed
3530 *
3531 * This is called when wlan driver needs to save the keys received via
3532 * vendor specific command.
3533 *
3534 * Return: Return the Success or Failure code.
3535 */
3536static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3537 struct wireless_dev *wdev,
3538 const void *data, int data_len)
3539{
3540 int ret;
3541
3542 cds_ssr_protect(__func__);
3543 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3544 cds_ssr_unprotect(__func__);
3545
3546 return ret;
3547}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003548#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003549
3550static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3551 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3552 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3553 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003554 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003555};
3556
3557/**
3558 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3559 * @wiphy: pointer to wireless wiphy structure.
3560 * @wdev: pointer to wireless_dev structure.
3561 * @data: Pointer to the data to be passed via vendor interface
3562 * @data_len:Length of the data to be passed
3563 *
3564 * This is called when wlan driver needs to send wifi driver related info
3565 * (driver/fw version) to the user space application upon request.
3566 *
3567 * Return: Return the Success or Failure code.
3568 */
3569static int
3570__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3571 struct wireless_dev *wdev,
3572 const void *data, int data_len)
3573{
3574 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3575 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003576 tSirVersionString driver_version;
3577 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003578 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003579 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003580 struct sk_buff *reply_skb;
3581 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003582
Jeff Johnson1f61b612016-02-12 16:28:33 -08003583 ENTER_DEV(wdev->netdev);
3584
Anurag Chouhan6d760662016-02-20 16:05:43 +05303585 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003586 hdd_err("Command not allowed in FTM mode");
3587 return -EPERM;
3588 }
3589
3590 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303591 if (status)
3592 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003593
3594 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3595 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003596 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003597 return -EINVAL;
3598 }
3599
3600 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003601 hdd_err("Rcvd req for Driver version");
3602 strlcpy(driver_version, QWLAN_VERSIONSTR,
3603 sizeof(driver_version));
3604 skb_len += strlen(driver_version) + 1;
3605 count++;
3606 }
3607
3608 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3609 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003610 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3611 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003612 snprintf(firmware_version, sizeof(firmware_version),
3613 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3614 skb_len += strlen(firmware_version) + 1;
3615 count++;
3616 }
3617
3618 if (count == 0) {
3619 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003620 return -EINVAL;
3621 }
3622
Ryan Hsu7ac88852016-04-28 10:20:34 -07003623 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3624 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3625
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003626 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003627 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003628 return -ENOMEM;
3629 }
3630
Ryan Hsu7ac88852016-04-28 10:20:34 -07003631 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3632 if (nla_put_string(reply_skb,
3633 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3634 driver_version))
3635 goto error_nla_fail;
3636 }
3637
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05303638 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003639 if (nla_put_string(reply_skb,
3640 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3641 firmware_version))
3642 goto error_nla_fail;
3643 }
3644
3645 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3646 if (nla_put_u32(reply_skb,
3647 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3648 hdd_ctx->radio_index))
3649 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003650 }
3651
3652 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003653
3654error_nla_fail:
3655 hdd_err("nla put fail");
3656 kfree_skb(reply_skb);
3657 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003658}
3659
3660/**
3661 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3662 * @wiphy: pointer to wireless wiphy structure.
3663 * @wdev: pointer to wireless_dev structure.
3664 * @data: Pointer to the data to be passed via vendor interface
3665 * @data_len:Length of the data to be passed
3666 *
3667 * This is called when wlan driver needs to send wifi driver related info
3668 * (driver/fw version) to the user space application upon request.
3669 *
3670 * Return: Return the Success or Failure code.
3671 */
3672static int
3673wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3674 struct wireless_dev *wdev,
3675 const void *data, int data_len)
3676{
3677 int ret;
3678
3679 cds_ssr_protect(__func__);
3680 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3681 cds_ssr_unprotect(__func__);
3682
3683 return ret;
3684}
3685
3686/**
3687 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3688 * @wiphy: pointer to wireless wiphy structure.
3689 * @wdev: pointer to wireless_dev structure.
3690 * @data: Pointer to the data to be passed via vendor interface
3691 * @data_len:Length of the data to be passed
3692 *
3693 * This is called by userspace to know the supported logger features
3694 *
3695 * Return: Return the Success or Failure code.
3696 */
3697static int
3698__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3699 struct wireless_dev *wdev,
3700 const void *data, int data_len)
3701{
3702 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3703 int status;
3704 uint32_t features;
3705 struct sk_buff *reply_skb = NULL;
3706
Jeff Johnson1f61b612016-02-12 16:28:33 -08003707 ENTER_DEV(wdev->netdev);
3708
Anurag Chouhan6d760662016-02-20 16:05:43 +05303709 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003710 hdd_err("Command not allowed in FTM mode");
3711 return -EPERM;
3712 }
3713
3714 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303715 if (status)
3716 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003717
3718 features = 0;
3719
3720 if (hdd_is_memdump_supported())
3721 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3722 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3723 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3724 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3725
3726 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3727 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3728 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003729 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003730 return -ENOMEM;
3731 }
3732
Jeff Johnson020db452016-06-29 14:37:26 -07003733 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003734 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3735 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003736 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003737 kfree_skb(reply_skb);
3738 return -EINVAL;
3739 }
3740
3741 return cfg80211_vendor_cmd_reply(reply_skb);
3742}
3743
3744/**
3745 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3746 * @wiphy: pointer to wireless wiphy structure.
3747 * @wdev: pointer to wireless_dev structure.
3748 * @data: Pointer to the data to be passed via vendor interface
3749 * @data_len:Length of the data to be passed
3750 *
3751 * This is called by userspace to know the supported logger features
3752 *
3753 * Return: Return the Success or Failure code.
3754 */
3755static int
3756wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3757 struct wireless_dev *wdev,
3758 const void *data, int data_len)
3759{
3760 int ret;
3761
3762 cds_ssr_protect(__func__);
3763 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3764 data, data_len);
3765 cds_ssr_unprotect(__func__);
3766
3767 return ret;
3768}
3769
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003770#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003771/**
3772 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3773 * @hdd_ctx_ptr: pointer to HDD Context.
3774 * @bssid: pointer to bssid of roamed AP.
3775 * @req_rsn_ie: Pointer to request RSN IE
3776 * @req_rsn_len: Length of the request RSN IE
3777 * @rsp_rsn_ie: Pointer to response RSN IE
3778 * @rsp_rsn_len: Length of the response RSN IE
3779 * @roam_info_ptr: Pointer to the roaming related information
3780 *
3781 * This is called when wlan driver needs to send the roaming and
3782 * authorization information after roaming.
3783 *
3784 * The information that would be sent is the request RSN IE, response
3785 * RSN IE and BSSID of the newly roamed AP.
3786 *
3787 * If the Authorized status is authenticated, then additional parameters
3788 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3789 * supplicant.
3790 *
3791 * The supplicant upon receiving this event would ignore the legacy
3792 * cfg80211_roamed call and use the entire information from this event.
3793 * The cfg80211_roamed should still co-exist since the kernel will
3794 * make use of the parameters even if the supplicant ignores it.
3795 *
3796 * Return: Return the Success or Failure code.
3797 */
3798int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3799 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3800 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3801{
3802 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003803 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003804 ENTER();
3805
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303806 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003807 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003808
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003809 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003810 !roam_info_ptr->roamSynchInProgress)
3811 return 0;
3812
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003813 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3814 NULL,
3815 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3816 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3817 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003818 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003819 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3820 GFP_KERNEL);
3821
3822 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003823 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003824 return -EINVAL;
3825 }
3826
3827 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3828 ETH_ALEN, bssid) ||
3829 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3830 req_rsn_len, req_rsn_ie) ||
3831 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3832 rsp_rsn_len, rsp_rsn_ie)) {
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 }
Jeff Johnson020db452016-06-29 14:37:26 -07003836 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003837 if (roam_info_ptr->synchAuthStatus ==
3838 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003839 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003840 if (nla_put_u8(skb,
3841 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3842 hdd_err("nla put fail");
3843 goto nla_put_failure;
3844 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003845 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3846 /* if FT or CCKM connection: dont send replay counter */
3847 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3848 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3849 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3850 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3851 nla_put(skb,
3852 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3853 SIR_REPLAY_CTR_LEN,
3854 roam_info_ptr->replay_ctr)) {
3855 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003856 hdd_err("failed to send replay counter.");
3857 goto nla_put_failure;
3858 }
3859 if (nla_put(skb,
3860 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3861 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3862 nla_put(skb,
3863 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3864 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3865 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003866 goto nla_put_failure;
3867 }
3868 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003869 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003870 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3871 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003872 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003873 goto nla_put_failure;
3874 }
3875 }
3876
Jeff Johnson020db452016-06-29 14:37:26 -07003877 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003878 roam_info_ptr->subnet_change_status);
3879
3880 /*
3881 * Add subnet change status if subnet has changed
3882 * 0 = unchanged
3883 * 1 = changed
3884 * 2 = unknown
3885 */
3886 if (roam_info_ptr->subnet_change_status) {
3887 if (nla_put_u8(skb,
3888 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3889 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003890 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003891 goto nla_put_failure;
3892 }
3893 }
3894
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003895 cfg80211_vendor_event(skb, GFP_KERNEL);
3896 return 0;
3897
3898nla_put_failure:
3899 kfree_skb(skb);
3900 return -EINVAL;
3901}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003902#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003903
3904static const struct nla_policy
3905wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3906
3907 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3908 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3909 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303910 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303911 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3912 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003913 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
3914 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
3915 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
3916 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
3917 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05303918 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003919};
3920
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003921/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303922 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3923 *
3924 * @adapter: Pointer to HDD adapter
3925 * @ie_data: Pointer to Scan IEs buffer
3926 * @ie_len: Length of Scan IEs
3927 *
3928 * Return: 0 on success; error number otherwise
3929 */
3930static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3931 uint8_t *ie_data, uint8_t ie_len)
3932{
3933 hdd_scaninfo_t *scan_info = NULL;
3934 scan_info = &adapter->scan_info;
3935
3936 if (scan_info->default_scan_ies) {
3937 qdf_mem_free(scan_info->default_scan_ies);
3938 scan_info->default_scan_ies = NULL;
3939 }
3940
3941 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3942 if (!scan_info->default_scan_ies)
3943 return -ENOMEM;
3944
3945 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3946 scan_info->default_scan_ies_len = ie_len;
3947 return 0;
3948}
3949
3950/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003951 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3952 * vendor command
3953 *
3954 * @wiphy: wiphy device pointer
3955 * @wdev: wireless device pointer
3956 * @data: Vendor command data buffer
3957 * @data_len: Buffer length
3958 *
3959 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3960 *
3961 * Return: Error code.
3962 */
3963static int
3964__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3965 struct wireless_dev *wdev,
3966 const void *data,
3967 int data_len)
3968{
3969 struct net_device *dev = wdev->netdev;
3970 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3971 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3972 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3973 int ret_val = 0;
3974 u32 modulated_dtim;
3975 u16 stats_avg_factor;
3976 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303977 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003978 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07003979 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303980 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303981 int attr_len;
3982 int access_policy = 0;
3983 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3984 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303985 uint16_t scan_ie_len = 0;
3986 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303987 struct sir_set_tx_rx_aggregation_size request;
3988 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003989 uint8_t retry, delay;
3990 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05303991 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303992
Jeff Johnson1f61b612016-02-12 16:28:33 -08003993 ENTER_DEV(dev);
3994
Anurag Chouhan6d760662016-02-20 16:05:43 +05303995 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003996 hdd_err("Command not allowed in FTM mode");
3997 return -EPERM;
3998 }
3999
4000 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304001 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004002 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004003
4004 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4005 data, data_len,
4006 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004007 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004008 return -EINVAL;
4009 }
4010
Krunal Sonie3531942016-04-12 17:43:53 -07004011 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4012 ftm_capab = nla_get_u32(tb[
4013 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4014 hdd_ctx->config->fine_time_meas_cap =
4015 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4016 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304017 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004018 hdd_ctx->config->fine_time_meas_cap);
4019 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4020 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4021 hdd_ctx->config->fine_time_meas_cap);
4022 }
4023
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004024 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4025 modulated_dtim = nla_get_u32(
4026 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4027
4028 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4029 adapter->sessionId,
4030 modulated_dtim);
4031
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304032 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004033 ret_val = -EPERM;
4034 }
4035
Kapil Gupta6213c012016-09-02 19:39:09 +05304036 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4037 qpower = nla_get_u8(
4038 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4039 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4040 ret_val = -EINVAL;
4041 }
4042
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4044 stats_avg_factor = nla_get_u16(
4045 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4046 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4047 adapter->sessionId,
4048 stats_avg_factor);
4049
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304050 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004051 ret_val = -EPERM;
4052 }
4053
4054
4055 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4056 guard_time = nla_get_u32(
4057 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4058 status = sme_configure_guard_time(hdd_ctx->hHal,
4059 adapter->sessionId,
4060 guard_time);
4061
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304062 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004063 ret_val = -EPERM;
4064 }
4065
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304066 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4067 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4068 attr_len = nla_len(
4069 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4070 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4071 hdd_info("Invalid value. attr_len %d",
4072 attr_len);
4073 return -EINVAL;
4074 }
4075
4076 nla_memcpy(&vendor_ie,
4077 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4078 attr_len);
4079 vendor_ie_present = true;
4080 hdd_info("Access policy vendor ie present.attr_len %d",
4081 attr_len);
4082 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4083 &vendor_ie[0], attr_len);
4084 }
4085
4086 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4087 access_policy = (int) nla_get_u32(
4088 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4089 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4090 (access_policy >
4091 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4092 hdd_info("Invalid value. access_policy %d",
4093 access_policy);
4094 return -EINVAL;
4095 }
4096 access_policy_present = true;
4097 hdd_info("Access policy present. access_policy %d",
4098 access_policy);
4099 }
4100
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004101 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4102 retry = nla_get_u8(tb[
4103 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4104 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4105 CFG_NON_AGG_RETRY_MAX : retry;
4106 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4107 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4108 retry, PDEV_CMD);
4109 }
4110
4111 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4112 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4113 retry = retry > CFG_AGG_RETRY_MAX ?
4114 CFG_AGG_RETRY_MAX : retry;
4115
4116 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4117 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4118 CFG_AGG_RETRY_MIN : retry;
4119 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4120 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4121 retry, PDEV_CMD);
4122 }
4123
4124 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4125 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4126 retry = retry > CFG_MGMT_RETRY_MAX ?
4127 CFG_MGMT_RETRY_MAX : retry;
4128 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4129 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4130 retry, PDEV_CMD);
4131 }
4132
4133 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4134 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4135 retry = retry > CFG_CTRL_RETRY_MAX ?
4136 CFG_CTRL_RETRY_MAX : retry;
4137 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4138 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4139 retry, PDEV_CMD);
4140 }
4141
4142 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4143 delay = nla_get_u8(tb[
4144 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4145 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4146 CFG_PROPAGATION_DELAY_MAX : delay;
4147 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4148 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4149 delay, PDEV_CMD);
4150 }
4151
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304152 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4153 tx_fail_count = nla_get_u32(
4154 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4155 if (tx_fail_count) {
4156 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4157 adapter->sessionId, tx_fail_count);
4158 if (QDF_STATUS_SUCCESS != status) {
4159 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4160 status);
4161 return -EINVAL;
4162 }
4163 }
4164 }
4165
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304166 if (vendor_ie_present && access_policy_present) {
4167 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4168 access_policy =
4169 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304170 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304171 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304172 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304173
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304174 hdd_info("calling sme_update_access_policy_vendor_ie");
4175 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4176 adapter->sessionId, &vendor_ie[0],
4177 access_policy);
4178 if (QDF_STATUS_SUCCESS != status) {
4179 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304180 return -EINVAL;
4181 }
4182 }
4183
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304184 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4185 set_value = nla_get_u8(
4186 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4187 hdd_info("set_value: %d", set_value);
4188 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4189 }
4190
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304191 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4192 scan_ie_len = nla_len(
4193 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4194 hdd_info("Received default scan IE of len %d session %d device mode %d",
4195 scan_ie_len, adapter->sessionId,
4196 adapter->device_mode);
4197 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4198 scan_ie = (uint8_t *) nla_data(tb
4199 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304200
4201 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4202 scan_ie_len))
4203 hdd_err("Failed to save default scan IEs");
4204
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304205 if (adapter->device_mode == QDF_STA_MODE) {
4206 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4207 adapter->sessionId, scan_ie,
4208 scan_ie_len);
4209 if (QDF_STATUS_SUCCESS != status)
4210 ret_val = -EPERM;
4211 }
4212 } else
4213 ret_val = -EPERM;
4214 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304215
4216 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4217 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4218 /* if one is specified, both must be specified */
4219 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4220 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4221 hdd_err("Both TX and RX MPDU Aggregation required");
4222 return -EINVAL;
4223 }
4224
4225 request.tx_aggregation_size = nla_get_u8(
4226 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4227 request.rx_aggregation_size = nla_get_u8(
4228 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4229 request.vdev_id = adapter->sessionId;
4230
4231 if (request.tx_aggregation_size >=
4232 CFG_TX_AGGREGATION_SIZE_MIN &&
4233 request.tx_aggregation_size <=
4234 CFG_TX_AGGREGATION_SIZE_MAX &&
4235 request.rx_aggregation_size >=
4236 CFG_RX_AGGREGATION_SIZE_MIN &&
4237 request.rx_aggregation_size <=
4238 CFG_RX_AGGREGATION_SIZE_MAX) {
4239 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4240 if (qdf_status != QDF_STATUS_SUCCESS) {
4241 hdd_err("failed to set aggr sizes err %d",
4242 qdf_status);
4243 ret_val = -EPERM;
4244 }
4245 } else {
4246 hdd_err("TX %d RX %d MPDU aggr size not in range",
4247 request.tx_aggregation_size,
4248 request.rx_aggregation_size);
4249 ret_val = -EINVAL;
4250 }
4251 }
4252
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304253 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4254 uint8_t ignore_assoc_disallowed;
4255
4256 ignore_assoc_disallowed
4257 = nla_get_u8(tb[
4258 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4259 hdd_info("Set ignore_assoc_disallowed value - %d",
4260 ignore_assoc_disallowed);
4261 if ((ignore_assoc_disallowed <
4262 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4263 (ignore_assoc_disallowed >
4264 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4265 return -EPERM;
4266
4267 sme_update_session_param(hdd_ctx->hHal,
4268 adapter->sessionId,
4269 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4270 ignore_assoc_disallowed);
4271 }
4272
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004273 return ret_val;
4274}
4275
4276/**
4277 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4278 * vendor command
4279 *
4280 * @wiphy: wiphy device pointer
4281 * @wdev: wireless device pointer
4282 * @data: Vendor command data buffer
4283 * @data_len: Buffer length
4284 *
4285 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4286 *
4287 * Return: EOK or other error codes.
4288 */
4289static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4290 struct wireless_dev *wdev,
4291 const void *data,
4292 int data_len)
4293{
4294 int ret;
4295
4296 cds_ssr_protect(__func__);
4297 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4298 data, data_len);
4299 cds_ssr_unprotect(__func__);
4300
4301 return ret;
4302}
4303
4304static const struct
4305nla_policy
4306qca_wlan_vendor_wifi_logger_start_policy
4307[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4308 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4309 = {.type = NLA_U32 },
4310 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4311 = {.type = NLA_U32 },
4312 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4313 = {.type = NLA_U32 },
4314};
4315
4316/**
4317 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4318 * or disable the collection of packet statistics from the firmware
4319 * @wiphy: WIPHY structure pointer
4320 * @wdev: Wireless device structure pointer
4321 * @data: Pointer to the data received
4322 * @data_len: Length of the data received
4323 *
4324 * This function enables or disables the collection of packet statistics from
4325 * the firmware
4326 *
4327 * Return: 0 on success and errno on failure
4328 */
4329static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4330 struct wireless_dev *wdev,
4331 const void *data,
4332 int data_len)
4333{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304334 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4336 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4337 struct sir_wifi_start_log start_log;
4338
Jeff Johnson1f61b612016-02-12 16:28:33 -08004339 ENTER_DEV(wdev->netdev);
4340
Anurag Chouhan6d760662016-02-20 16:05:43 +05304341 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004342 hdd_err("Command not allowed in FTM mode");
4343 return -EPERM;
4344 }
4345
4346 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304347 if (status)
4348 return status;
4349
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004350
4351 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4352 data, data_len,
4353 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004354 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 return -EINVAL;
4356 }
4357
4358 /* Parse and fetch ring id */
4359 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004360 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004361 return -EINVAL;
4362 }
4363 start_log.ring_id = nla_get_u32(
4364 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004365 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004366
4367 /* Parse and fetch verbose level */
4368 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004369 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004370 return -EINVAL;
4371 }
4372 start_log.verbose_level = nla_get_u32(
4373 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004374 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375
4376 /* Parse and fetch flag */
4377 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004378 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004379 return -EINVAL;
4380 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304381 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004382 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304383 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004384
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304385 /* size is buff size which can be set using iwpriv command*/
4386 start_log.size = 0;
4387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4389
4390 if (start_log.ring_id == RING_ID_WAKELOCK) {
4391 /* Start/stop wakelock events */
4392 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4393 cds_set_wakelock_logging(true);
4394 else
4395 cds_set_wakelock_logging(false);
4396 return 0;
4397 }
4398
4399 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304400 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004401 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004402 status);
4403 return -EINVAL;
4404 }
4405 return 0;
4406}
4407
4408/**
4409 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4410 * or disable the collection of packet statistics from the firmware
4411 * @wiphy: WIPHY structure pointer
4412 * @wdev: Wireless device structure pointer
4413 * @data: Pointer to the data received
4414 * @data_len: Length of the data received
4415 *
4416 * This function is used to enable or disable the collection of packet
4417 * statistics from the firmware
4418 *
4419 * Return: 0 on success and errno on failure
4420 */
4421static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4422 struct wireless_dev *wdev,
4423 const void *data,
4424 int data_len)
4425{
4426 int ret = 0;
4427
4428 cds_ssr_protect(__func__);
4429 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4430 wdev, data, data_len);
4431 cds_ssr_unprotect(__func__);
4432
4433 return ret;
4434}
4435
4436static const struct
4437nla_policy
4438qca_wlan_vendor_wifi_logger_get_ring_data_policy
4439[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4440 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4441 = {.type = NLA_U32 },
4442};
4443
4444/**
4445 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4446 * @wiphy: WIPHY structure pointer
4447 * @wdev: Wireless device structure pointer
4448 * @data: Pointer to the data received
4449 * @data_len: Length of the data received
4450 *
4451 * This function is used to flush or retrieve the per packet statistics from
4452 * the driver
4453 *
4454 * Return: 0 on success and errno on failure
4455 */
4456static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4457 struct wireless_dev *wdev,
4458 const void *data,
4459 int data_len)
4460{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304461 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004462 uint32_t ring_id;
4463 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4464 struct nlattr *tb
4465 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4466
Jeff Johnson1f61b612016-02-12 16:28:33 -08004467 ENTER_DEV(wdev->netdev);
4468
Anurag Chouhan6d760662016-02-20 16:05:43 +05304469 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004470 hdd_err("Command not allowed in FTM mode");
4471 return -EPERM;
4472 }
4473
4474 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304475 if (status)
4476 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004477
4478 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4479 data, data_len,
4480 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004481 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004482 return -EINVAL;
4483 }
4484
4485 /* Parse and fetch ring id */
4486 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004487 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004488 return -EINVAL;
4489 }
4490
4491 ring_id = nla_get_u32(
4492 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4493
4494 if (ring_id == RING_ID_PER_PACKET_STATS) {
4495 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004496 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304497 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4498 /*
4499 * As part of DRIVER ring ID, flush both driver and fw logs.
4500 * For other Ring ID's driver doesn't have any rings to flush
4501 */
4502 hdd_notice("Bug report triggered by framework");
4503
4504 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4505 WLAN_LOG_INDICATOR_FRAMEWORK,
4506 WLAN_LOG_REASON_CODE_UNUSED,
4507 true, false);
4508 if (QDF_STATUS_SUCCESS != status) {
4509 hdd_err("Failed to trigger bug report");
4510 return -EINVAL;
4511 }
4512 } else {
4513 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4514 WLAN_LOG_INDICATOR_FRAMEWORK,
4515 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004516 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004517 return 0;
4518}
4519
4520/**
4521 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4522 * @wiphy: WIPHY structure pointer
4523 * @wdev: Wireless device structure pointer
4524 * @data: Pointer to the data received
4525 * @data_len: Length of the data received
4526 *
4527 * This function is used to flush or retrieve the per packet statistics from
4528 * the driver
4529 *
4530 * Return: 0 on success and errno on failure
4531 */
4532static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4533 struct wireless_dev *wdev,
4534 const void *data,
4535 int data_len)
4536{
4537 int ret = 0;
4538
4539 cds_ssr_protect(__func__);
4540 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4541 wdev, data, data_len);
4542 cds_ssr_unprotect(__func__);
4543
4544 return ret;
4545}
4546
4547#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4548/**
4549 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4550 * @hdd_ctx: HDD context
4551 * @request_id: [input] request id
4552 * @pattern_id: [output] pattern id
4553 *
4554 * This function loops through request id to pattern id array
4555 * if the slot is available, store the request id and return pattern id
4556 * if entry exists, return the pattern id
4557 *
4558 * Return: 0 on success and errno on failure
4559 */
4560static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4561 uint32_t request_id,
4562 uint8_t *pattern_id)
4563{
4564 uint32_t i;
4565
4566 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4567 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4568 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4569 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4570 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4571 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4572 return 0;
4573 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4574 request_id) {
4575 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4576 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4577 return 0;
4578 }
4579 }
4580 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4581 return -EINVAL;
4582}
4583
4584/**
4585 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4586 * @hdd_ctx: HDD context
4587 * @request_id: [input] request id
4588 * @pattern_id: [output] pattern id
4589 *
4590 * This function loops through request id to pattern id array
4591 * reset request id to 0 (slot available again) and
4592 * return pattern id
4593 *
4594 * Return: 0 on success and errno on failure
4595 */
4596static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4597 uint32_t request_id,
4598 uint8_t *pattern_id)
4599{
4600 uint32_t i;
4601
4602 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4603 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4604 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4605 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4606 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4607 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4608 return 0;
4609 }
4610 }
4611 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4612 return -EINVAL;
4613}
4614
4615
4616/*
4617 * define short names for the global vendor params
4618 * used by __wlan_hdd_cfg80211_offloaded_packets()
4619 */
4620#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4621#define PARAM_REQUEST_ID \
4622 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4623#define PARAM_CONTROL \
4624 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4625#define PARAM_IP_PACKET \
4626 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4627#define PARAM_SRC_MAC_ADDR \
4628 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4629#define PARAM_DST_MAC_ADDR \
4630 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4631#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4632
4633/**
4634 * wlan_hdd_add_tx_ptrn() - add tx pattern
4635 * @adapter: adapter pointer
4636 * @hdd_ctx: hdd context
4637 * @tb: nl attributes
4638 *
4639 * This function reads the NL attributes and forms a AddTxPtrn message
4640 * posts it to SME.
4641 *
4642 */
4643static int
4644wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4645 struct nlattr **tb)
4646{
4647 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304648 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004649 uint32_t request_id, ret, len;
4650 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304651 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004652 uint16_t eth_type = htons(ETH_P_IP);
4653
4654 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004655 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004656 return -ENOTSUPP;
4657 }
4658
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304659 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004660 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004661 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004662 return -ENOMEM;
4663 }
4664
4665 /* Parse and fetch request Id */
4666 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004667 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004668 goto fail;
4669 }
4670
4671 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4672 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004673 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004674 return -EINVAL;
4675 }
Jeff Johnson77848112016-06-29 14:52:06 -07004676 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004677
4678 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004679 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680 goto fail;
4681 }
4682 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004683 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004684 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004685 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004686 goto fail;
4687 }
4688
4689 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004690 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004691 goto fail;
4692 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004693 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304694 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004695 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004696 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697
Anurag Chouhanc5548422016-02-24 18:33:27 +05304698 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004699 &adapter->macAddressCurrent)) {
4700 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004701 goto fail;
4702 }
4703
4704 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004705 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004706 goto fail;
4707 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304708 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004709 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004710 MAC_ADDR_ARRAY(dst_addr.bytes));
4711
4712 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004713 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004714 goto fail;
4715 }
4716 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004717 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004718
4719 if (add_req->ucPtrnSize < 0 ||
4720 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4721 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004722 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004723 add_req->ucPtrnSize);
4724 goto fail;
4725 }
4726
4727 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304728 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304729 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304730 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304731 QDF_MAC_ADDR_SIZE);
4732 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304733 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004734 len += 2;
4735
4736 /*
4737 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4738 * ------------------------------------------------------------
4739 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4740 * ------------------------------------------------------------
4741 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304742 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004743 nla_data(tb[PARAM_IP_PACKET]),
4744 add_req->ucPtrnSize);
4745 add_req->ucPtrnSize += len;
4746
4747 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4748 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004749 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004750 goto fail;
4751 }
4752 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004753 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004754
4755 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304756 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004757 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004758 goto fail;
4759 }
4760
4761 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304762 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004763 return 0;
4764
4765fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304766 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004767 return -EINVAL;
4768}
4769
4770/**
4771 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4772 * @adapter: adapter pointer
4773 * @hdd_ctx: hdd context
4774 * @tb: nl attributes
4775 *
4776 * This function reads the NL attributes and forms a DelTxPtrn message
4777 * posts it to SME.
4778 *
4779 */
4780static int
4781wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4782 struct nlattr **tb)
4783{
4784 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304785 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004786 uint32_t request_id, ret;
4787 uint8_t pattern_id = 0;
4788
4789 /* Parse and fetch request Id */
4790 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004791 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004792 return -EINVAL;
4793 }
4794 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4795 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004796 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004797 return -EINVAL;
4798 }
4799
4800 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4801 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004802 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004803 return -EINVAL;
4804 }
4805
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304806 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004807 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004808 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004809 return -ENOMEM;
4810 }
4811
Anurag Chouhanc5548422016-02-24 18:33:27 +05304812 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004813 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004814 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004815 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004816 request_id, del_req->ucPtrnId);
4817
4818 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304819 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004820 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004821 goto fail;
4822 }
4823
4824 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304825 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004826 return 0;
4827
4828fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304829 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004830 return -EINVAL;
4831}
4832
4833
4834/**
4835 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4836 * @wiphy: Pointer to wireless phy
4837 * @wdev: Pointer to wireless device
4838 * @data: Pointer to data
4839 * @data_len: Data length
4840 *
4841 * Return: 0 on success, negative errno on failure
4842 */
4843static int
4844__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4845 struct wireless_dev *wdev,
4846 const void *data,
4847 int data_len)
4848{
4849 struct net_device *dev = wdev->netdev;
4850 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4851 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4852 struct nlattr *tb[PARAM_MAX + 1];
4853 uint8_t control;
4854 int ret;
4855 static const struct nla_policy policy[PARAM_MAX + 1] = {
4856 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4857 [PARAM_CONTROL] = { .type = NLA_U32 },
4858 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304859 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304861 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004862 [PARAM_PERIOD] = { .type = NLA_U32 },
4863 };
4864
Jeff Johnson1f61b612016-02-12 16:28:33 -08004865 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004866
Anurag Chouhan6d760662016-02-20 16:05:43 +05304867 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004868 hdd_err("Command not allowed in FTM mode");
4869 return -EPERM;
4870 }
4871
4872 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304873 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004874 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004875
4876 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004877 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004878 return -ENOTSUPP;
4879 }
4880
4881 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004882 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004883 return -EINVAL;
4884 }
4885
4886 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004887 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004888 return -EINVAL;
4889 }
4890 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004891 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004892
4893 if (control == WLAN_START_OFFLOADED_PACKETS)
4894 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4895 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4896 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4897 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004898 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004899 return -EINVAL;
4900 }
4901}
4902
4903/*
4904 * done with short names for the global vendor params
4905 * used by __wlan_hdd_cfg80211_offloaded_packets()
4906 */
4907#undef PARAM_MAX
4908#undef PARAM_REQUEST_ID
4909#undef PARAM_CONTROL
4910#undef PARAM_IP_PACKET
4911#undef PARAM_SRC_MAC_ADDR
4912#undef PARAM_DST_MAC_ADDR
4913#undef PARAM_PERIOD
4914
4915/**
4916 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4917 * @wiphy: wiphy structure pointer
4918 * @wdev: Wireless device structure pointer
4919 * @data: Pointer to the data received
4920 * @data_len: Length of @data
4921 *
4922 * Return: 0 on success; errno on failure
4923 */
4924static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4925 struct wireless_dev *wdev,
4926 const void *data,
4927 int data_len)
4928{
4929 int ret = 0;
4930
4931 cds_ssr_protect(__func__);
4932 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4933 wdev, data, data_len);
4934 cds_ssr_unprotect(__func__);
4935
4936 return ret;
4937}
4938#endif
4939
4940/*
4941 * define short names for the global vendor params
4942 * used by __wlan_hdd_cfg80211_monitor_rssi()
4943 */
4944#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4945#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4946#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4947#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4948#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4949
4950/**
4951 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4952 * @wiphy: Pointer to wireless phy
4953 * @wdev: Pointer to wireless device
4954 * @data: Pointer to data
4955 * @data_len: Data length
4956 *
4957 * Return: 0 on success, negative errno on failure
4958 */
4959static int
4960__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4961 struct wireless_dev *wdev,
4962 const void *data,
4963 int data_len)
4964{
4965 struct net_device *dev = wdev->netdev;
4966 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4967 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4968 struct nlattr *tb[PARAM_MAX + 1];
4969 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304970 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004971 int ret;
4972 uint32_t control;
4973 static const struct nla_policy policy[PARAM_MAX + 1] = {
4974 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4975 [PARAM_CONTROL] = { .type = NLA_U32 },
4976 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4977 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4978 };
4979
Jeff Johnson1f61b612016-02-12 16:28:33 -08004980 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004981
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05304982 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
4983 hdd_err("invalid session id: %d", adapter->sessionId);
4984 return -EINVAL;
4985 }
4986
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004987 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304988 if (ret)
4989 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004990
4991 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004992 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004993 return -ENOTSUPP;
4994 }
4995
4996 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004997 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004998 return -EINVAL;
4999 }
5000
5001 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005002 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005003 return -EINVAL;
5004 }
5005
5006 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005007 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005008 return -EINVAL;
5009 }
5010
5011 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5012 req.session_id = adapter->sessionId;
5013 control = nla_get_u32(tb[PARAM_CONTROL]);
5014
5015 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5016 req.control = true;
5017 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005018 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005019 return -EINVAL;
5020 }
5021
5022 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005023 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005024 return -EINVAL;
5025 }
5026
5027 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5028 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5029
5030 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005031 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005032 req.min_rssi, req.max_rssi);
5033 return -EINVAL;
5034 }
Jeff Johnson77848112016-06-29 14:52:06 -07005035 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005036 req.min_rssi, req.max_rssi);
5037
5038 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5039 req.control = false;
5040 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005041 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005042 return -EINVAL;
5043 }
Jeff Johnson77848112016-06-29 14:52:06 -07005044 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005045 req.request_id, req.session_id, req.control);
5046
5047 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305048 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005049 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005050 return -EINVAL;
5051 }
5052
5053 return 0;
5054}
5055
5056/*
5057 * done with short names for the global vendor params
5058 * used by __wlan_hdd_cfg80211_monitor_rssi()
5059 */
5060#undef PARAM_MAX
5061#undef PARAM_CONTROL
5062#undef PARAM_REQUEST_ID
5063#undef PARAM_MAX_RSSI
5064#undef PARAM_MIN_RSSI
5065
5066/**
5067 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5068 * @wiphy: wiphy structure pointer
5069 * @wdev: Wireless device structure pointer
5070 * @data: Pointer to the data received
5071 * @data_len: Length of @data
5072 *
5073 * Return: 0 on success; errno on failure
5074 */
5075static int
5076wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5077 const void *data, int data_len)
5078{
5079 int ret;
5080
5081 cds_ssr_protect(__func__);
5082 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5083 cds_ssr_unprotect(__func__);
5084
5085 return ret;
5086}
5087
5088/**
5089 * hdd_rssi_threshold_breached() - rssi breached NL event
5090 * @hddctx: HDD context
5091 * @data: rssi breached event data
5092 *
5093 * This function reads the rssi breached event %data and fill in the skb with
5094 * NL attributes and send up the NL event.
5095 *
5096 * Return: none
5097 */
5098void hdd_rssi_threshold_breached(void *hddctx,
5099 struct rssi_breach_event *data)
5100{
5101 hdd_context_t *hdd_ctx = hddctx;
5102 struct sk_buff *skb;
5103
5104 ENTER();
5105
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305106 if (wlan_hdd_validate_context(hdd_ctx))
5107 return;
5108 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005109 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005110 return;
5111 }
5112
5113 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5114 NULL,
5115 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5116 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5117 GFP_KERNEL);
5118
5119 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005120 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005121 return;
5122 }
5123
Jeff Johnson77848112016-06-29 14:52:06 -07005124 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005125 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005126 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005127 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5128
5129 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5130 data->request_id) ||
5131 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5132 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5133 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5134 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005135 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005136 goto fail;
5137 }
5138
5139 cfg80211_vendor_event(skb, GFP_KERNEL);
5140 return;
5141
5142fail:
5143 kfree_skb(skb);
5144 return;
5145}
5146
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305147static const struct nla_policy
5148ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5149 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5150};
5151
5152/**
5153 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5154 * @wiphy: Pointer to wireless phy
5155 * @wdev: Pointer to wireless device
5156 * @data: Pointer to data
5157 * @data_len: Length of @data
5158 *
5159 * Return: 0 on success, negative errno on failure
5160 */
5161static int
5162__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5163 struct wireless_dev *wdev,
5164 const void *data, int data_len)
5165{
5166 int status;
5167 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5168 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005169 struct net_device *dev = wdev->netdev;
5170 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305171
5172 ENTER_DEV(wdev->netdev);
5173
5174 status = wlan_hdd_validate_context(pHddCtx);
5175 if (0 != status)
5176 return status;
5177 if (!pHddCtx->config->fhostNSOffload) {
5178 hdd_err("ND Offload not supported");
5179 return -EINVAL;
5180 }
5181
5182 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5183 (struct nlattr *)data,
5184 data_len, ns_offload_set_policy)) {
5185 hdd_err("nla_parse failed");
5186 return -EINVAL;
5187 }
5188
5189 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5190 hdd_err("ND Offload flag attribute not present");
5191 return -EINVAL;
5192 }
5193
5194 pHddCtx->ns_offload_enable =
5195 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5196
Dustin Brownd8279d22016-09-07 14:52:57 -07005197 /* update ns offload in case it is already enabled/disabled */
5198 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5199
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305200 return 0;
5201}
5202
5203/**
5204 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5205 * @wiphy: pointer to wireless wiphy structure.
5206 * @wdev: pointer to wireless_dev structure.
5207 * @data: Pointer to the data to be passed via vendor interface
5208 * @data_len:Length of the data to be passed
5209 *
5210 * Return: Return the Success or Failure code.
5211 */
5212static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5213 struct wireless_dev *wdev,
5214 const void *data, int data_len)
5215{
5216 int ret;
5217
5218 cds_ssr_protect(__func__);
5219 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5220 cds_ssr_unprotect(__func__);
5221
5222 return ret;
5223}
5224
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005225/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5226 * @wiphy: Pointer to wireless phy
5227 * @wdev: Pointer to wireless device
5228 * @data: Pointer to data
5229 * @data_len: Data length
5230 *
5231 * This function return the preferred frequency list generated by the policy
5232 * manager.
5233 *
5234 * Return: success or failure code
5235 */
5236static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5237 struct wireless_dev
5238 *wdev, const void *data,
5239 int data_len)
5240{
5241 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5242 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305243 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305244 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005245 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305246 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247 enum cds_con_mode intf_mode;
5248 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5249 struct sk_buff *reply_skb;
5250
Jeff Johnson1f61b612016-02-12 16:28:33 -08005251 ENTER_DEV(wdev->netdev);
5252
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005253 ret = wlan_hdd_validate_context(hdd_ctx);
5254 if (ret)
5255 return -EINVAL;
5256
5257 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5258 data, data_len, NULL)) {
5259 hdd_err("Invalid ATTR");
5260 return -EINVAL;
5261 }
5262
5263 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5264 hdd_err("attr interface type failed");
5265 return -EINVAL;
5266 }
5267
5268 intf_mode = nla_get_u32(tb
5269 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5270
5271 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5272 hdd_err("Invalid interface type");
5273 return -EINVAL;
5274 }
5275
5276 hdd_debug("Userspace requested pref freq list");
5277
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305278 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5279 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305280 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005281 hdd_err("Get pcl failed");
5282 return -EINVAL;
5283 }
5284
5285 /* convert channel number to frequency */
5286 for (i = 0; i < pcl_len; i++) {
5287 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5288 freq_list[i] =
5289 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005290 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005291 else
5292 freq_list[i] =
5293 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005294 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005295 }
5296
5297 /* send the freq_list back to supplicant */
5298 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5299 sizeof(u32) *
5300 pcl_len +
5301 NLMSG_HDRLEN);
5302
5303 if (!reply_skb) {
5304 hdd_err("Allocate reply_skb failed");
5305 return -EINVAL;
5306 }
5307
5308 if (nla_put_u32(reply_skb,
5309 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5310 intf_mode) ||
5311 nla_put(reply_skb,
5312 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5313 sizeof(uint32_t) * pcl_len,
5314 freq_list)) {
5315 hdd_err("nla put fail");
5316 kfree_skb(reply_skb);
5317 return -EINVAL;
5318 }
5319
5320 return cfg80211_vendor_cmd_reply(reply_skb);
5321}
5322
5323/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5324 * @wiphy: Pointer to wireless phy
5325 * @wdev: Pointer to wireless device
5326 * @data: Pointer to data
5327 * @data_len: Data length
5328 *
5329 * This function return the preferred frequency list generated by the policy
5330 * manager.
5331 *
5332 * Return: success or failure code
5333 */
5334static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5335 struct wireless_dev
5336 *wdev, const void *data,
5337 int data_len)
5338{
5339 int ret = 0;
5340
5341 cds_ssr_protect(__func__);
5342 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5343 data, data_len);
5344 cds_ssr_unprotect(__func__);
5345
5346 return ret;
5347}
5348
5349/**
5350 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5351 * @wiphy: Pointer to wireless phy
5352 * @wdev: Pointer to wireless device
5353 * @data: Pointer to data
5354 * @data_len: Data length
5355 *
5356 * Return: 0 on success, negative errno on failure
5357 */
5358static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5359 struct wireless_dev *wdev,
5360 const void *data,
5361 int data_len)
5362{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305363 struct net_device *ndev = wdev->netdev;
5364 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005365 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5366 int ret = 0;
5367 enum cds_con_mode intf_mode;
5368 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5369 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005370
Jeff Johnson1f61b612016-02-12 16:28:33 -08005371 ENTER_DEV(ndev);
5372
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005373 ret = wlan_hdd_validate_context(hdd_ctx);
5374 if (ret)
5375 return ret;
5376
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5378 data, data_len, NULL)) {
5379 hdd_err("Invalid ATTR");
5380 return -EINVAL;
5381 }
5382
5383 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5384 hdd_err("attr interface type failed");
5385 return -EINVAL;
5386 }
5387
5388 intf_mode = nla_get_u32(tb
5389 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5390
5391 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5392 hdd_err("Invalid interface type");
5393 return -EINVAL;
5394 }
5395
5396 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5397 hdd_err("attr probable freq failed");
5398 return -EINVAL;
5399 }
5400
5401 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5402 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5403
5404 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005405 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005406 channel_hint, HW_MODE_20_MHZ)) {
5407 hdd_err("Set channel hint failed due to concurrency check");
5408 return -EINVAL;
5409 }
5410
Krunal Soni09e55032016-06-07 10:06:55 -07005411 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5412 hdd_warn("Remain On Channel Pending");
5413
Krunal Soni3091bcc2016-06-23 12:28:21 -07005414 ret = qdf_reset_connection_update();
5415 if (!QDF_IS_STATUS_SUCCESS(ret))
5416 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417
Krunal Soni3091bcc2016-06-23 12:28:21 -07005418 ret = cds_current_connections_update(adapter->sessionId,
5419 channel_hint,
5420 SIR_UPDATE_REASON_SET_OPER_CHAN);
5421 if (QDF_STATUS_E_FAILURE == ret) {
5422 /* return in the failure case */
5423 hdd_err("ERROR: connections update failed!!");
5424 return -EINVAL;
5425 }
5426
5427 if (QDF_STATUS_SUCCESS == ret) {
5428 /*
5429 * Success is the only case for which we expect hw mode
5430 * change to take place, hence we need to wait.
5431 * For any other return value it should be a pass
5432 * through
5433 */
5434 ret = qdf_wait_for_connection_update();
5435 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5436 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005437 return -EINVAL;
5438 }
5439
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005440 }
5441
5442 return 0;
5443}
5444
5445/**
5446 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5447 * @wiphy: Pointer to wireless phy
5448 * @wdev: Pointer to wireless device
5449 * @data: Pointer to data
5450 * @data_len: Data length
5451 *
5452 * Return: 0 on success, negative errno on failure
5453 */
5454static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5455 struct wireless_dev *wdev,
5456 const void *data,
5457 int data_len)
5458{
5459 int ret = 0;
5460
5461 cds_ssr_protect(__func__);
5462 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5463 data, data_len);
5464 cds_ssr_unprotect(__func__);
5465
5466 return ret;
5467}
5468
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305469static const struct
5470nla_policy
5471qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5472 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5473};
5474
5475/**
5476 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5477 * @wiphy: WIPHY structure pointer
5478 * @wdev: Wireless device structure pointer
5479 * @data: Pointer to the data received
5480 * @data_len: Length of the data received
5481 *
5482 * This function is used to get link properties like nss, rate flags and
5483 * operating frequency for the active connection with the given peer.
5484 *
5485 * Return: 0 on success and errno on failure
5486 */
5487static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5488 struct wireless_dev *wdev,
5489 const void *data,
5490 int data_len)
5491{
5492 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5493 struct net_device *dev = wdev->netdev;
5494 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5495 hdd_station_ctx_t *hdd_sta_ctx;
5496 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305497 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305498 uint32_t sta_id;
5499 struct sk_buff *reply_skb;
5500 uint32_t rate_flags = 0;
5501 uint8_t nss;
5502 uint8_t final_rate_flags = 0;
5503 uint32_t freq;
5504
Jeff Johnson1f61b612016-02-12 16:28:33 -08005505 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305506
Anurag Chouhan6d760662016-02-20 16:05:43 +05305507 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305508 hdd_err("Command not allowed in FTM mode");
5509 return -EPERM;
5510 }
5511
5512 if (0 != wlan_hdd_validate_context(hdd_ctx))
5513 return -EINVAL;
5514
5515 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5516 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005517 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305518 return -EINVAL;
5519 }
5520
5521 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005522 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305523 adapter->device_mode);
5524 return -EINVAL;
5525 }
5526
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305527 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305528 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005529 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305530 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5531
Krunal Sonib4326f22016-03-10 13:05:51 -08005532 if (adapter->device_mode == QDF_STA_MODE ||
5533 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305534 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5535 if ((hdd_sta_ctx->conn_info.connState !=
5536 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305537 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305538 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005539 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305540 MAC_ADDR_ARRAY(peer_mac));
5541 return -EINVAL;
5542 }
5543
5544 nss = hdd_sta_ctx->conn_info.nss;
5545 freq = cds_chan_to_freq(
5546 hdd_sta_ctx->conn_info.operationChannel);
5547 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005548 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5549 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305550
5551 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5552 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305553 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305554 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305555 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305556 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305557 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305558 break;
5559 }
5560
5561 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005562 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305563 MAC_ADDR_ARRAY(peer_mac));
5564 return -EINVAL;
5565 }
5566
5567 nss = adapter->aStaInfo[sta_id].nss;
5568 freq = cds_chan_to_freq(
5569 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5570 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5571 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005572 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305573 MAC_ADDR_ARRAY(peer_mac));
5574 return -EINVAL;
5575 }
5576
5577 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5578 if (rate_flags & eHAL_TX_RATE_VHT80) {
5579 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005580#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305581 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005582#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305583 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5584 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005585#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305586 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005587#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305588 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5589 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5590 } else if (rate_flags &
5591 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5592 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005593#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305594 if (rate_flags & eHAL_TX_RATE_HT40)
5595 final_rate_flags |=
5596 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005597#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305598 }
5599
5600 if (rate_flags & eHAL_TX_RATE_SGI) {
5601 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5602 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5603 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5604 }
5605 }
5606
5607 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5608 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5609
5610 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005611 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305612 return -EINVAL;
5613 }
5614
5615 if (nla_put_u8(reply_skb,
5616 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5617 nss) ||
5618 nla_put_u8(reply_skb,
5619 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5620 final_rate_flags) ||
5621 nla_put_u32(reply_skb,
5622 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5623 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005624 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305625 kfree_skb(reply_skb);
5626 return -EINVAL;
5627 }
5628
5629 return cfg80211_vendor_cmd_reply(reply_skb);
5630}
5631
5632/**
5633 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5634 * properties.
5635 * @wiphy: WIPHY structure pointer
5636 * @wdev: Wireless device structure pointer
5637 * @data: Pointer to the data received
5638 * @data_len: Length of the data received
5639 *
5640 * This function is used to get link properties like nss, rate flags and
5641 * operating frequency for the active connection with the given peer.
5642 *
5643 * Return: 0 on success and errno on failure
5644 */
5645static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5646 struct wireless_dev *wdev,
5647 const void *data,
5648 int data_len)
5649{
5650 int ret = 0;
5651
5652 cds_ssr_protect(__func__);
5653 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5654 wdev, data, data_len);
5655 cds_ssr_unprotect(__func__);
5656
5657 return ret;
5658}
5659
Peng Xu278d0122015-09-24 16:34:17 -07005660static const struct
5661nla_policy
5662qca_wlan_vendor_ota_test_policy
5663[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5664 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5665};
5666
5667/**
5668 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5669 * @wiphy: Pointer to wireless phy
5670 * @wdev: Pointer to wireless device
5671 * @data: Pointer to data
5672 * @data_len: Data length
5673 *
5674 * Return: 0 on success, negative errno on failure
5675 */
5676static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5677 struct wireless_dev *wdev,
5678 const void *data,
5679 int data_len)
5680{
5681 struct net_device *dev = wdev->netdev;
5682 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5683 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5684 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5685 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5686 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305687 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005688 uint32_t current_roam_state;
5689
Jeff Johnson1f61b612016-02-12 16:28:33 -08005690 ENTER_DEV(dev);
5691
Anurag Chouhan6d760662016-02-20 16:05:43 +05305692 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005693 hdd_err("Command not allowed in FTM mode");
5694 return -EPERM;
5695 }
5696
5697 if (0 != wlan_hdd_validate_context(hdd_ctx))
5698 return -EINVAL;
5699
5700 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5701 data, data_len,
5702 qca_wlan_vendor_ota_test_policy)) {
5703 hdd_err("invalid attr");
5704 return -EINVAL;
5705 }
5706
5707 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5708 hdd_err("attr ota test failed");
5709 return -EINVAL;
5710 }
5711
5712 ota_enable = nla_get_u8(
5713 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5714
5715 hdd_info(" OTA test enable = %d", ota_enable);
5716 if (ota_enable != 1) {
5717 hdd_err("Invalid value, only enable test mode is supported!");
5718 return -EINVAL;
5719 }
5720
5721 current_roam_state =
5722 sme_get_current_roam_state(hal, adapter->sessionId);
5723 status = sme_stop_roaming(hal, adapter->sessionId,
5724 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305725 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005726 hdd_err("Enable/Disable roaming failed");
5727 return -EINVAL;
5728 }
5729
5730 status = sme_ps_enable_disable(hal, adapter->sessionId,
5731 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305732 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005733 hdd_err("Enable/Disable power save failed");
5734 /* restore previous roaming setting */
5735 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5736 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5737 status = sme_start_roaming(hal, adapter->sessionId,
5738 eCsrHddIssued);
5739 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5740 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5741 status = sme_stop_roaming(hal, adapter->sessionId,
5742 eCsrHddIssued);
5743
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305744 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005745 hdd_err("Restoring roaming state failed");
5746
5747 return -EINVAL;
5748 }
5749
5750
5751 return 0;
5752}
5753
5754/**
5755 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5756 * @wiphy: Pointer to wireless phy
5757 * @wdev: Pointer to wireless device
5758 * @data: Pointer to data
5759 * @data_len: Data length
5760 *
5761 * Return: 0 on success, negative errno on failure
5762 */
5763static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5764 struct wireless_dev *wdev,
5765 const void *data,
5766 int data_len)
5767{
5768 int ret = 0;
5769
5770 cds_ssr_protect(__func__);
5771 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5772 cds_ssr_unprotect(__func__);
5773
5774 return ret;
5775}
5776
Peng Xu4d67c8f2015-10-16 16:02:26 -07005777/**
5778 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5779 * @wiphy: Pointer to wireless phy
5780 * @wdev: Pointer to wireless device
5781 * @data: Pointer to data
5782 * @data_len: Data length
5783 *
5784 * Return: 0 on success, negative errno on failure
5785 */
5786static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5787 struct wireless_dev *wdev,
5788 const void *data,
5789 int data_len)
5790{
5791 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5792 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005793 hdd_adapter_t *adapter;
5794 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005795 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5796 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005797 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005798
Jeff Johnson1f61b612016-02-12 16:28:33 -08005799 ENTER_DEV(dev);
5800
Peng Xu4d67c8f2015-10-16 16:02:26 -07005801 ret = wlan_hdd_validate_context(hdd_ctx);
5802 if (ret)
5803 return ret;
5804
5805 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5806
5807 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5808 data, data_len, NULL)) {
5809 hdd_err("Invalid ATTR");
5810 return -EINVAL;
5811 }
5812
5813 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5814 hdd_err("attr tx power scale failed");
5815 return -EINVAL;
5816 }
5817
5818 scale_value = nla_get_u8(tb
5819 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5820
5821 if (scale_value > MAX_TXPOWER_SCALE) {
5822 hdd_err("Invalid tx power scale level");
5823 return -EINVAL;
5824 }
5825
Peng Xu62c8c432016-05-09 15:23:02 -07005826 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005827
Peng Xu62c8c432016-05-09 15:23:02 -07005828 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005829 hdd_err("Set tx power scale failed");
5830 return -EINVAL;
5831 }
5832
5833 return 0;
5834}
5835
5836/**
5837 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5838 * @wiphy: Pointer to wireless phy
5839 * @wdev: Pointer to wireless device
5840 * @data: Pointer to data
5841 * @data_len: Data length
5842 *
5843 * Return: 0 on success, negative errno on failure
5844 */
5845static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5846 struct wireless_dev *wdev,
5847 const void *data,
5848 int data_len)
5849{
Peng Xu62c8c432016-05-09 15:23:02 -07005850 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005851
5852 cds_ssr_protect(__func__);
5853 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5854 data, data_len);
5855 cds_ssr_unprotect(__func__);
5856
5857 return ret;
5858}
5859
5860/**
5861 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5862 * @wiphy: Pointer to wireless phy
5863 * @wdev: Pointer to wireless device
5864 * @data: Pointer to data
5865 * @data_len: Data length
5866 *
5867 * Return: 0 on success, negative errno on failure
5868 */
5869static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5870 struct wireless_dev *wdev,
5871 const void *data,
5872 int data_len)
5873{
5874 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5875 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005876 hdd_adapter_t *adapter;
5877 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005878 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5879 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005880 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005881
Jeff Johnson1f61b612016-02-12 16:28:33 -08005882 ENTER_DEV(dev);
5883
Peng Xu4d67c8f2015-10-16 16:02:26 -07005884 ret = wlan_hdd_validate_context(hdd_ctx);
5885 if (ret)
5886 return ret;
5887
5888 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5889
5890 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5891 data, data_len, NULL)) {
5892 hdd_err("Invalid ATTR");
5893 return -EINVAL;
5894 }
5895
5896 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5897 hdd_err("attr tx power decrease db value failed");
5898 return -EINVAL;
5899 }
5900
5901 scale_value = nla_get_u8(tb
5902 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5903
Peng Xu62c8c432016-05-09 15:23:02 -07005904 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5905 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005906
Peng Xu62c8c432016-05-09 15:23:02 -07005907 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005908 hdd_err("Set tx power decrease db failed");
5909 return -EINVAL;
5910 }
5911
5912 return 0;
5913}
5914
5915/**
5916 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5917 * @wiphy: Pointer to wireless phy
5918 * @wdev: Pointer to wireless device
5919 * @data: Pointer to data
5920 * @data_len: Data length
5921 *
5922 * Return: 0 on success, negative errno on failure
5923 */
5924static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5925 struct wireless_dev *wdev,
5926 const void *data,
5927 int data_len)
5928{
Peng Xu62c8c432016-05-09 15:23:02 -07005929 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005930
5931 cds_ssr_protect(__func__);
5932 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5933 data, data_len);
5934 cds_ssr_unprotect(__func__);
5935
5936 return ret;
5937}
Peng Xu8fdaa492016-06-22 10:20:47 -07005938
5939/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305940 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5941 * @wiphy: Pointer to wireless phy
5942 * @wdev: Pointer to wireless device
5943 * @data: Pointer to data
5944 * @data_len: Data length
5945 *
5946 * Processes the conditional channel switch request and invokes the helper
5947 * APIs to process the channel switch request.
5948 *
5949 * Return: 0 on success, negative errno on failure
5950 */
5951static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5952 struct wireless_dev *wdev,
5953 const void *data,
5954 int data_len)
5955{
5956 int ret;
5957 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5958 struct net_device *dev = wdev->netdev;
5959 hdd_adapter_t *adapter;
5960 struct nlattr
5961 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5962 uint32_t freq_len, i;
5963 uint32_t *freq;
5964 uint8_t chans[QDF_MAX_NUM_CHAN];
5965
5966 ENTER_DEV(dev);
5967
5968 ret = wlan_hdd_validate_context(hdd_ctx);
5969 if (ret)
5970 return ret;
5971
5972 if (!hdd_ctx->config->enableDFSMasterCap) {
5973 hdd_err("DFS master capability is not present in the driver");
5974 return -EINVAL;
5975 }
5976
5977 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5978 hdd_err("Command not allowed in FTM mode");
5979 return -EPERM;
5980 }
5981
5982 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5983 if (adapter->device_mode != QDF_SAP_MODE) {
5984 hdd_err("Invalid device mode %d", adapter->device_mode);
5985 return -EINVAL;
5986 }
5987
5988 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
5989 data, data_len, NULL)) {
5990 hdd_err("Invalid ATTR");
5991 return -EINVAL;
5992 }
5993
5994 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
5995 hdd_err("Frequency list is missing");
5996 return -EINVAL;
5997 }
5998
5999 freq_len = nla_len(
6000 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6001 sizeof(uint32_t);
6002
6003 if (freq_len > QDF_MAX_NUM_CHAN) {
6004 hdd_err("insufficient space to hold channels");
6005 return -ENOMEM;
6006 }
6007
6008 hdd_debug("freq_len=%d", freq_len);
6009
6010 freq = nla_data(
6011 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6012
6013
6014 for (i = 0; i < freq_len; i++) {
6015 if (freq[i] == 0)
6016 chans[i] = 0;
6017 else
6018 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6019
6020 hdd_debug("freq[%d]=%d", i, freq[i]);
6021 }
6022
6023 /*
6024 * The input frequency list from user space is designed to be a
6025 * priority based frequency list. This is only to accommodate any
6026 * future request. But, current requirement is only to perform CAC
6027 * on a single channel. So, the first entry from the list is picked.
6028 *
6029 * If channel is zero, any channel in the available outdoor regulatory
6030 * domain will be selected.
6031 */
6032 ret = wlan_hdd_request_pre_cac(chans[0]);
6033 if (ret) {
6034 hdd_err("pre cac request failed with reason:%d", ret);
6035 return ret;
6036 }
6037
6038 return 0;
6039}
6040
6041/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006042 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6043 * @wiphy: Pointer to wireless phy
6044 * @wdev: Pointer to wireless device
6045 * @data: Pointer to data
6046 * @data_len: Data length
6047 *
6048 * This function is to process the p2p listen offload start vendor
6049 * command. It parses the input parameters and invoke WMA API to
6050 * send the command to firmware.
6051 *
6052 * Return: 0 on success, negative errno on failure
6053 */
6054static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6055 struct wireless_dev *wdev,
6056 const void *data,
6057 int data_len)
6058{
6059 int ret;
6060 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6061 struct net_device *dev = wdev->netdev;
6062 hdd_adapter_t *adapter;
6063 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6064 struct sir_p2p_lo_start params;
6065 QDF_STATUS status;
6066
6067 ENTER_DEV(dev);
6068
6069 ret = wlan_hdd_validate_context(hdd_ctx);
6070 if (ret)
6071 return ret;
6072
6073 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6074 hdd_err("Command not allowed in FTM mode");
6075 return -EPERM;
6076 }
6077
6078 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6079 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6080 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6081 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6082 hdd_err("Invalid device mode %d", adapter->device_mode);
6083 return -EINVAL;
6084 }
6085
6086 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6087 data, data_len, NULL)) {
6088 hdd_err("Invalid ATTR");
6089 return -EINVAL;
6090 }
6091
6092 memset(&params, 0, sizeof(params));
6093
6094 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6095 params.ctl_flags = 1; /* set to default value */
6096 else
6097 params.ctl_flags = nla_get_u32(tb
6098 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6099
6100 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6101 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6102 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6103 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6104 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6105 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6106 hdd_err("Attribute parsing failed");
6107 return -EINVAL;
6108 }
6109
6110 params.vdev_id = adapter->sessionId;
6111 params.freq = nla_get_u32(tb
6112 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6113 if ((params.freq != 2412) && (params.freq != 2437) &&
6114 (params.freq != 2462)) {
6115 hdd_err("Invalid listening channel: %d", params.freq);
6116 return -EINVAL;
6117 }
6118
6119 params.period = nla_get_u32(tb
6120 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6121 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6122 hdd_err("Invalid period: %d", params.period);
6123 return -EINVAL;
6124 }
6125
6126 params.interval = nla_get_u32(tb
6127 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6128 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6129 hdd_err("Invalid interval: %d", params.interval);
6130 return -EINVAL;
6131 }
6132
6133 params.count = nla_get_u32(tb
6134 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
6135 if (!((params.count > 0) && (params.count < UINT_MAX))) {
6136 hdd_err("Invalid count: %d", params.count);
6137 return -EINVAL;
6138 }
6139
6140 params.device_types = nla_data(tb
6141 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6142 if (params.device_types == NULL) {
6143 hdd_err("Invalid device types");
6144 return -EINVAL;
6145 }
6146
6147 params.dev_types_len = nla_len(tb
6148 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6149 if (params.dev_types_len < 8) {
6150 hdd_err("Invalid device type length: %d", params.dev_types_len);
6151 return -EINVAL;
6152 }
6153
6154 params.probe_resp_tmplt = nla_data(tb
6155 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6156 if (params.probe_resp_tmplt == NULL) {
6157 hdd_err("Invalid probe response template");
6158 return -EINVAL;
6159 }
6160
6161 params.probe_resp_len = nla_len(tb
6162 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6163 if (params.probe_resp_len == 0) {
6164 hdd_err("Invalid probe resp template length: %d",
6165 params.probe_resp_len);
6166 return -EINVAL;
6167 }
6168
6169 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6170 params.freq, params.period, params.interval, params.count);
6171
6172 status = wma_p2p_lo_start(&params);
6173
6174 if (!QDF_IS_STATUS_SUCCESS(status)) {
6175 hdd_err("P2P LO start failed");
6176 return -EINVAL;
6177 }
6178
6179 return 0;
6180}
6181
6182
6183/**
6184 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6185 * @wiphy: Pointer to wireless phy
6186 * @wdev: Pointer to wireless device
6187 * @data: Pointer to data
6188 * @data_len: Data length
6189 *
6190 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6191 * to process p2p listen offload start vendor command.
6192 *
6193 * Return: 0 on success, negative errno on failure
6194 */
6195static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6196 struct wireless_dev *wdev,
6197 const void *data,
6198 int data_len)
6199{
6200 int ret = 0;
6201
6202 cds_ssr_protect(__func__);
6203 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6204 data, data_len);
6205 cds_ssr_unprotect(__func__);
6206
6207 return ret;
6208}
6209
6210/**
6211 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6212 * @wiphy: Pointer to wireless phy
6213 * @wdev: Pointer to wireless device
6214 * @data: Pointer to data
6215 * @data_len: Data length
6216 *
6217 * This function is to process the p2p listen offload stop vendor
6218 * command. It invokes WMA API to send command to firmware.
6219 *
6220 * Return: 0 on success, negative errno on failure
6221 */
6222static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6223 struct wireless_dev *wdev,
6224 const void *data,
6225 int data_len)
6226{
6227 QDF_STATUS status;
6228 hdd_adapter_t *adapter;
6229 struct net_device *dev = wdev->netdev;
6230
6231 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6232 hdd_err("Command not allowed in FTM mode");
6233 return -EPERM;
6234 }
6235
6236 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6237 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6238 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6239 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6240 hdd_err("Invalid device mode");
6241 return -EINVAL;
6242 }
6243
6244 status = wma_p2p_lo_stop(adapter->sessionId);
6245
6246 if (!QDF_IS_STATUS_SUCCESS(status)) {
6247 hdd_err("P2P LO stop failed");
6248 return -EINVAL;
6249 }
6250
6251 return 0;
6252}
6253
6254/**
6255 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6256 * @wiphy: Pointer to wireless phy
6257 * @wdev: Pointer to wireless device
6258 * @data: Pointer to data
6259 * @data_len: Data length
6260 *
6261 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6262 * to process p2p listen offload stop vendor command.
6263 *
6264 * Return: 0 on success, negative errno on failure
6265 */
6266static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6267 struct wireless_dev *wdev,
6268 const void *data,
6269 int data_len)
6270{
6271 int ret = 0;
6272
6273 cds_ssr_protect(__func__);
6274 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6275 data, data_len);
6276 cds_ssr_unprotect(__func__);
6277
6278 return ret;
6279}
6280
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306281/**
6282 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6283 * @wiphy: Pointer to wireless phy
6284 * @wdev: Pointer to wireless device
6285 * @data: Pointer to data
6286 * @data_len: Data length
6287 *
6288 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6289 * to process the conditional channel switch request.
6290 *
6291 * Return: 0 on success, negative errno on failure
6292 */
6293static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6294 struct wireless_dev *wdev,
6295 const void *data,
6296 int data_len)
6297{
6298 int ret;
6299
6300 cds_ssr_protect(__func__);
6301 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6302 data, data_len);
6303 cds_ssr_unprotect(__func__);
6304
6305 return ret;
6306}
6307
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306308/*
6309 * define short names for the global vendor params
6310 * used by __wlan_hdd_cfg80211_bpf_offload()
6311 */
6312#define BPF_INVALID \
6313 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6314#define BPF_SET_RESET \
6315 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6316#define BPF_VERSION \
6317 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6318#define BPF_FILTER_ID \
6319 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6320#define BPF_PACKET_SIZE \
6321 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6322#define BPF_CURRENT_OFFSET \
6323 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6324#define BPF_PROGRAM \
6325 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6326#define BPF_MAX \
6327 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006328
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306329static const struct nla_policy
6330wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6331 [BPF_SET_RESET] = {.type = NLA_U32},
6332 [BPF_VERSION] = {.type = NLA_U32},
6333 [BPF_FILTER_ID] = {.type = NLA_U32},
6334 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6335 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6336 [BPF_PROGRAM] = {.type = NLA_U8},
6337};
6338
6339/**
6340 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6341 * @hdd_context: hdd_context
6342 * @bpf_get_offload: struct for get offload
6343 *
6344 * This function receives the response/data from the lower layer and
6345 * checks to see if the thread is still waiting then post the results to
6346 * upper layer, if the request has timed out then ignore.
6347 *
6348 * Return: None
6349 */
6350void hdd_get_bpf_offload_cb(void *hdd_context,
6351 struct sir_bpf_get_offload *data)
6352{
6353 hdd_context_t *hdd_ctx = hdd_context;
6354 struct hdd_bpf_context *context;
6355
6356 ENTER();
6357
6358 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006359 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306360 data);
6361 return;
6362 }
6363
6364 spin_lock(&hdd_context_lock);
6365
6366 context = &bpf_context;
6367 /* The caller presumably timed out so there is nothing we can do */
6368 if (context->magic != BPF_CONTEXT_MAGIC) {
6369 spin_unlock(&hdd_context_lock);
6370 return;
6371 }
6372
6373 /* context is valid so caller is still waiting */
6374 /* paranoia: invalidate the magic */
6375 context->magic = 0;
6376
6377 context->capability_response = *data;
6378 complete(&context->completion);
6379
6380 spin_unlock(&hdd_context_lock);
6381
6382 return;
6383}
6384
6385/**
6386 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6387 * @hdd_context: hdd_context
6388 * @bpf_get_offload: struct for get offload
6389 *
6390 * Return: 0 on success, error number otherwise.
6391 */
6392static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6393 struct sir_bpf_get_offload *bpf_get_offload)
6394{
6395 struct sk_buff *skb;
6396 uint32_t nl_buf_len;
6397
6398 ENTER();
6399
6400 nl_buf_len = NLMSG_HDRLEN;
6401 nl_buf_len +=
6402 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6403 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6404
6405 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6406 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006407 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306408 return -ENOMEM;
6409 }
6410
Jeff Johnson77848112016-06-29 14:52:06 -07006411 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306412 bpf_get_offload->bpf_version,
6413 bpf_get_offload->max_bytes_for_bpf_inst);
6414
6415 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6416 bpf_get_offload->max_bytes_for_bpf_inst) ||
6417 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006418 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306419 goto nla_put_failure;
6420 }
6421
6422 cfg80211_vendor_cmd_reply(skb);
6423 EXIT();
6424 return 0;
6425
6426nla_put_failure:
6427 kfree_skb(skb);
6428 return -EINVAL;
6429}
6430
6431/**
6432 * hdd_get_bpf_offload - Get BPF offload Capabilities
6433 * @hdd_ctx: Hdd context
6434 *
6435 * Return: 0 on success, errno on failure
6436 */
6437static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6438{
6439 unsigned long rc;
6440 struct hdd_bpf_context *context;
6441 QDF_STATUS status;
6442 int ret;
6443
6444 ENTER();
6445
6446 spin_lock(&hdd_context_lock);
6447 context = &bpf_context;
6448 context->magic = BPF_CONTEXT_MAGIC;
6449 INIT_COMPLETION(context->completion);
6450 spin_unlock(&hdd_context_lock);
6451
6452 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6453 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006454 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306455 return -EINVAL;
6456 }
6457 /* request was sent -- wait for the response */
6458 rc = wait_for_completion_timeout(&context->completion,
6459 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6460 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006461 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306462 spin_lock(&hdd_context_lock);
6463 context->magic = 0;
6464 spin_unlock(&hdd_context_lock);
6465
6466 return -ETIMEDOUT;
6467 }
6468 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6469 &bpf_context.capability_response);
6470 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006471 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306472
6473 EXIT();
6474 return ret;
6475}
6476
6477/**
6478 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6479 * @hdd_ctx: Hdd context
6480 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306481 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306482 *
6483 * Return: 0 on success; errno on failure
6484 */
6485static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6486 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306487 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306488{
6489 struct sir_bpf_set_offload *bpf_set_offload;
6490 QDF_STATUS status;
6491 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306492 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306493
6494 ENTER();
6495
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306496 if (adapter->device_mode == QDF_STA_MODE ||
6497 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6498 if (!hdd_conn_is_connected(
6499 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6500 hdd_err("Not in Connected state!");
6501 return -ENOTSUPP;
6502 }
6503 }
6504
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306505 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6506 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006507 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306508 return -ENOMEM;
6509 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306510
6511 /* Parse and fetch bpf packet size */
6512 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006513 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306514 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306515 goto fail;
6516 }
6517 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6518
6519 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006520 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306521 goto post_sme;
6522 }
6523
6524 /* Parse and fetch bpf program */
6525 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006526 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306527 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306528 goto fail;
6529 }
6530
6531 prog_len = nla_len(tb[BPF_PROGRAM]);
6532 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306533
6534 if (bpf_set_offload->program == NULL) {
6535 hdd_err("qdf_mem_malloc failed for bpf offload program");
6536 ret = -ENOMEM;
6537 goto fail;
6538 }
6539
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306540 bpf_set_offload->current_length = prog_len;
6541 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306542 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306543
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306544 hdd_info("BPF set instructions");
6545 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6546 bpf_set_offload->program, prog_len);
6547
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306548 /* Parse and fetch filter Id */
6549 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006550 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306551 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306552 goto fail;
6553 }
6554 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6555
6556 /* Parse and fetch current offset */
6557 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006558 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306559 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306560 goto fail;
6561 }
6562 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6563
6564post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006565 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 +05306566 bpf_set_offload->session_id,
6567 bpf_set_offload->version,
6568 bpf_set_offload->filter_id,
6569 bpf_set_offload->total_length,
6570 bpf_set_offload->current_length,
6571 bpf_set_offload->current_offset);
6572
6573 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6574 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006575 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306576 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306577 goto fail;
6578 }
6579 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306580
6581fail:
6582 if (bpf_set_offload->current_length)
6583 qdf_mem_free(bpf_set_offload->program);
6584 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306585 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306586}
6587
6588/**
6589 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6590 * @wiphy: wiphy structure pointer
6591 * @wdev: Wireless device structure pointer
6592 * @data: Pointer to the data received
6593 * @data_len: Length of @data
6594 *
6595 * Return: 0 on success; errno on failure
6596 */
6597static int
6598__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6599 struct wireless_dev *wdev,
6600 const void *data, int data_len)
6601{
6602 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6603 struct net_device *dev = wdev->netdev;
6604 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6605 struct nlattr *tb[BPF_MAX + 1];
6606 int ret_val, packet_filter_subcmd;
6607
6608 ENTER();
6609
6610 ret_val = wlan_hdd_validate_context(hdd_ctx);
6611 if (ret_val)
6612 return ret_val;
6613
6614 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006615 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306616 return -EINVAL;
6617 }
6618
6619 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006620 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306621 return -ENOTSUPP;
6622 }
6623
6624 if (nla_parse(tb, BPF_MAX, data, data_len,
6625 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006626 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306627 return -EINVAL;
6628 }
6629
6630 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006631 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306632 return -EINVAL;
6633 }
6634
6635 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6636
6637 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6638 return hdd_get_bpf_offload(hdd_ctx);
6639 else
6640 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306641 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306642}
6643
6644/**
6645 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6646 * @wiphy: wiphy structure pointer
6647 * @wdev: Wireless device structure pointer
6648 * @data: Pointer to the data received
6649 * @data_len: Length of @data
6650 *
6651 * Return: 0 on success; errno on failure
6652 */
6653
6654static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6655 struct wireless_dev *wdev,
6656 const void *data, int data_len)
6657{
6658 int ret;
6659
6660 cds_ssr_protect(__func__);
6661 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6662 cds_ssr_unprotect(__func__);
6663
6664 return ret;
6665}
6666
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306667/**
6668 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6669 * @pre_cac_adapter: AP adapter used for pre cac
6670 * @status: Status (true or false)
6671 * @handle: Global handle
6672 *
6673 * Sets the status of pre cac i.e., whether the pre cac is active or not
6674 *
6675 * Return: Zero on success, non-zero on failure
6676 */
6677static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6678 bool status, tHalHandle handle)
6679{
6680 QDF_STATUS ret;
6681
6682 ret = wlan_sap_set_pre_cac_status(
6683 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6684 if (QDF_IS_STATUS_ERROR(ret))
6685 return -EINVAL;
6686
6687 return 0;
6688}
6689
6690/**
6691 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6692 * @ap_adapter: AP adapter
6693 * @chan_before_pre_cac: Channel
6694 *
6695 * Saves the channel which the AP was beaconing on before moving to the pre
6696 * cac channel. If radar is detected on the pre cac channel, this saved
6697 * channel will be used for AP operations.
6698 *
6699 * Return: Zero on success, non-zero on failure
6700 */
6701static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6702 uint8_t chan_before_pre_cac)
6703{
6704 QDF_STATUS ret;
6705
6706 ret = wlan_sap_set_chan_before_pre_cac(
6707 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6708 if (QDF_IS_STATUS_ERROR(ret))
6709 return -EINVAL;
6710
6711 return 0;
6712}
6713
6714/**
6715 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6716 * @ap_adapter: AP adapter
6717 * @nol: Non-occupancy list
6718 * @nol_len: Length of NOL
6719 *
6720 * Get the NOL for SAP
6721 *
6722 * Return: Zero on success, non-zero on failure
6723 */
6724static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6725 uint32_t *nol_len)
6726{
6727 QDF_STATUS ret;
6728
6729 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6730 nol, nol_len);
6731 if (QDF_IS_STATUS_ERROR(ret))
6732 return -EINVAL;
6733
6734 return 0;
6735}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306736
6737/**
6738 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6739 * @hdd_ctx: HDD context
6740 * @ap_adapter: AP adapter
6741 * @channel: Channel requested by userspace
6742 * @pre_cac_chan: Pointer to the pre CAC channel
6743 *
6744 * Validates the channel provided by userspace. If user provided channel 0,
6745 * a valid outdoor channel must be selected from the regulatory channel.
6746 *
6747 * Return: Zero on success and non zero value on error
6748 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006749static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6750 hdd_adapter_t *ap_adapter,
6751 uint8_t channel,
6752 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306753{
6754 uint32_t i, j;
6755 QDF_STATUS status;
6756 int ret;
6757 uint8_t nol[QDF_MAX_NUM_CHAN];
6758 uint32_t nol_len = 0, weight_len = 0;
6759 bool found;
6760 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6761 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6762 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6763
6764 if (0 == channel) {
6765 /* Channel is not obtained from PCL because PCL may not have
6766 * the entire channel list. For example: if SAP is up on
6767 * channel 6 and PCL is queried for the next SAP interface,
6768 * if SCC is preferred, the PCL will contain only the channel
6769 * 6. But, we are in need of a DFS channel. So, going with the
6770 * first channel from the valid channel list.
6771 */
6772 status = cds_get_valid_chans(channel_list, &len);
6773 if (QDF_IS_STATUS_ERROR(status)) {
6774 hdd_err("Failed to get channel list");
6775 return -EINVAL;
6776 }
6777 cds_update_with_safe_channel_list(channel_list, &len,
6778 pcl_weights, weight_len);
6779 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6780 for (i = 0; i < len; i++) {
6781 found = false;
6782 for (j = 0; j < nol_len; j++) {
6783 if (channel_list[i] == nol[j]) {
6784 found = true;
6785 break;
6786 }
6787 }
6788 if (found)
6789 continue;
6790 if (CDS_IS_DFS_CH(channel_list[i])) {
6791 *pre_cac_chan = channel_list[i];
6792 break;
6793 }
6794 }
6795 if (*pre_cac_chan == 0) {
6796 hdd_err("unable to find outdoor channel");
6797 return -EINVAL;
6798 }
6799 } else {
6800 /* Only when driver selects a channel, check is done for
6801 * unnsafe and NOL channels. When user provides a fixed channel
6802 * the user is expected to take care of this.
6803 */
6804 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6805 !CDS_IS_DFS_CH(channel)) {
6806 hdd_err("Invalid channel for pre cac:%d", channel);
6807 return -EINVAL;
6808 } else {
6809 *pre_cac_chan = channel;
6810 }
6811 }
6812 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6813 return 0;
6814}
6815
6816/**
6817 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6818 * @channel: Channel option provided by userspace
6819 *
6820 * Sets the driver to the required hardware mode and start an adapater for
6821 * pre CAC which will mimic an AP.
6822 *
6823 * Return: Zero on success, non-zero value on error
6824 */
6825int wlan_hdd_request_pre_cac(uint8_t channel)
6826{
6827 uint8_t pre_cac_chan = 0;
6828 hdd_context_t *hdd_ctx;
6829 int ret;
6830 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6831 hdd_ap_ctx_t *hdd_ap_ctx;
6832 QDF_STATUS status;
6833 struct wiphy *wiphy;
6834 struct net_device *dev;
6835 struct cfg80211_chan_def chandef;
6836 enum nl80211_channel_type channel_type;
6837 uint32_t freq;
6838 struct ieee80211_channel *chan;
6839 tHalHandle handle;
6840 bool val;
6841
6842 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6843 if (0 != wlan_hdd_validate_context(hdd_ctx))
6844 return -EINVAL;
6845
6846 if (cds_get_connection_count() > 1) {
6847 hdd_err("pre cac not allowed in concurrency");
6848 return -EINVAL;
6849 }
6850
6851 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6852 if (!ap_adapter) {
6853 hdd_err("unable to get SAP adapter");
6854 return -EINVAL;
6855 }
6856
6857 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6858 if (!handle) {
6859 hdd_err("Invalid handle");
6860 return -EINVAL;
6861 }
6862
6863 val = wlan_sap_is_pre_cac_active(handle);
6864 if (val) {
6865 hdd_err("pre cac is already in progress");
6866 return -EINVAL;
6867 }
6868
6869 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6870 if (!hdd_ap_ctx) {
6871 hdd_err("SAP context is NULL");
6872 return -EINVAL;
6873 }
6874
6875 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6876 hdd_err("SAP is already on DFS channel:%d",
6877 hdd_ap_ctx->operatingChannel);
6878 return -EINVAL;
6879 }
6880
6881 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6882 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6883 hdd_ap_ctx->operatingChannel);
6884 return -EINVAL;
6885 }
6886
6887 hdd_info("channel:%d", channel);
6888
6889 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6890 &pre_cac_chan);
6891 if (ret != 0)
6892 return ret;
6893
6894 /* Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
6895 * connection update should result in DBS mode
6896 */
6897 status = cds_update_and_wait_for_connection_update(
6898 ap_adapter->sessionId,
6899 pre_cac_chan,
6900 SIR_UPDATE_REASON_PRE_CAC);
6901 if (QDF_IS_STATUS_ERROR(status)) {
6902 hdd_err("error in moving to DBS mode");
6903 return -EINVAL;
6904 }
6905
6906 hdd_debug("starting pre cac SAP adapter");
6907
6908 /* Starting a SAP adapter:
6909 * Instead of opening an adapter, we could just do a SME open session
6910 * for AP type. But, start BSS would still need an adapter.
6911 * So, this option is not taken.
6912 *
6913 * hdd open adapter is going to register this precac interface with
6914 * user space. This interface though exposed to user space will be in
6915 * DOWN state. Consideration was done to avoid this registration to the
6916 * user space. But, as part of SAP operations multiple events are sent
6917 * to user space. Some of these events received from unregistered
6918 * interface was causing crashes. So, retaining the registration.
6919 *
6920 * So, this interface would remain registered and will remain in DOWN
6921 * state for the CAC duration. We will add notes in the feature
6922 * announcement to not use this temporary interface for any activity
6923 * from user space.
6924 */
6925 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
6926 wlan_hdd_get_intf_addr(hdd_ctx),
6927 NET_NAME_UNKNOWN, true);
6928 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306929 hdd_err("error opening the pre cac adapter");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306930 return -EINVAL;
6931 }
6932
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306933 /*
6934 * This interface is internally created by the driver. So, no interface
6935 * up comes for this interface from user space and hence starting
6936 * the adapter internally.
6937 */
6938 if (hdd_start_adapter(pre_cac_adapter)) {
6939 hdd_err("error starting the pre cac adapter");
6940 goto close_pre_cac_adapter;
6941 }
6942
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306943 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6944
6945 wiphy = hdd_ctx->wiphy;
6946 dev = pre_cac_adapter->dev;
6947
6948 /* Since this is only a dummy interface lets us use the IEs from the
6949 * other active SAP interface. In regular scenarios, these IEs would
6950 * come from the user space entity
6951 */
6952 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6953 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6954 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6955 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306956 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306957 }
6958 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6959 ap_adapter->sessionCtx.ap.beacon,
6960 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6961 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6962 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6963 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6964 ap_adapter->sessionCtx.ap.sapConfig.authType;
6965
6966 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6967 * to operate on the same bandwidth as that of the 2.4GHz operations.
6968 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6969 */
6970 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6971 case CH_WIDTH_20MHZ:
6972 channel_type = NL80211_CHAN_HT20;
6973 break;
6974 case CH_WIDTH_40MHZ:
6975 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6976 ap_adapter->sessionCtx.ap.sapConfig.channel)
6977 channel_type = NL80211_CHAN_HT40PLUS;
6978 else
6979 channel_type = NL80211_CHAN_HT40MINUS;
6980 break;
6981 default:
6982 channel_type = NL80211_CHAN_NO_HT;
6983 break;
6984 }
6985
6986 freq = cds_chan_to_freq(pre_cac_chan);
6987 chan = __ieee80211_get_channel(wiphy, freq);
6988 if (!chan) {
6989 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306990 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306991 }
6992
6993 cfg80211_chandef_create(&chandef, chan, channel_type);
6994
6995 hdd_debug("orig width:%d channel_type:%d freq:%d",
6996 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
6997 channel_type, freq);
6998
6999 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7000 if (0 != ret) {
7001 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307002 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307003 }
7004
7005 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7006 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
7007 eHIDDEN_SSID_NOT_IN_USE, false);
7008 if (QDF_IS_STATUS_ERROR(status)) {
7009 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307010 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307011 }
7012
7013 /*
7014 * The pre cac status is set here. But, it would not be reset explicitly
7015 * anywhere, since after the pre cac success/failure, the pre cac
7016 * adapter itself would be removed.
7017 */
7018 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7019 if (0 != ret) {
7020 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307021 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307022 }
7023
7024 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7025 hdd_ap_ctx->operatingChannel);
7026 if (0 != ret) {
7027 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307028 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307029 }
7030
7031 ap_adapter->pre_cac_chan = pre_cac_chan;
7032
7033 return 0;
7034
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307035stop_close_pre_cac_adapter:
7036 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307037 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7038 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307039close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307040 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
7041 return -EINVAL;
7042}
7043
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307044/**
7045 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7046 *
7047 * Return: None
7048 */
7049void hdd_init_bpf_completion(void)
7050{
7051 init_completion(&bpf_context.completion);
7052}
7053
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307054static const struct nla_policy
7055wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7056 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7057};
7058
Agrawal Ashish65634612016-08-18 13:24:32 +05307059static const struct nla_policy
7060wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7061 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7062 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7063};
7064
7065/**
7066 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7067 * @wiphy: Pointer to wireless phy
7068 * @wdev: Pointer to wireless device
7069 * @data: Pointer to data
7070 * @data_len: Length of @data
7071 *
7072 * This function parses the incoming NL vendor command data attributes and
7073 * updates the SAP context about channel_hint and DFS mode.
7074 * If channel_hint is set, SAP will choose that channel
7075 * as operating channel.
7076 *
7077 * If DFS mode is enabled, driver will include DFS channels
7078 * in ACS else driver will skip DFS channels.
7079 *
7080 * Return: 0 on success, negative errno on failure
7081 */
7082static int
7083__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7084 struct wireless_dev *wdev,
7085 const void *data, int data_len)
7086{
7087 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7088 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7089 int ret;
7090 struct acs_dfs_policy *acs_policy;
7091 int mode = DFS_MODE_NONE;
7092 int channel_hint = 0;
7093
7094 ENTER_DEV(wdev->netdev);
7095
7096 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7097 hdd_err("Command not allowed in FTM mode");
7098 return -EINVAL;
7099 }
7100
7101 ret = wlan_hdd_validate_context(hdd_ctx);
7102 if (0 != ret)
7103 return ret;
7104
7105 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7106 data, data_len,
7107 wlan_hdd_set_acs_dfs_config_policy)) {
7108 hdd_err("invalid attr");
7109 return -EINVAL;
7110 }
7111
7112 acs_policy = &hdd_ctx->acs_policy;
7113 /*
7114 * SCM sends this attribute to restrict SAP from choosing
7115 * DFS channels from ACS.
7116 */
7117 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7118 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7119
7120 if (!IS_DFS_MODE_VALID(mode)) {
7121 hdd_err("attr acs dfs mode is not valid");
7122 return -EINVAL;
7123 }
7124 acs_policy->acs_dfs_mode = mode;
7125
7126 /*
7127 * SCM sends this attribute to provide an active channel,
7128 * to skip redundant ACS between drivers, and save driver start up time
7129 */
7130 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7131 channel_hint = nla_get_u8(
7132 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7133
7134 if (!IS_CHANNEL_VALID(channel_hint)) {
7135 hdd_err("acs channel is not valid");
7136 return -EINVAL;
7137 }
7138 acs_policy->acs_channel = channel_hint;
7139
7140 return 0;
7141}
7142
7143/**
7144 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7145 * @wiphy: wiphy structure pointer
7146 * @wdev: Wireless device structure pointer
7147 * @data: Pointer to the data received
7148 * @data_len: Length of @data
7149 *
7150 * This function parses the incoming NL vendor command data attributes and
7151 * updates the SAP context about channel_hint and DFS mode.
7152 *
7153 * Return: 0 on success; errno on failure
7154 */
7155static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7156 struct wireless_dev *wdev,
7157 const void *data, int data_len)
7158{
7159 int ret;
7160
7161 cds_ssr_protect(__func__);
7162 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7163 cds_ssr_unprotect(__func__);
7164
7165 return ret;
7166}
7167
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307168/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307169 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7170 * @mode : cfg80211 dfs mode
7171 *
7172 * Return: return csr sta roam dfs mode else return NONE
7173 */
7174static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7175 enum dfs_mode mode)
7176{
7177 switch (mode) {
7178 case DFS_MODE_ENABLE:
7179 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7180 break;
7181 case DFS_MODE_DISABLE:
7182 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7183 break;
7184 case DFS_MODE_DEPRIORITIZE:
7185 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7186 break;
7187 default:
7188 hdd_err("STA Roam policy dfs mode is NONE");
7189 return CSR_STA_ROAM_POLICY_NONE;
7190 }
7191}
7192
7193static const struct nla_policy
7194wlan_hdd_set_sta_roam_config_policy[
7195QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7196 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7197 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7198};
7199
7200/**
7201 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7202 * for station connection or roaming.
7203 * @wiphy: Pointer to wireless phy
7204 * @wdev: Pointer to wireless device
7205 * @data: Pointer to data
7206 * @data_len: Length of @data
7207 *
7208 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7209 * channels needs to be skipped in scanning or not.
7210 * If dfs_mode is disabled, driver will not scan DFS channels.
7211 * If skip_unsafe_channels is set, driver will skip unsafe channels
7212 * in Scanning.
7213 *
7214 * Return: 0 on success, negative errno on failure
7215 */
7216static int
7217__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7218 struct wireless_dev *wdev,
7219 const void *data, int data_len)
7220{
7221 struct net_device *dev = wdev->netdev;
7222 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7223 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7224 struct nlattr *tb[
7225 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7226 int ret;
7227 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7228 enum dfs_mode mode = DFS_MODE_NONE;
7229 bool skip_unsafe_channels = false;
7230 QDF_STATUS status;
7231
7232 ENTER_DEV(dev);
7233
7234 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7235 hdd_err("Command not allowed in FTM mode");
7236 return -EINVAL;
7237 }
7238
7239 ret = wlan_hdd_validate_context(hdd_ctx);
7240 if (0 != ret)
7241 return ret;
7242 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7243 data, data_len,
7244 wlan_hdd_set_sta_roam_config_policy)) {
7245 hdd_err("invalid attr");
7246 return -EINVAL;
7247 }
7248 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7249 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7250 if (!IS_DFS_MODE_VALID(mode)) {
7251 hdd_err("attr sta roam dfs mode policy is not valid");
7252 return -EINVAL;
7253 }
7254
7255 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7256
7257 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7258 skip_unsafe_channels = nla_get_u8(
7259 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7260
7261 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7262 skip_unsafe_channels, adapter->sessionId);
7263
7264 if (!QDF_IS_STATUS_SUCCESS(status)) {
7265 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7266 return -EINVAL;
7267 }
7268 return 0;
7269}
7270
7271/**
7272 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7273 * connection and roaming for station.
7274 * @wiphy: wiphy structure pointer
7275 * @wdev: Wireless device structure pointer
7276 * @data: Pointer to the data received
7277 * @data_len: Length of @data
7278 *
7279 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7280 * channels needs to be skipped in scanning or not.
7281 * If dfs_mode is disabled, driver will not scan DFS channels.
7282 * If skip_unsafe_channels is set, driver will skip unsafe channels
7283 * in Scanning.
7284 * Return: 0 on success; errno on failure
7285 */
7286static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7287 struct wireless_dev *wdev,
7288 const void *data, int data_len)
7289{
7290 int ret;
7291
7292 cds_ssr_protect(__func__);
7293 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7294 cds_ssr_unprotect(__func__);
7295
7296 return ret;
7297}
7298
Agrawal Ashish467dde42016-09-08 18:44:22 +05307299#ifdef FEATURE_WLAN_CH_AVOID
7300/**
7301 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7302 * is on unsafe channel.
7303 * @wiphy: wiphy structure pointer
7304 * @wdev: Wireless device structure pointer
7305 * @data: Pointer to the data received
7306 * @data_len: Length of @data
7307 *
7308 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7309 * on any of unsafe channels.
7310 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7311 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7312 *
7313 * Return: 0 on success; errno on failure
7314 */
7315static int
7316__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7317 struct wireless_dev *wdev,
7318 const void *data, int data_len)
7319{
7320 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7321 int ret;
7322 uint16_t unsafe_channel_count;
7323 int unsafe_channel_index;
7324 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7325
7326 ENTER_DEV(wdev->netdev);
7327
7328 if (!qdf_ctx) {
7329 cds_err("qdf_ctx is NULL");
7330 return -EINVAL;
7331 }
7332
7333 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7334 hdd_err("Command not allowed in FTM mode");
7335 return -EINVAL;
7336 }
7337
7338 ret = wlan_hdd_validate_context(hdd_ctx);
7339 if (0 != ret)
7340 return ret;
7341 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7342 &(hdd_ctx->unsafe_channel_count),
7343 sizeof(hdd_ctx->unsafe_channel_list));
7344
7345 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7346 (uint16_t)NUM_CHANNELS);
7347 for (unsafe_channel_index = 0;
7348 unsafe_channel_index < unsafe_channel_count;
7349 unsafe_channel_index++) {
7350 hdd_info("Channel %d is not safe",
7351 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7352 }
7353 hdd_unsafe_channel_restart_sap(hdd_ctx);
7354 return 0;
7355}
7356
7357/**
7358 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7359 * is on unsafe channel.
7360 * @wiphy: wiphy structure pointer
7361 * @wdev: Wireless device structure pointer
7362 * @data: Pointer to the data received
7363 * @data_len: Length of @data
7364 *
7365 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7366 * on any of unsafe channels.
7367 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7368 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7369 *
7370 * Return: 0 on success; errno on failure
7371 */
7372static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7373 struct wireless_dev *wdev,
7374 const void *data, int data_len)
7375{
7376 int ret;
7377
7378 cds_ssr_protect(__func__);
7379 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7380 cds_ssr_unprotect(__func__);
7381
7382 return ret;
7383}
7384
7385#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307386/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307387 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7388 * SAP is on unsafe channel.
7389 * @wiphy: wiphy structure pointer
7390 * @wdev: Wireless device structure pointer
7391 * @data: Pointer to the data received
7392 * @data_len: Length of @data
7393 *
7394 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7395 * driver.
7396 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7397 * will initiate restart of sap.
7398 *
7399 * Return: 0 on success; errno on failure
7400 */
7401static int
7402__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7403 struct wireless_dev *wdev,
7404 const void *data, int data_len)
7405{
7406 struct net_device *ndev = wdev->netdev;
7407 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7408 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7409 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7410 uint8_t config_channel = 0;
7411 hdd_ap_ctx_t *ap_ctx;
7412 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307413 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307414
7415 ENTER();
7416
7417 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007418 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307419 return -EINVAL;
7420 }
7421
7422 ret = wlan_hdd_validate_context(hdd_ctx);
7423 if (0 != ret)
7424 return -EINVAL;
7425
7426 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7427 data, data_len,
7428 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007429 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307430 return -EINVAL;
7431 }
7432
7433 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7434 if (!test_bit(SOFTAP_BSS_STARTED,
7435 &hostapd_adapter->event_flags)) {
7436 hdd_err("SAP is not started yet. Restart sap will be invalid");
7437 return -EINVAL;
7438 }
7439
7440 config_channel =
7441 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7442
7443 if (!((IS_24G_CH(config_channel)) ||
7444 (IS_5G_CH(config_channel)))) {
7445 hdd_err("Channel %d is not valid to restart SAP",
7446 config_channel);
7447 return -ENOTSUPP;
7448 }
7449
7450 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7451 ap_ctx->sapConfig.channel = config_channel;
7452 ap_ctx->sapConfig.ch_params.ch_width =
7453 ap_ctx->sapConfig.ch_width_orig;
7454
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007455 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307456 ap_ctx->sapConfig.sec_ch,
7457 &ap_ctx->sapConfig.ch_params);
7458
7459 cds_restart_sap(hostapd_adapter);
7460 }
7461
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307462 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7463 uint32_t freq_len, i;
7464 uint32_t *freq;
7465 uint8_t chans[QDF_MAX_NUM_CHAN];
7466
7467 hdd_debug("setting mandatory freq/chan list");
7468
7469 freq_len = nla_len(
7470 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7471 sizeof(uint32_t);
7472
7473 if (freq_len > QDF_MAX_NUM_CHAN) {
7474 hdd_err("insufficient space to hold channels");
7475 return -ENOMEM;
7476 }
7477
7478 freq = nla_data(
7479 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7480
7481 hdd_debug("freq_len=%d", freq_len);
7482
7483 for (i = 0; i < freq_len; i++) {
7484 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7485 hdd_debug("freq[%d]=%d", i, freq[i]);
7486 }
7487
7488 status = cds_set_sap_mandatory_channels(chans, freq_len);
7489 if (QDF_IS_STATUS_ERROR(status))
7490 return -EINVAL;
7491 }
7492
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307493 return 0;
7494}
7495
7496/**
7497 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7498 * @wiphy: wiphy structure pointer
7499 * @wdev: Wireless device structure pointer
7500 * @data: Pointer to the data received
7501 * @data_len: Length of @data
7502 *
7503 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7504 * driver.
7505 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7506 * will initiate restart of sap.
7507 *
7508 * Return: 0 on success; errno on failure
7509 */
7510static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7511 struct wireless_dev *wdev,
7512 const void *data, int data_len)
7513{
7514 int ret;
7515
7516 cds_ssr_protect(__func__);
7517 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7518 wdev, data, data_len);
7519 cds_ssr_unprotect(__func__);
7520
7521 return ret;
7522}
7523
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307524#undef BPF_INVALID
7525#undef BPF_SET_RESET
7526#undef BPF_VERSION
7527#undef BPF_ID
7528#undef BPF_PACKET_SIZE
7529#undef BPF_CURRENT_OFFSET
7530#undef BPF_PROGRAM
7531#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307532
7533/**
7534 * define short names for the global vendor params
7535 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7536 */
7537#define PARAM_TOTAL_CMD_EVENT_WAKE \
7538 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7539#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7540 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7541#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7542 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7543#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7544 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7545#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7546 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7547#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7548 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7549#define PARAM_TOTAL_RX_DATA_WAKE \
7550 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7551#define PARAM_RX_UNICAST_CNT \
7552 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7553#define PARAM_RX_MULTICAST_CNT \
7554 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7555#define PARAM_RX_BROADCAST_CNT \
7556 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7557#define PARAM_ICMP_PKT \
7558 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7559#define PARAM_ICMP6_PKT \
7560 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7561#define PARAM_ICMP6_RA \
7562 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7563#define PARAM_ICMP6_NA \
7564 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7565#define PARAM_ICMP6_NS \
7566 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7567#define PARAM_ICMP4_RX_MULTICAST_CNT \
7568 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7569#define PARAM_ICMP6_RX_MULTICAST_CNT \
7570 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7571#define PARAM_OTHER_RX_MULTICAST_CNT \
7572 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
7573
7574
7575/**
7576 * hdd_send_wakelock_stats() - API to send wakelock stats
7577 * @ctx: context to be passed to callback
7578 * @data: data passed to callback
7579 *
7580 * This function is used to send wake lock stats to HAL layer
7581 *
7582 * Return: 0 on success, error number otherwise.
7583 */
7584static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7585 const struct sir_wake_lock_stats *data)
7586{
7587 struct sk_buff *skb;
7588 uint32_t nl_buf_len;
7589 uint32_t total_rx_data_wake, rx_multicast_cnt;
7590 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307591 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307592
7593 ENTER();
7594
7595 nl_buf_len = NLMSG_HDRLEN;
7596 nl_buf_len +=
7597 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7598 (NLMSG_HDRLEN + sizeof(uint32_t));
7599
7600 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7601
7602 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007603 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307604 return -ENOMEM;
7605 }
7606
Jeff Johnson64943bd2016-08-23 13:14:06 -07007607 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307608 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007609 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307610 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007611 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307612 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007613 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307614 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007615 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307616 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007617 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307618 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007619 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307620 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007621 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7622 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307623 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307624
7625 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307626 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307627
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307628 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307629 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307630
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307631 rx_multicast_cnt =
7632 data->wow_ipv4_mcast_wake_up_count +
7633 ipv6_rx_multicast_addr_cnt;
7634
7635 total_rx_data_wake =
7636 data->wow_ucast_wake_up_count +
7637 data->wow_bcast_wake_up_count +
7638 rx_multicast_cnt;
7639
7640 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7641 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7642 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7643 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7644 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7645 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7646 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7647 total_rx_data_wake) ||
7648 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7649 data->wow_ucast_wake_up_count) ||
7650 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7651 rx_multicast_cnt) ||
7652 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7653 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307654 nla_put_u32(skb, PARAM_ICMP_PKT,
7655 data->wow_icmpv4_count) ||
7656 nla_put_u32(skb, PARAM_ICMP6_PKT,
7657 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307658 nla_put_u32(skb, PARAM_ICMP6_RA,
7659 data->wow_ipv6_mcast_ra_stats) ||
7660 nla_put_u32(skb, PARAM_ICMP6_NA,
7661 data->wow_ipv6_mcast_na_stats) ||
7662 nla_put_u32(skb, PARAM_ICMP6_NS,
7663 data->wow_ipv6_mcast_ns_stats) ||
7664 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7665 data->wow_ipv4_mcast_wake_up_count) ||
7666 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7667 ipv6_rx_multicast_addr_cnt) ||
7668 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007669 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307670 goto nla_put_failure;
7671 }
7672
7673 cfg80211_vendor_cmd_reply(skb);
7674
7675 EXIT();
7676 return 0;
7677
7678nla_put_failure:
7679 kfree_skb(skb);
7680 return -EINVAL;
7681}
7682
7683/**
7684 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7685 * @wiphy: wiphy pointer
7686 * @wdev: pointer to struct wireless_dev
7687 * @data: pointer to incoming NL vendor data
7688 * @data_len: length of @data
7689 *
7690 * This function parses the incoming NL vendor command data attributes and
7691 * invokes the SME Api and blocks on a completion variable.
7692 * WMA copies required data and invokes callback
7693 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7694 *
7695 * Return: 0 on success; error number otherwise.
7696 */
7697static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7698 struct wireless_dev *wdev,
7699 const void *data,
7700 int data_len)
7701{
7702 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7703 int status, ret;
7704 struct sir_wake_lock_stats wake_lock_stats;
7705 QDF_STATUS qdf_status;
7706
7707 ENTER();
7708
7709 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007710 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307711 return -EINVAL;
7712 }
7713
7714 status = wlan_hdd_validate_context(hdd_ctx);
7715 if (0 != status)
7716 return -EINVAL;
7717
7718 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7719 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007720 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307721 return -EINVAL;
7722 }
7723
7724 ret = hdd_send_wakelock_stats(hdd_ctx,
7725 &wake_lock_stats);
7726 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007727 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307728
7729 EXIT();
7730 return ret;
7731}
7732
7733/**
7734 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7735 * @wiphy: wiphy pointer
7736 * @wdev: pointer to struct wireless_dev
7737 * @data: pointer to incoming NL vendor data
7738 * @data_len: length of @data
7739 *
7740 * This function parses the incoming NL vendor command data attributes and
7741 * invokes the SME Api and blocks on a completion variable.
7742 * WMA copies required data and invokes callback
7743 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7744 *
7745 * Return: 0 on success; error number otherwise.
7746 */
7747static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7748 struct wireless_dev *wdev,
7749 const void *data, int data_len)
7750{
7751 int ret;
7752
7753 cds_ssr_protect(__func__);
7754 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7755 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007756 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307757
7758 return ret;
7759}
7760
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307761/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307762 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7763 * @wiphy: wiphy structure pointer
7764 * @wdev: Wireless device structure pointer
7765 * @data: Pointer to the data received
7766 * @data_len: Length of @data
7767 *
7768 * This function reads wmi max bus size and fill in the skb with
7769 * NL attributes and send up the NL event.
7770 * Return: 0 on success; errno on failure
7771 */
7772static int
7773__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7774 struct wireless_dev *wdev,
7775 const void *data, int data_len)
7776{
7777 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7778 int ret_val;
7779 struct sk_buff *skb;
7780 uint32_t nl_buf_len;
7781
7782 ENTER();
7783
7784 ret_val = wlan_hdd_validate_context(hdd_ctx);
7785 if (ret_val)
7786 return ret_val;
7787
7788 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7789 hdd_err("Command not allowed in FTM mode");
7790 return -EINVAL;
7791 }
7792
7793 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7794
7795 nl_buf_len = NLMSG_HDRLEN;
7796 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7797
7798 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7799 if (!skb) {
7800 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7801 return -ENOMEM;
7802 }
7803
7804 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7805 hdd_ctx->wmi_max_len)) {
7806 hdd_err("nla put failure");
7807 goto nla_put_failure;
7808 }
7809
7810 cfg80211_vendor_cmd_reply(skb);
7811
7812 EXIT();
7813
7814 return 0;
7815
7816nla_put_failure:
7817 kfree_skb(skb);
7818 return -EINVAL;
7819}
7820
7821/**
7822 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7823 * @wiphy: wiphy structure pointer
7824 * @wdev: Wireless device structure pointer
7825 * @data: Pointer to the data received
7826 * @data_len: Length of @data
7827 *
7828 * Return: 0 on success; errno on failure
7829 */
7830static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7831 struct wireless_dev *wdev,
7832 const void *data, int data_len)
7833{
7834 int ret;
7835
7836 cds_ssr_protect(__func__);
7837 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7838 cds_ssr_unprotect(__func__);
7839
7840 return ret;
7841}
7842
7843/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307844 *__wlan_hdd_cfg80211_setband() - set band
7845 * @wiphy: Pointer to wireless phy
7846 * @wdev: Pointer to wireless device
7847 * @data: Pointer to data
7848 * @data_len: Length of @data
7849 *
7850 * Return: 0 on success, negative errno on failure
7851 */
7852static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7853 struct wireless_dev *wdev,
7854 const void *data, int data_len)
7855{
7856 struct net_device *dev = wdev->netdev;
7857 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7858 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7859 int ret;
7860 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7861 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7862
7863 ENTER();
7864
7865 ret = wlan_hdd_validate_context(hdd_ctx);
7866 if (ret)
7867 return ret;
7868
7869 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7870 hdd_err(FL("Invalid ATTR"));
7871 return -EINVAL;
7872 }
7873
7874 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7875 hdd_err(FL("attr SETBAND_VALUE failed"));
7876 return -EINVAL;
7877 }
7878
7879 ret = hdd_set_band(dev,
7880 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7881
7882 EXIT();
7883 return ret;
7884}
7885
7886/**
7887 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7888 * @wiphy: wiphy structure pointer
7889 * @wdev: Wireless device structure pointer
7890 * @data: Pointer to the data received
7891 * @data_len: Length of @data
7892 *
7893 * Return: 0 on success; errno on failure
7894 */
7895static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7896 struct wireless_dev *wdev,
7897 const void *data, int data_len)
7898{
7899 int ret;
7900
7901 cds_ssr_protect(__func__);
7902 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7903 cds_ssr_unprotect(__func__);
7904
7905 return ret;
7906}
7907
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307908static const struct
7909nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7910 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7911 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7912 .len = QDF_MAC_ADDR_SIZE},
7913};
7914
7915/**
7916 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7917 * @wiphy: Pointer to wireless phy
7918 * @wdev: Pointer to wireless device
7919 * @data: Pointer to data
7920 * @data_len: Length of @data
7921 *
7922 * This function is used to enable/disable roaming using vendor commands
7923 *
7924 * Return: 0 on success, negative errno on failure
7925 */
7926static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7927 struct wireless_dev *wdev,
7928 const void *data, int data_len)
7929{
7930 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7931 struct net_device *dev = wdev->netdev;
7932 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7933 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7934 uint32_t is_fast_roam_enabled;
7935 int ret;
7936
7937 ENTER_DEV(dev);
7938
7939 ret = wlan_hdd_validate_context(hdd_ctx);
7940 if (0 != ret)
7941 return ret;
7942
7943 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7944 hdd_err("Command not allowed in FTM mode");
7945 return -EINVAL;
7946 }
7947
7948 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
7949 qca_wlan_vendor_attr);
7950 if (ret) {
7951 hdd_err("Invalid ATTR");
7952 return -EINVAL;
7953 }
7954
7955 /* Parse and fetch Enable flag */
7956 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
7957 hdd_err("attr enable failed");
7958 return -EINVAL;
7959 }
7960
7961 is_fast_roam_enabled = nla_get_u32(
7962 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
7963 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
7964
7965 /* Update roaming */
7966 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
7967 is_fast_roam_enabled);
7968 if (ret)
7969 hdd_err("sme_config_fast_roaming failed");
7970 EXIT();
7971 return ret;
7972}
7973
7974/**
7975 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7976 * @wiphy: Pointer to wireless phy
7977 * @wdev: Pointer to wireless device
7978 * @data: Pointer to data
7979 * @data_len: Length of @data
7980 *
7981 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
7982 *
7983 * Return: 0 on success, negative errno on failure
7984 */
7985static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7986 struct wireless_dev *wdev,
7987 const void *data, int data_len)
7988{
7989 int ret;
7990
7991 cds_ssr_protect(__func__);
7992 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
7993 cds_ssr_unprotect(__func__);
7994
7995 return ret;
7996}
7997
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007998const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
7999 {
8000 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8001 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
8002 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05308003 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008004 .doit = is_driver_dfs_capable
8005 },
8006
8007#ifdef WLAN_FEATURE_NAN
8008 {
8009 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8010 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
8011 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8012 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8013 .doit = wlan_hdd_cfg80211_nan_request
8014 },
8015#endif
8016
8017#ifdef WLAN_FEATURE_STATS_EXT
8018 {
8019 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8020 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
8021 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8022 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8023 .doit = wlan_hdd_cfg80211_stats_ext_request
8024 },
8025#endif
8026#ifdef FEATURE_WLAN_EXTSCAN
8027 {
8028 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8029 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
8030 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8031 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8032 .doit = wlan_hdd_cfg80211_extscan_start
8033 },
8034 {
8035 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8036 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
8037 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8038 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8039 .doit = wlan_hdd_cfg80211_extscan_stop
8040 },
8041 {
8042 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8043 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8044 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8045 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8046 },
8047 {
8048 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8049 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8050 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8051 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8052 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8053 },
8054 {
8055 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8056 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8057 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8058 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8059 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8060 },
8061 {
8062 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8063 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8064 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8065 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8066 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8067 },
8068 {
8069 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8070 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8071 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8072 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8073 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8074 },
8075 {
8076 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8077 .info.subcmd =
8078 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8079 .flags =
8080 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8081 WIPHY_VENDOR_CMD_NEED_RUNNING,
8082 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8083 },
8084 {
8085 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8086 .info.subcmd =
8087 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8088 .flags =
8089 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8090 WIPHY_VENDOR_CMD_NEED_RUNNING,
8091 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8092 },
8093 {
8094 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8095 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8096 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8097 WIPHY_VENDOR_CMD_NEED_NETDEV |
8098 WIPHY_VENDOR_CMD_NEED_RUNNING,
8099 .doit = wlan_hdd_cfg80211_set_epno_list
8100 },
8101#endif /* FEATURE_WLAN_EXTSCAN */
8102
8103#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8104 {
8105 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8106 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8107 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8108 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8109 .doit = wlan_hdd_cfg80211_ll_stats_clear
8110 },
8111
8112 {
8113 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8114 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8115 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8116 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8117 .doit = wlan_hdd_cfg80211_ll_stats_set
8118 },
8119
8120 {
8121 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8122 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8123 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8124 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8125 .doit = wlan_hdd_cfg80211_ll_stats_get
8126 },
8127#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8128#ifdef FEATURE_WLAN_TDLS
8129 {
8130 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8131 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8132 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8133 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8134 .doit = wlan_hdd_cfg80211_exttdls_enable
8135 },
8136 {
8137 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8138 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8139 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8140 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8141 .doit = wlan_hdd_cfg80211_exttdls_disable
8142 },
8143 {
8144 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8145 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8146 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8147 .doit = wlan_hdd_cfg80211_exttdls_get_status
8148 },
8149#endif
8150 {
8151 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8152 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8153 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8154 .doit = wlan_hdd_cfg80211_get_supported_features
8155 },
8156 {
8157 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8158 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8159 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8160 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8161 },
8162 {
8163 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8164 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8165 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308166 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008167 },
8168 {
8169 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8170 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8171 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8172 WIPHY_VENDOR_CMD_NEED_NETDEV,
8173 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8174 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008175 {
8176 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8177 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8178 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8179 WIPHY_VENDOR_CMD_NEED_NETDEV,
8180 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8181 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008182 {
8183 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308184 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8185 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8186 WIPHY_VENDOR_CMD_NEED_NETDEV |
8187 WIPHY_VENDOR_CMD_NEED_RUNNING,
8188 .doit = hdd_cfg80211_get_station_cmd
8189 },
8190 {
8191 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008192 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8193 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8194 WIPHY_VENDOR_CMD_NEED_NETDEV |
8195 WIPHY_VENDOR_CMD_NEED_RUNNING,
8196 .doit = wlan_hdd_cfg80211_do_acs
8197 },
8198
8199 {
8200 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8201 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8202 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8203 WIPHY_VENDOR_CMD_NEED_NETDEV,
8204 .doit = wlan_hdd_cfg80211_get_features
8205 },
8206#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8207 {
8208 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8209 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8210 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8211 WIPHY_VENDOR_CMD_NEED_NETDEV |
8212 WIPHY_VENDOR_CMD_NEED_RUNNING,
8213 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8214 },
8215#endif
8216#ifdef FEATURE_WLAN_EXTSCAN
8217 {
8218 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8219 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8220 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8221 WIPHY_VENDOR_CMD_NEED_NETDEV |
8222 WIPHY_VENDOR_CMD_NEED_RUNNING,
8223 .doit = wlan_hdd_cfg80211_set_passpoint_list
8224 },
8225 {
8226 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8227 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8228 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8229 WIPHY_VENDOR_CMD_NEED_NETDEV |
8230 WIPHY_VENDOR_CMD_NEED_RUNNING,
8231 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8232 },
8233 {
8234 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8235 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8236 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8237 WIPHY_VENDOR_CMD_NEED_NETDEV |
8238 WIPHY_VENDOR_CMD_NEED_RUNNING,
8239 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8240 },
8241 {
8242 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8243 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8244 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8245 WIPHY_VENDOR_CMD_NEED_NETDEV |
8246 WIPHY_VENDOR_CMD_NEED_RUNNING,
8247 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8248 },
8249#endif /* FEATURE_WLAN_EXTSCAN */
8250 {
8251 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8252 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8253 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8254 WIPHY_VENDOR_CMD_NEED_NETDEV,
8255 .doit = wlan_hdd_cfg80211_get_wifi_info
8256 },
8257 {
8258 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8259 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8260 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8261 WIPHY_VENDOR_CMD_NEED_NETDEV |
8262 WIPHY_VENDOR_CMD_NEED_RUNNING,
8263 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8264 },
8265 {
8266 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8267 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8268 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8269 WIPHY_VENDOR_CMD_NEED_NETDEV,
8270 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8271 },
8272 {
8273 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8274 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8275 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8276 WIPHY_VENDOR_CMD_NEED_NETDEV,
8277 .doit = wlan_hdd_cfg80211_wifi_logger_start
8278 },
8279 {
8280 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8281 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8282 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8283 WIPHY_VENDOR_CMD_NEED_NETDEV,
8284 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8285 },
8286 {
8287 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8288 .info.subcmd =
8289 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8290 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8291 WIPHY_VENDOR_CMD_NEED_NETDEV |
8292 WIPHY_VENDOR_CMD_NEED_RUNNING,
8293 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8294 },
8295 {
8296 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8297 .info.subcmd =
8298 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8299 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8300 WIPHY_VENDOR_CMD_NEED_NETDEV |
8301 WIPHY_VENDOR_CMD_NEED_RUNNING,
8302 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8303 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008304#ifdef WLAN_FEATURE_TSF
8305 {
8306 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8307 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8308 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8309 WIPHY_VENDOR_CMD_NEED_NETDEV |
8310 WIPHY_VENDOR_CMD_NEED_RUNNING,
8311 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8312 },
8313#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008314#ifdef FEATURE_WLAN_TDLS
8315 {
8316 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8317 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8318 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8319 WIPHY_VENDOR_CMD_NEED_NETDEV |
8320 WIPHY_VENDOR_CMD_NEED_RUNNING,
8321 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8322 },
8323#endif
8324#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8325 {
8326 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8327 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8328 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8329 WIPHY_VENDOR_CMD_NEED_NETDEV |
8330 WIPHY_VENDOR_CMD_NEED_RUNNING,
8331 .doit = wlan_hdd_cfg80211_offloaded_packets
8332 },
8333#endif
8334 {
8335 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8336 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8337 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8338 WIPHY_VENDOR_CMD_NEED_NETDEV |
8339 WIPHY_VENDOR_CMD_NEED_RUNNING,
8340 .doit = wlan_hdd_cfg80211_monitor_rssi
8341 },
8342 {
8343 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308344 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8345 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8346 WIPHY_VENDOR_CMD_NEED_NETDEV |
8347 WIPHY_VENDOR_CMD_NEED_RUNNING,
8348 .doit = wlan_hdd_cfg80211_set_ns_offload
8349 },
8350 {
8351 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008352 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8353 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8354 WIPHY_VENDOR_CMD_NEED_NETDEV |
8355 WIPHY_VENDOR_CMD_NEED_RUNNING,
8356 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8357 },
8358#ifdef WLAN_FEATURE_MEMDUMP
8359 {
8360 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8361 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8362 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8363 WIPHY_VENDOR_CMD_NEED_NETDEV |
8364 WIPHY_VENDOR_CMD_NEED_RUNNING,
8365 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8366 },
8367#endif /* WLAN_FEATURE_MEMDUMP */
8368 {
8369 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8370 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8371 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8372 WIPHY_VENDOR_CMD_NEED_NETDEV |
8373 WIPHY_VENDOR_CMD_NEED_RUNNING,
8374 .doit = wlan_hdd_cfg80211_vendor_scan
8375 },
8376
8377 /* OCB commands */
8378 {
8379 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8380 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8381 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8382 WIPHY_VENDOR_CMD_NEED_NETDEV |
8383 WIPHY_VENDOR_CMD_NEED_RUNNING,
8384 .doit = wlan_hdd_cfg80211_ocb_set_config
8385 },
8386 {
8387 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8388 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8389 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8390 WIPHY_VENDOR_CMD_NEED_NETDEV |
8391 WIPHY_VENDOR_CMD_NEED_RUNNING,
8392 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8393 },
8394 {
8395 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8396 .info.subcmd =
8397 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8398 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8399 WIPHY_VENDOR_CMD_NEED_NETDEV |
8400 WIPHY_VENDOR_CMD_NEED_RUNNING,
8401 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8402 },
8403 {
8404 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8405 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8406 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8407 WIPHY_VENDOR_CMD_NEED_NETDEV |
8408 WIPHY_VENDOR_CMD_NEED_RUNNING,
8409 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8410 },
8411 {
8412 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8413 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8414 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8415 WIPHY_VENDOR_CMD_NEED_NETDEV |
8416 WIPHY_VENDOR_CMD_NEED_RUNNING,
8417 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8418 },
8419 {
8420 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8421 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8422 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8423 WIPHY_VENDOR_CMD_NEED_NETDEV |
8424 WIPHY_VENDOR_CMD_NEED_RUNNING,
8425 .doit = wlan_hdd_cfg80211_dcc_get_stats
8426 },
8427 {
8428 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8429 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8430 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8431 WIPHY_VENDOR_CMD_NEED_NETDEV |
8432 WIPHY_VENDOR_CMD_NEED_RUNNING,
8433 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8434 },
8435 {
8436 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8437 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8438 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8439 WIPHY_VENDOR_CMD_NEED_NETDEV |
8440 WIPHY_VENDOR_CMD_NEED_RUNNING,
8441 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8442 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308443 {
8444 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8445 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8446 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8447 WIPHY_VENDOR_CMD_NEED_NETDEV |
8448 WIPHY_VENDOR_CMD_NEED_RUNNING,
8449 .doit = wlan_hdd_cfg80211_get_link_properties
8450 },
Peng Xu278d0122015-09-24 16:34:17 -07008451 {
Peng Xud2220962016-07-11 17:59:17 -07008452 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008453 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8454 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8455 WIPHY_VENDOR_CMD_NEED_NETDEV |
8456 WIPHY_VENDOR_CMD_NEED_RUNNING,
8457 .doit = wlan_hdd_cfg80211_set_ota_test
8458 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008459#ifdef FEATURE_LFR_SUBNET_DETECTION
8460 {
8461 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8462 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8464 WIPHY_VENDOR_CMD_NEED_NETDEV |
8465 WIPHY_VENDOR_CMD_NEED_RUNNING,
8466 .doit = wlan_hdd_cfg80211_set_gateway_params
8467 },
8468#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008469 {
Peng Xud2220962016-07-11 17:59:17 -07008470 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008471 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8472 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8473 WIPHY_VENDOR_CMD_NEED_NETDEV |
8474 WIPHY_VENDOR_CMD_NEED_RUNNING,
8475 .doit = wlan_hdd_cfg80211_txpower_scale
8476 },
8477 {
8478 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8479 .info.subcmd =
8480 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8481 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8482 WIPHY_VENDOR_CMD_NEED_NETDEV |
8483 WIPHY_VENDOR_CMD_NEED_RUNNING,
8484 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8485 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308486 {
8487 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8488 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8489 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8490 WIPHY_VENDOR_CMD_NEED_NETDEV |
8491 WIPHY_VENDOR_CMD_NEED_RUNNING,
8492 .doit = wlan_hdd_cfg80211_bpf_offload
8493 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308494 {
8495 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308496 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8497 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8498 WIPHY_VENDOR_CMD_NEED_NETDEV |
8499 WIPHY_VENDOR_CMD_NEED_RUNNING,
8500 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8501 },
8502 {
8503 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308504 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8505 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8506 WIPHY_VENDOR_CMD_NEED_NETDEV |
8507 WIPHY_VENDOR_CMD_NEED_RUNNING,
8508 .doit = wlan_hdd_cfg80211_sta_roam_policy
8509 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308510#ifdef FEATURE_WLAN_CH_AVOID
8511 {
8512 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8513 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8514 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8515 WIPHY_VENDOR_CMD_NEED_NETDEV |
8516 WIPHY_VENDOR_CMD_NEED_RUNNING,
8517 .doit = wlan_hdd_cfg80211_avoid_freq
8518 },
8519#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308520 {
8521 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308522 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8523 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8524 WIPHY_VENDOR_CMD_NEED_NETDEV |
8525 WIPHY_VENDOR_CMD_NEED_RUNNING,
8526 .doit = wlan_hdd_cfg80211_sap_configuration_set
8527 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008528 {
Peng Xu4225c152016-07-14 21:18:14 -07008529 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008530 .info.subcmd =
8531 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8532 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8533 WIPHY_VENDOR_CMD_NEED_NETDEV |
8534 WIPHY_VENDOR_CMD_NEED_RUNNING,
8535 .doit = wlan_hdd_cfg80211_p2p_lo_start
8536 },
8537 {
8538 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8539 .info.subcmd =
8540 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8541 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8542 WIPHY_VENDOR_CMD_NEED_NETDEV |
8543 WIPHY_VENDOR_CMD_NEED_RUNNING,
8544 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8545 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308546 {
8547 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8548 .info.subcmd =
8549 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8550 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8551 WIPHY_VENDOR_CMD_NEED_NETDEV |
8552 WIPHY_VENDOR_CMD_NEED_RUNNING,
8553 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8554 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008555#ifdef WLAN_FEATURE_NAN_DATAPATH
8556 {
8557 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8558 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8559 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8560 WIPHY_VENDOR_CMD_NEED_NETDEV |
8561 WIPHY_VENDOR_CMD_NEED_RUNNING,
8562 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8563 },
8564#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308565 {
8566 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8567 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8568 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8569 WIPHY_VENDOR_CMD_NEED_NETDEV |
8570 WIPHY_VENDOR_CMD_NEED_RUNNING,
8571 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8572 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308573 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308574 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8575 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8576 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8577 WIPHY_VENDOR_CMD_NEED_NETDEV |
8578 WIPHY_VENDOR_CMD_NEED_RUNNING,
8579 .doit = wlan_hdd_cfg80211_get_bus_size
8580 },
8581 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308582 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8583 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8584 WIPHY_VENDOR_CMD_NEED_NETDEV |
8585 WIPHY_VENDOR_CMD_NEED_RUNNING,
8586 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308587 },
8588 {
8589 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8590 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8591 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8592 WIPHY_VENDOR_CMD_NEED_NETDEV |
8593 WIPHY_VENDOR_CMD_NEED_RUNNING,
8594 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308595 },
8596#ifdef WLAN_FEATURE_DISA
8597 {
8598 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8599 .info.subcmd =
8600 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8601 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8602 WIPHY_VENDOR_CMD_NEED_NETDEV |
8603 WIPHY_VENDOR_CMD_NEED_RUNNING,
8604 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8605 },
8606#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07008607#ifdef FEATURE_WLAN_TDLS
8608 {
8609 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8610 .info.subcmd =
8611 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
8612 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8613 WIPHY_VENDOR_CMD_NEED_NETDEV |
8614 WIPHY_VENDOR_CMD_NEED_RUNNING,
8615 .doit = wlan_hdd_cfg80211_configure_tdls_mode
8616 }
8617#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008618};
8619
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008620/**
8621 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8622 * @priv_size: Size of the hdd context.
8623 *
8624 * Allocate wiphy context and hdd context.
8625 *
8626 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008627 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008628hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008629{
8630 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008631 hdd_context_t *hdd_ctx;
8632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008633 ENTER();
8634
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008635 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8636
8637 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008638 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008639 return NULL;
8640 }
8641
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008642 hdd_ctx = wiphy_priv(wiphy);
8643
8644 hdd_ctx->wiphy = wiphy;
8645
8646 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008647}
8648
8649/*
8650 * FUNCTION: wlan_hdd_cfg80211_update_band
8651 * This function is called from the supplicant through a
8652 * private ioctl to change the band value
8653 */
8654int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8655{
8656 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008657 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008658
8659 ENTER();
8660
Dustin Browna30892e2016-10-12 17:28:36 -07008661 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008662
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008663 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008664 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008665
8666 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8667 struct ieee80211_supported_band *band = wiphy->bands[i];
8668
8669 channelEnabledState =
8670 cds_get_channel_state(band->channels[j].
8671 hw_value);
8672
Dustin Browna30892e2016-10-12 17:28:36 -07008673 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008674 /* 5G only */
8675#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8676 /* Enable Social channels for P2P */
8677 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8678 (band->channels[j].center_freq)
8679 && CHANNEL_STATE_ENABLE ==
8680 channelEnabledState)
8681 band->channels[j].flags &=
8682 ~IEEE80211_CHAN_DISABLED;
8683 else
8684#endif
8685 band->channels[j].flags |=
8686 IEEE80211_CHAN_DISABLED;
8687 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008688 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008689 eCSR_BAND_24 == eBand) {
8690 /* 2G only */
8691 band->channels[j].flags |=
8692 IEEE80211_CHAN_DISABLED;
8693 continue;
8694 }
8695
Amar Singhal6842e8f2016-02-23 16:30:32 -08008696 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008697 band->channels[j].flags &=
8698 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008699 }
8700 }
8701 return 0;
8702}
8703
8704/*
8705 * FUNCTION: wlan_hdd_cfg80211_init
8706 * This function is called by hdd_wlan_startup()
8707 * during initialization.
8708 * This function is used to initialize and register wiphy structure.
8709 */
8710int wlan_hdd_cfg80211_init(struct device *dev,
8711 struct wiphy *wiphy, struct hdd_config *pCfg)
8712{
8713 int i, j;
8714 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8715
8716 ENTER();
8717
8718 /* Now bind the underlying wlan device with wiphy */
8719 set_wiphy_dev(wiphy, dev);
8720
8721 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8722
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008723#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8724 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008725 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008726#else
8727 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008728 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008729#endif
8730
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008731 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8732 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8733 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8734#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8735 | WIPHY_FLAG_4ADDR_STATION
8736#endif
8737 | WIPHY_FLAG_OFFCHAN_TX;
8738
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008739#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8740 wiphy->wowlan = &wowlan_support_cfg80211_init;
8741#else
8742 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8743 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8744 wiphy->wowlan.pattern_min_len = 1;
8745 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8746#endif
8747
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008748 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008749#ifdef FEATURE_WLAN_ESE
8750 || pCfg->isEseIniFeatureEnabled
8751#endif
8752 ) {
8753 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8754 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008755#ifdef FEATURE_WLAN_TDLS
8756 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8757 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8758#endif
8759
8760 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8761
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008762#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8763 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8764#endif
8765
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008766#ifdef FEATURE_WLAN_SCAN_PNO
8767 if (pCfg->configPNOScanSupport) {
8768 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8769 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8770 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8771 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008772#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8773 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8774#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008775 }
8776#endif /*FEATURE_WLAN_SCAN_PNO */
8777
8778#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308779 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008780#endif
8781
8782 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8783 driver can still register regulatory callback and
8784 it will get regulatory settings in wiphy->band[], but
8785 driver need to determine what to do with both
8786 regulatory settings */
8787
8788 wiphy->reg_notifier = hdd_reg_notifier;
8789
8790#if defined QCA_WIFI_FTM
8791}
8792#endif
8793
8794 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8795
8796 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8797
8798 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8799
Arun Khandavallifae92942016-08-01 13:31:08 +05308800 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8801 | BIT(NL80211_IFTYPE_ADHOC)
8802 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8803 | BIT(NL80211_IFTYPE_P2P_GO)
8804 | BIT(NL80211_IFTYPE_AP)
8805 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008806
Arun Khandavallifae92942016-08-01 13:31:08 +05308807 if (pCfg->advertiseConcurrentOperation) {
8808 if (pCfg->enableMCC) {
8809 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008810
Arun Khandavallifae92942016-08-01 13:31:08 +05308811 for (i = 0;
8812 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8813 i++) {
8814 if (!pCfg->allowMCCGODiffBI)
8815 wlan_hdd_iface_combination[i].
8816 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008817 }
8818 }
8819 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308820 ARRAY_SIZE(wlan_hdd_iface_combination);
8821 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008822 }
8823
8824 /* Before registering we need to update the ht capabilitied based
8825 * on ini values*/
8826 if (!pCfg->ShortGI20MhzEnable) {
8827 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8828 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008829 }
8830
8831 if (!pCfg->ShortGI40MhzEnable) {
8832 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8833 }
8834
8835 if (!pCfg->nChannelBondingMode5GHz) {
8836 wlan_hdd_band_5_ghz.ht_cap.cap &=
8837 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8838 }
8839
Abhishek Singhf512bf32016-05-04 16:47:46 +05308840 /*
8841 * In case of static linked driver at the time of driver unload,
8842 * module exit doesn't happens. Module cleanup helps in cleaning
8843 * of static memory.
8844 * If driver load happens statically, at the time of driver unload,
8845 * wiphy flags don't get reset because of static memory.
8846 * It's better not to store channel in static memory.
8847 */
Dustin Browna30892e2016-10-12 17:28:36 -07008848 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
8849 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308850 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008851 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308852 hdd_err("Not enough memory to allocate channels");
8853 return -ENOMEM;
8854 }
Dustin Browna30892e2016-10-12 17:28:36 -07008855 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308856 &hdd_channels_2_4_ghz[0],
8857 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308858 if ((hdd_is_5g_supported(pHddCtx)) &&
8859 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8860 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8861 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8862 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -07008863 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
8864 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308865 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008866 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308867 hdd_err("Not enough memory to allocate channels");
8868 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -07008869 bands[NL80211_BAND_2GHZ]->channels);
8870 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308871 return -ENOMEM;
8872 }
Dustin Browna30892e2016-10-12 17:28:36 -07008873 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308874 &hdd_channels_5_ghz[0],
8875 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008876 }
8877
Dustin Browna30892e2016-10-12 17:28:36 -07008878 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008879
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008880 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008881 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008882
8883 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8884 struct ieee80211_supported_band *band = wiphy->bands[i];
8885
Dustin Browna30892e2016-10-12 17:28:36 -07008886 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008887 eCSR_BAND_5G == pCfg->nBandCapability) {
8888 /* 5G only */
8889#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8890 /* Enable social channels for P2P */
8891 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8892 (band->channels[j].center_freq))
8893 band->channels[j].flags &=
8894 ~IEEE80211_CHAN_DISABLED;
8895 else
8896#endif
8897 band->channels[j].flags |=
8898 IEEE80211_CHAN_DISABLED;
8899 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008900 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008901 eCSR_BAND_24 == pCfg->nBandCapability) {
8902 /* 2G only */
8903 band->channels[j].flags |=
8904 IEEE80211_CHAN_DISABLED;
8905 continue;
8906 }
8907 }
8908 }
8909 /*Initialise the supported cipher suite details */
8910 wiphy->cipher_suites = hdd_cipher_suites;
8911 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8912
8913 /*signal strength in mBm (100*dBm) */
8914 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8915 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8916
Anurag Chouhan6d760662016-02-20 16:05:43 +05308917 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008918 wiphy->n_vendor_commands =
8919 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8920 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8921
8922 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8923 wiphy->n_vendor_events =
8924 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8925 }
8926
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008927 if (pCfg->enableDFSMasterCap) {
8928 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8929 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008930
8931 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8932
8933#ifdef QCA_HT_2040_COEX
8934 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8935#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +05308936 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308937 hdd_add_channel_switch_support(&wiphy->flags);
8938
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008939 EXIT();
8940 return 0;
8941}
8942
Abhishek Singhf512bf32016-05-04 16:47:46 +05308943/**
8944 * wlan_hdd_cfg80211_deinit - Deinit cfg80211
8945 * @ wiphy: the wiphy to validate against
8946 *
8947 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308948 * memory allocated in wlan_hdd_cfg80211_init also
8949 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308950 *
8951 * Return: void
8952 */
8953void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8954{
8955 int i;
8956
Dustin Browna30892e2016-10-12 17:28:36 -07008957 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308958 if (NULL != wiphy->bands[i] &&
8959 (NULL != wiphy->bands[i]->channels)) {
8960 qdf_mem_free(wiphy->bands[i]->channels);
8961 wiphy->bands[i]->channels = NULL;
8962 }
8963 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308964 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05308965}
8966
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008967/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308968 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008969 * initialization. In wlan_hdd_cfg80211_init, only the
8970 * default values will be initialized. The final initialization
8971 * of all required members can be done here.
8972 */
8973void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
8974{
8975 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8976}
8977
8978/* In this function we are registering wiphy. */
8979int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
8980{
8981 ENTER();
8982 /* Register our wiphy dev with cfg80211 */
8983 if (0 > wiphy_register(wiphy)) {
8984 /* print error */
Jeff Johnson77848112016-06-29 14:52:06 -07008985 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008986 return -EIO;
8987 }
8988
8989 EXIT();
8990 return 0;
8991}
8992
8993/*
8994 HDD function to update wiphy capability based on target offload status.
8995
8996 wlan_hdd_cfg80211_init() does initialization of all wiphy related
8997 capability even before downloading firmware to the target. In discrete
8998 case, host will get know certain offload capability (say sched_scan
8999 caps) only after downloading firmware to the target and target boots up.
9000 This function is used to override setting done in wlan_hdd_cfg80211_init()
9001 based on target capability.
9002 */
9003void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
9004{
9005#ifdef FEATURE_WLAN_SCAN_PNO
9006 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9007 struct hdd_config *pCfg = pHddCtx->config;
9008
9009 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
9010 * control comes here. Here just we need to clear it if firmware doesn't
9011 * have PNO support. */
9012 if (!pCfg->PnoOffload) {
9013 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9014 wiphy->max_sched_scan_ssids = 0;
9015 wiphy->max_match_sets = 0;
9016 wiphy->max_sched_scan_ie_len = 0;
9017 }
9018#endif
9019}
9020
9021/* This function registers for all frame which supplicant is interested in */
9022void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
9023{
9024 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9025 /* Register for all P2P action, public action etc frames */
9026 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9027
9028 ENTER();
9029
Abhishek Singh7996eb72015-12-30 17:24:02 +05309030 /* Register frame indication call back */
9031 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
9032
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05309033 /* Register for p2p ack indication */
9034 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
9035
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009036 /* Right now we are registering these frame when driver is getting
9037 initialized. Once we will move to 2.6.37 kernel, in which we have
9038 frame register ops, we will move this code as a part of that */
9039 /* GAS Initial Request */
9040 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9041 (uint8_t *) GAS_INITIAL_REQ,
9042 GAS_INITIAL_REQ_SIZE);
9043
9044 /* GAS Initial Response */
9045 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9046 (uint8_t *) GAS_INITIAL_RSP,
9047 GAS_INITIAL_RSP_SIZE);
9048
9049 /* GAS Comeback Request */
9050 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9051 (uint8_t *) GAS_COMEBACK_REQ,
9052 GAS_COMEBACK_REQ_SIZE);
9053
9054 /* GAS Comeback Response */
9055 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9056 (uint8_t *) GAS_COMEBACK_RSP,
9057 GAS_COMEBACK_RSP_SIZE);
9058
9059 /* P2P Public Action */
9060 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9061 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9062 P2P_PUBLIC_ACTION_FRAME_SIZE);
9063
9064 /* P2P Action */
9065 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9066 (uint8_t *) P2P_ACTION_FRAME,
9067 P2P_ACTION_FRAME_SIZE);
9068
9069 /* WNM BSS Transition Request frame */
9070 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9071 (uint8_t *) WNM_BSS_ACTION_FRAME,
9072 WNM_BSS_ACTION_FRAME_SIZE);
9073
9074 /* WNM-Notification */
9075 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9076 (uint8_t *) WNM_NOTIFICATION_FRAME,
9077 WNM_NOTIFICATION_FRAME_SIZE);
9078}
9079
9080void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9081{
9082 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9083 /* Register for all P2P action, public action etc frames */
9084 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9085
9086 ENTER();
9087
9088 /* Right now we are registering these frame when driver is getting
9089 initialized. Once we will move to 2.6.37 kernel, in which we have
9090 frame register ops, we will move this code as a part of that */
9091 /* GAS Initial Request */
9092
9093 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9094 (uint8_t *) GAS_INITIAL_REQ,
9095 GAS_INITIAL_REQ_SIZE);
9096
9097 /* GAS Initial Response */
9098 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9099 (uint8_t *) GAS_INITIAL_RSP,
9100 GAS_INITIAL_RSP_SIZE);
9101
9102 /* GAS Comeback Request */
9103 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9104 (uint8_t *) GAS_COMEBACK_REQ,
9105 GAS_COMEBACK_REQ_SIZE);
9106
9107 /* GAS Comeback Response */
9108 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9109 (uint8_t *) GAS_COMEBACK_RSP,
9110 GAS_COMEBACK_RSP_SIZE);
9111
9112 /* P2P Public Action */
9113 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9114 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9115 P2P_PUBLIC_ACTION_FRAME_SIZE);
9116
9117 /* P2P Action */
9118 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9119 (uint8_t *) P2P_ACTION_FRAME,
9120 P2P_ACTION_FRAME_SIZE);
9121
9122 /* WNM-Notification */
9123 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9124 (uint8_t *) WNM_NOTIFICATION_FRAME,
9125 WNM_NOTIFICATION_FRAME_SIZE);
9126}
9127
9128#ifdef FEATURE_WLAN_WAPI
9129void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9130 const uint8_t *mac_addr, const uint8_t *key,
9131 int key_Len)
9132{
9133 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9134 tCsrRoamSetKey setKey;
9135 bool isConnected = true;
9136 int status = 0;
9137 uint32_t roamId = 0xFF;
9138 uint8_t *pKeyPtr = NULL;
9139 int n = 0;
9140
Jeff Johnson46b40792016-06-29 14:03:14 -07009141 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009142 hdd_device_mode_to_string(pAdapter->device_mode),
9143 pAdapter->device_mode);
9144
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309145 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009146 setKey.keyId = key_index; /* Store Key ID */
9147 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9148 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9149 setKey.paeRole = 0; /* the PAE role */
9150 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309151 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009152 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309153 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009154 }
9155 setKey.keyLength = key_Len;
9156 pKeyPtr = setKey.Key;
9157 memcpy(pKeyPtr, key, key_Len);
9158
Jeff Johnson46b40792016-06-29 14:03:14 -07009159 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009160 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009161 hdd_notice("WAPI KEY Data[%d]:%02x ",
9162 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009163
9164 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9165 if (isConnected) {
9166 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9167 pAdapter->sessionId, &setKey, &roamId);
9168 }
9169 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009170 hdd_err("sme_roam_set_key returned ERROR status= %d",
9171 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009172 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9173 }
9174}
9175#endif /* FEATURE_WLAN_WAPI */
9176
9177uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9178 uint8_t eid)
9179{
9180 int left = length;
9181 uint8_t *ptr = (uint8_t *)ies_ptr;
9182 uint8_t elem_id, elem_len;
9183
9184 while (left >= 2) {
9185 elem_id = ptr[0];
9186 elem_len = ptr[1];
9187 left -= 2;
9188 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009189 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009190 eid, elem_len, left);
9191 return NULL;
9192 }
9193 if (elem_id == eid) {
9194 return ptr;
9195 }
9196
9197 left -= elem_len;
9198 ptr += (elem_len + 2);
9199 }
9200 return NULL;
9201}
9202
9203/*
9204 * FUNCTION: wlan_hdd_validate_operation_channel
9205 * called by wlan_hdd_cfg80211_start_bss() and
9206 * wlan_hdd_set_channel()
9207 * This function validates whether given channel is part of valid
9208 * channel list.
9209 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309210QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009211 int channel)
9212{
9213
9214 uint32_t num_ch = 0;
9215 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9216 u32 indx = 0;
9217 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9218 uint8_t fValidChannel = false, count = 0;
9219 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9220
9221 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9222
9223 if (hdd_pConfig_ini->sapAllowAllChannel) {
9224 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009225 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009226 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009227 fValidChannel = true;
9228 break;
9229 }
9230 }
9231 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009232 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309233 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009234 }
9235 } else {
9236 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9237 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009238 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309239 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009240 }
9241 for (indx = 0; indx < num_ch; indx++) {
9242 if (channel == valid_ch[indx]) {
9243 break;
9244 }
9245 }
9246
9247 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009248 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309249 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009250 }
9251 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309252 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009253
9254}
9255
9256#ifdef DHCP_SERVER_OFFLOAD
9257static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9258{
9259 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9260 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9261 uint8_t numEntries = 0;
9262 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9263 uint8_t num;
9264 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309265 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009266 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009267 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009268 return;
9269 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009270 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9271 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9272 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9273 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9274 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9275 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009276 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009277 goto end;
9278 }
9279 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009280 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009281 goto end;
9282 }
9283 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009284 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009285 goto end;
9286 }
9287 for (num = 0; num < numEntries; num++) {
9288 temp = srv_ip[num];
9289 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9290 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309291 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009292 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009293 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009294 goto end;
9295 }
Jeff Johnson77848112016-06-29 14:52:06 -07009296 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009297end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309298 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009299 return;
9300}
9301#endif /* DHCP_SERVER_OFFLOAD */
9302
9303static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9304 struct net_device *dev,
9305 struct bss_parameters *params)
9306{
9307 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9308 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9309 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309310 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009311
9312 ENTER();
9313
Anurag Chouhan6d760662016-02-20 16:05:43 +05309314 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009315 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009316 return -EINVAL;
9317 }
9318
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309319 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9320 hdd_err("invalid session id: %d", pAdapter->sessionId);
9321 return -EINVAL;
9322 }
9323
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309324 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009325 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9326 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009327 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009328 hdd_device_mode_to_string(pAdapter->device_mode),
9329 pAdapter->device_mode, params->ap_isolate);
9330
9331 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9332 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309333 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009334 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009335
Krunal Sonib4326f22016-03-10 13:05:51 -08009336 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9337 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009338 return -EOPNOTSUPP;
9339 }
9340
9341 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9342 * want to update this parameter */
9343 if (-1 != params->ap_isolate) {
9344 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9345 !!params->ap_isolate;
9346
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309347 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009348 pAdapter->sessionId,
9349 pAdapter->sessionCtx.
9350 ap.
9351 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309352 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009353 ret = -EINVAL;
9354 }
9355 }
9356
9357 EXIT();
9358 return ret;
9359}
9360
Krunal Soni8c37e322016-02-03 16:08:37 -08009361/**
9362 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9363 * @ndev: pointer to net device provided by supplicant
9364 * @type: type of the interface, upper layer wanted to change
9365 *
9366 * Upper layer provides the new interface mode that needs to be changed
9367 * for given net device
9368 *
9369 * Return: success or failure in terms of integer value
9370 */
9371static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009372 enum nl80211_iftype type)
9373{
Krunal Soni8c37e322016-02-03 16:08:37 -08009374 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9375 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9376 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009377 hdd_wext_state_t *wext;
9378 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309379 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009380
9381 ENTER();
9382
Krunal Soni8c37e322016-02-03 16:08:37 -08009383 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009384 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009385 return 0;
9386 }
9387
9388 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009389 hdd_stop_adapter(hdd_ctx, adapter, true);
9390 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009391 wdev->iftype = type;
9392 /*Check for sub-string p2p to confirm its a p2p interface */
9393 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009394 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009395 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009396 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009397 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009398 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009399 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009400 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009401 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009402 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009403 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009404 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9405 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009406 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9407 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009408 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009409 adapter->scan_info.scanAddIE.length;
9410 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309411 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009412 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9413 wext->roamProfile.phyMode =
9414 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9415 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009416 EXIT();
9417 return status;
9418}
9419
9420static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9421 struct net_device *dev,
9422 struct bss_parameters *params)
9423{
9424 int ret;
9425
9426 cds_ssr_protect(__func__);
9427 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9428 cds_ssr_unprotect(__func__);
9429
9430 return ret;
9431}
9432
9433/* FUNCTION: wlan_hdd_change_country_code_cd
9434 * to wait for contry code completion
9435 */
9436void *wlan_hdd_change_country_code_cb(void *pAdapter)
9437{
9438 hdd_adapter_t *call_back_pAdapter = pAdapter;
9439 complete(&call_back_pAdapter->change_country_code);
9440 return NULL;
9441}
9442
Rajeev Kumar98edb772016-01-19 12:42:19 -08009443/**
9444 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9445 * @wiphy: Pointer to the wiphy structure
9446 * @ndev: Pointer to the net device
9447 * @type: Interface type
9448 * @flags: Flags for change interface
9449 * @params: Pointer to change interface parameters
9450 *
9451 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009452 */
9453static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9454 struct net_device *ndev,
9455 enum nl80211_iftype type,
9456 u32 *flags,
9457 struct vif_params *params)
9458{
9459 struct wireless_dev *wdev;
9460 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9461 hdd_context_t *pHddCtx;
9462 tCsrRoamProfile *pRoamProfile = NULL;
9463 eCsrRoamBssType LastBSSType;
9464 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309465 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009466 int status;
9467
9468 ENTER();
9469
Anurag Chouhan6d760662016-02-20 16:05:43 +05309470 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009471 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009472 return -EINVAL;
9473 }
9474
9475 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9476 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309477 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009478 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009479
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309480 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009481 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9482 pAdapter->sessionId, type));
9483
Jeff Johnson77848112016-06-29 14:52:06 -07009484 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009485 pAdapter->device_mode, type);
9486
Arun Khandavallifae92942016-08-01 13:31:08 +05309487 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9488 if (status) {
9489 hdd_err("Failed to start modules");
9490 return -EINVAL;
9491 }
9492
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009493 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009494 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9495 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009496 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009497 return -EINVAL;
9498 }
9499
9500 pConfig = pHddCtx->config;
9501 wdev = ndev->ieee80211_ptr;
9502
9503 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009504 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009505
9506 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9507
Krunal Sonib4326f22016-03-10 13:05:51 -08009508 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9509 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9510 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9511 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009512 hdd_wext_state_t *pWextState =
9513 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9514
9515 pRoamProfile = &pWextState->roamProfile;
9516 LastBSSType = pRoamProfile->BSSType;
9517
9518 switch (type) {
9519 case NL80211_IFTYPE_STATION:
9520 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009521 case NL80211_IFTYPE_ADHOC:
9522 if (type == NL80211_IFTYPE_ADHOC) {
9523 wlan_hdd_tdls_exit(pAdapter);
9524 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009525 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009526 }
9527 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9528 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309529 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009530 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309531 if (hdd_start_adapter(pAdapter)) {
9532 hdd_err("Failed to start adapter :%d",
9533 pAdapter->device_mode);
9534 return -EINVAL;
9535 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009536 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009537 case NL80211_IFTYPE_AP:
9538 case NL80211_IFTYPE_P2P_GO:
9539 {
Jeff Johnson77848112016-06-29 14:52:06 -07009540 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009541 (type ==
9542 NL80211_IFTYPE_AP) ? "SoftAP" :
9543 "P2pGo");
9544
9545 /* Cancel any remain on channel for GO mode */
9546 if (NL80211_IFTYPE_P2P_GO == type) {
9547 wlan_hdd_cancel_existing_remain_on_channel
9548 (pAdapter);
9549 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009550
Arun Khandavallifae92942016-08-01 13:31:08 +05309551 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009552 /* De-init the adapter */
9553 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9554 memset(&pAdapter->sessionCtx, 0,
9555 sizeof(pAdapter->sessionCtx));
9556 pAdapter->device_mode =
9557 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009558 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9559 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009560
9561 /*
9562 * Fw will take care incase of concurrency
9563 */
9564
Krunal Sonib4326f22016-03-10 13:05:51 -08009565 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009566 && (pConfig->apRandomBssidEnabled)) {
9567 /* To meet Android requirements create a randomized
9568 MAC address of the form 02:1A:11:Fx:xx:xx */
9569 get_random_bytes(&ndev->dev_addr[3], 3);
9570 ndev->dev_addr[0] = 0x02;
9571 ndev->dev_addr[1] = 0x1A;
9572 ndev->dev_addr[2] = 0x11;
9573 ndev->dev_addr[3] |= 0xF0;
9574 memcpy(pAdapter->macAddressCurrent.
9575 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309576 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009577 pr_info("wlan: Generated HotSpot BSSID "
9578 MAC_ADDRESS_STR "\n",
9579 MAC_ADDR_ARRAY(ndev->dev_addr));
9580 }
9581
9582 hdd_set_ap_ops(pAdapter->dev);
9583
Arun Khandavallifae92942016-08-01 13:31:08 +05309584 if (hdd_start_adapter(pAdapter)) {
9585 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009586 return -EINVAL;
9587 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009588 /* Interface type changed update in wiphy structure */
9589 if (wdev) {
9590 wdev->iftype = type;
9591 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009592 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009593 return -EINVAL;
9594 }
9595 goto done;
9596 }
9597
9598 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009599 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009600 type);
9601 return -EOPNOTSUPP;
9602 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009603 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9604 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009605 switch (type) {
9606 case NL80211_IFTYPE_STATION:
9607 case NL80211_IFTYPE_P2P_CLIENT:
9608 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009609 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9610 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309611 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009612 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309613 if (hdd_start_adapter(pAdapter)) {
9614 hdd_err("Failed to start adapter :%d",
9615 pAdapter->device_mode);
9616 return -EINVAL;
9617 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009618 goto done;
9619
9620 case NL80211_IFTYPE_AP:
9621 case NL80211_IFTYPE_P2P_GO:
9622 wdev->iftype = type;
9623 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009624 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009625 goto done;
9626
9627 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009628 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009629 type);
9630 return -EOPNOTSUPP;
9631 }
9632 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009633 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009634 pAdapter->device_mode);
9635 return -EOPNOTSUPP;
9636 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009637done:
9638 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009639 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009640
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009641 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009642
9643 EXIT();
9644 return 0;
9645}
9646
Rajeev Kumar98edb772016-01-19 12:42:19 -08009647/**
9648 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9649 * @wiphy: Pointer to the wiphy structure
9650 * @ndev: Pointer to the net device
9651 * @type: Interface type
9652 * @flags: Flags for change interface
9653 * @params: Pointer to change interface parameters
9654 *
9655 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009656 */
9657static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9658 struct net_device *ndev,
9659 enum nl80211_iftype type,
9660 u32 *flags,
9661 struct vif_params *params)
9662{
9663 int ret;
9664
9665 cds_ssr_protect(__func__);
9666 ret =
9667 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9668 cds_ssr_unprotect(__func__);
9669
9670 return ret;
9671}
9672
9673#ifdef FEATURE_WLAN_TDLS
9674static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9675 int index, uint8_t match)
9676{
9677 int i;
9678 for (i = 0; i < index; i++) {
9679 if (arr[i] == match)
9680 return true;
9681 }
9682 return false;
9683}
9684#endif
9685
9686/**
9687 * __wlan_hdd_change_station() - change station
9688 * @wiphy: Pointer to the wiphy structure
9689 * @dev: Pointer to the net device.
9690 * @mac: bssid
9691 * @params: Pointer to station parameters
9692 *
9693 * Return: 0 for success, error number on failure.
9694 */
9695#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9696static int __wlan_hdd_change_station(struct wiphy *wiphy,
9697 struct net_device *dev,
9698 const uint8_t *mac,
9699 struct station_parameters *params)
9700#else
9701static int __wlan_hdd_change_station(struct wiphy *wiphy,
9702 struct net_device *dev,
9703 uint8_t *mac,
9704 struct station_parameters *params)
9705#endif
9706{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309707 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009708 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9709 hdd_context_t *pHddCtx;
9710 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309711 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009712#ifdef FEATURE_WLAN_TDLS
9713 tCsrStaParams StaParams = { 0 };
9714 uint8_t isBufSta = 0;
9715 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309716 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009717#endif
9718 int ret;
9719
9720 ENTER();
9721
Anurag Chouhan6d760662016-02-20 16:05:43 +05309722 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009723 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009724 return -EINVAL;
9725 }
9726
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309727 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009728 TRACE_CODE_HDD_CHANGE_STATION,
9729 pAdapter->sessionId, params->listen_interval));
9730
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309731 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9732 hdd_err("invalid session id: %d", pAdapter->sessionId);
9733 return -EINVAL;
9734 }
9735
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009736 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9737 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309738 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009739 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009740
9741 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9742
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309743 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009744
Krunal Sonib4326f22016-03-10 13:05:51 -08009745 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9746 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009747 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9748 status =
9749 hdd_softap_change_sta_state(pAdapter,
9750 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009751 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009752
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309753 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009754 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009755 return -EINVAL;
9756 }
9757 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009758 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9759 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009760#ifdef FEATURE_WLAN_TDLS
9761 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009762
9763 if (cds_is_sub_20_mhz_enabled()) {
9764 hdd_err("TDLS not allowed with sub 20 MHz");
9765 return -EINVAL;
9766 }
9767
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009768 StaParams.capability = params->capability;
9769 StaParams.uapsd_queues = params->uapsd_queues;
9770 StaParams.max_sp = params->max_sp;
9771
9772 /* Convert (first channel , number of channels) tuple to
9773 * the total list of channels. This goes with the assumption
9774 * that if the first channel is < 14, then the next channels
9775 * are an incremental of 1 else an incremental of 4 till the number
9776 * of channels.
9777 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009778 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009779 if (0 != params->supported_channels_len) {
9780 int i = 0, j = 0, k = 0, no_of_channels = 0;
9781 int num_unique_channels;
9782 int next;
9783 for (i = 0;
9784 i < params->supported_channels_len
9785 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9786 int wifi_chan_index;
9787 if (!wlan_hdd_is_duplicate_channel
9788 (StaParams.supported_channels, j,
9789 params->supported_channels[i])) {
9790 StaParams.
9791 supported_channels[j] =
9792 params->
9793 supported_channels[i];
9794 } else {
9795 continue;
9796 }
9797 wifi_chan_index =
9798 ((StaParams.supported_channels[j] <=
9799 HDD_CHANNEL_14) ? 1 : 4);
9800 no_of_channels =
9801 params->supported_channels[i + 1];
9802
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009803 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 -08009804 StaParams.
9805 supported_channels[j],
9806 wifi_chan_index,
9807 no_of_channels);
9808 for (k = 1; k <= no_of_channels &&
9809 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9810 k++) {
9811 next =
9812 StaParams.
9813 supported_channels[j] +
9814 wifi_chan_index;
9815 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9816 StaParams.
9817 supported_channels[j
9818 +
9819 1]
9820 = next;
9821 } else {
9822 continue;
9823 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009824 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009825 j + 1,
9826 StaParams.
9827 supported_channels[j +
9828 1]);
9829 j += 1;
9830 }
9831 }
9832 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009833 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009834 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009835 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009836 StaParams.
9837 supported_channels[i]);
9838 }
9839 if (MAX_CHANNEL < num_unique_channels)
9840 num_unique_channels = MAX_CHANNEL;
9841 StaParams.supported_channels_len =
9842 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009843 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009844 StaParams.supported_channels_len);
9845 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309846 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009847 params->supported_oper_classes,
9848 params->supported_oper_classes_len);
9849 StaParams.supported_oper_classes_len =
9850 params->supported_oper_classes_len;
9851
9852 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309853 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009854 params->ext_capab,
9855 sizeof(StaParams.extn_capability));
9856
9857 if (NULL != params->ht_capa) {
9858 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309859 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009860 sizeof(tSirHTCap));
9861 }
9862
9863 StaParams.supported_rates_len =
9864 params->supported_rates_len;
9865
9866 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9867 * The supported_rates array , for all the structures propogating till Add Sta
9868 * to the firmware has to be modified , if the supplicant (ieee80211) is
9869 * modified to send more rates.
9870 */
9871
9872 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
9873 */
9874 if (StaParams.supported_rates_len >
9875 SIR_MAC_MAX_SUPP_RATES)
9876 StaParams.supported_rates_len =
9877 SIR_MAC_MAX_SUPP_RATES;
9878
9879 if (0 != StaParams.supported_rates_len) {
9880 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309881 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009882 params->supported_rates,
9883 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009884 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009885 StaParams.supported_rates_len);
9886 for (i = 0; i < StaParams.supported_rates_len;
9887 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009888 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009889 StaParams.supported_rates[i]);
9890 }
9891
9892 if (NULL != params->vht_capa) {
9893 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309894 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009895 params->vht_capa,
9896 sizeof(tSirVHTCap));
9897 }
9898
9899 if (0 != params->ext_capab_len) {
9900 /*Define A Macro : TODO Sunil */
9901 if ((1 << 4) & StaParams.extn_capability[3]) {
9902 isBufSta = 1;
9903 }
9904 /* TDLS Channel Switching Support */
9905 if ((1 << 6) & StaParams.extn_capability[3]) {
9906 isOffChannelSupported = 1;
9907 }
9908 }
9909
Nitesh Shah99934ac2016-09-05 15:54:08 +05309910 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +05309911 (params->ht_capa || params->vht_capa ||
9912 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +05309913 is_qos_wmm_sta = true;
9914
9915 hdd_notice("%s: TDLS Peer is QOS capable"
9916 " is_qos_wmm_sta= %d HTcapPresent = %d",
9917 __func__, is_qos_wmm_sta,
9918 StaParams.htcap_present);
9919
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009920 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +05309921 &StaParams,
9922 isBufSta,
9923 isOffChannelSupported,
9924 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309925 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009926 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009927 return -EINVAL;
9928 }
9929
9930 status =
9931 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
9932 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309933 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009934 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009935 return -EINVAL;
9936 }
9937 }
9938#endif
9939 }
9940 EXIT();
9941 return ret;
9942}
9943
9944/**
9945 * wlan_hdd_change_station() - cfg80211 change station handler function
9946 * @wiphy: Pointer to the wiphy structure
9947 * @dev: Pointer to the net device.
9948 * @mac: bssid
9949 * @params: Pointer to station parameters
9950 *
9951 * This is the cfg80211 change station handler function which invokes
9952 * the internal function @__wlan_hdd_change_station with
9953 * SSR protection.
9954 *
9955 * Return: 0 for success, error number on failure.
9956 */
9957#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
9958static int wlan_hdd_change_station(struct wiphy *wiphy,
9959 struct net_device *dev,
9960 const u8 *mac,
9961 struct station_parameters *params)
9962#else
9963static int wlan_hdd_change_station(struct wiphy *wiphy,
9964 struct net_device *dev,
9965 u8 *mac,
9966 struct station_parameters *params)
9967#endif
9968{
9969 int ret;
9970
9971 cds_ssr_protect(__func__);
9972 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
9973 cds_ssr_unprotect(__func__);
9974
9975 return ret;
9976}
9977
9978/*
9979 * FUNCTION: __wlan_hdd_cfg80211_add_key
9980 * This function is used to initialize the key information
9981 */
9982static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
9983 struct net_device *ndev,
9984 u8 key_index, bool pairwise,
9985 const u8 *mac_addr,
9986 struct key_params *params)
9987{
9988 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9989 tCsrRoamSetKey setKey;
9990 int status;
9991 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009992 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309993 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009994 hdd_context_t *pHddCtx;
9995 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9996
9997 ENTER();
9998
Anurag Chouhan6d760662016-02-20 16:05:43 +05309999 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010000 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010001 return -EINVAL;
10002 }
10003
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010004 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10005 hdd_err("invalid session id: %d", pAdapter->sessionId);
10006 return -EINVAL;
10007 }
10008
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010009 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010010 TRACE_CODE_HDD_CFG80211_ADD_KEY,
10011 pAdapter->sessionId, params->key_len));
10012 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10013 status = wlan_hdd_validate_context(pHddCtx);
10014
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010015 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010016 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010017
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010018 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010019 hdd_device_mode_to_string(pAdapter->device_mode),
10020 pAdapter->device_mode);
10021
10022 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010023 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010024
10025 return -EINVAL;
10026 }
10027
10028 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010029 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010030
10031 return -EINVAL;
10032 }
10033
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010034 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010035
10036 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010037 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010038 setKey.keyId = key_index;
10039 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010040 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010041
10042 switch (params->cipher) {
10043 case WLAN_CIPHER_SUITE_WEP40:
10044 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10045 break;
10046
10047 case WLAN_CIPHER_SUITE_WEP104:
10048 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
10049 break;
10050
10051 case WLAN_CIPHER_SUITE_TKIP:
10052 {
10053 u8 *pKey = &setKey.Key[0];
10054 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
10055
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010056 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010057
10058 /*Supplicant sends the 32bytes key in this order
10059
10060 |--------------|----------|----------|
10061 | Tk1 |TX-MIC | RX Mic |
10062 |||--------------|----------|----------|
10063 <---16bytes---><--8bytes--><--8bytes-->
10064
10065 */
10066 /*Sme expects the 32 bytes key to be in the below order
10067
10068 |--------------|----------|----------|
10069 | Tk1 |RX-MIC | TX Mic |
10070 |||--------------|----------|----------|
10071 <---16bytes---><--8bytes--><--8bytes-->
10072 */
10073 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010074 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010075
10076 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010077 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010078
10079 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010080 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010081
10082 break;
10083 }
10084
10085 case WLAN_CIPHER_SUITE_CCMP:
10086 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10087 break;
10088
10089#ifdef FEATURE_WLAN_WAPI
10090 case WLAN_CIPHER_SUITE_SMS4:
10091 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010092 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010093 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10094 mac_addr, params->key,
10095 params->key_len);
10096 return 0;
10097 }
10098#endif
10099
10100#ifdef FEATURE_WLAN_ESE
10101 case WLAN_CIPHER_SUITE_KRK:
10102 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10103 break;
10104#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10105 case WLAN_CIPHER_SUITE_BTK:
10106 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10107 break;
10108#endif
10109#endif
10110
10111#ifdef WLAN_FEATURE_11W
10112 case WLAN_CIPHER_SUITE_AES_CMAC:
10113 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10114 break;
10115#endif
10116
10117 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010118 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010119 return -EOPNOTSUPP;
10120 }
10121
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010122 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010123
10124 if (!pairwise) {
10125 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010126 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010127 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010128 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010129 } else {
10130 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010131 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010132 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010133 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010134 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010135 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010136 /* if a key is already installed, block all subsequent ones */
10137 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010138 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010139 return 0;
10140 }
10141
10142 setKey.keyDirection = eSIR_TX_RX;
10143 /*Set the group key */
10144 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10145 pAdapter->sessionId, &setKey, &roamId);
10146
10147 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010148 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010149 return -EINVAL;
10150 }
10151 /*Save the keys here and call sme_roam_set_key for setting
10152 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010153 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010154 &setKey, sizeof(tCsrRoamSetKey));
10155
10156 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10157 return status;
10158 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010159 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10160 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010161 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10162 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010163 status = wlansap_set_key_sta(
10164 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010165 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010166 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010167 __LINE__, status);
10168 }
10169 }
10170
10171 /* Save the key in ap ctx for use on START_BASS and restart */
10172 if (pairwise ||
10173 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10174 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010175 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010176 sizeof(tCsrRoamSetKey));
10177 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010178 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010179 sizeof(tCsrRoamSetKey));
10180
Krunal Sonib4326f22016-03-10 13:05:51 -080010181 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10182 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010183 hdd_wext_state_t *pWextState =
10184 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10185 hdd_station_ctx_t *pHddStaCtx =
10186 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10187
10188 if (!pairwise) {
10189 /* set group key */
10190 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010191 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010192 __func__, __LINE__);
10193 hdd_perform_roam_set_key_complete(pAdapter);
10194 }
10195 }
10196
10197 pWextState->roamProfile.Keys.KeyLength[key_index] =
10198 (u8) params->key_len;
10199
10200 pWextState->roamProfile.Keys.defaultIndex = key_index;
10201
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010202 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010203 KeyMaterial[key_index][0], params->key,
10204 params->key_len);
10205
10206 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10207
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010208 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010209 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10210 setKey.keyDirection);
10211
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010212 /* The supplicant may attempt to set the PTK once pre-authentication
10213 is done. Save the key in the UMAC and include it in the ADD BSS
10214 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010215 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010216 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010217 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010218 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010219 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010220 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010221 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010222 return -EINVAL;
10223 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010224
10225 /* issue set key request to SME */
10226 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10227 pAdapter->sessionId, &setKey, &roamId);
10228
10229 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010230 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010231 pHddStaCtx->roam_info.roamingState =
10232 HDD_ROAM_STATE_NONE;
10233 return -EINVAL;
10234 }
10235
10236 /* in case of IBSS as there was no information available about WEP keys during
10237 * IBSS join, group key intialized with NULL key, so re-initialize group key
10238 * with correct value*/
10239 if ((eCSR_BSS_TYPE_START_IBSS ==
10240 pWextState->roamProfile.BSSType)
10241 &&
10242 !((IW_AUTH_KEY_MGMT_802_1X ==
10243 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10244 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10245 pHddStaCtx->conn_info.authType)
10246 )
10247 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10248 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10249 )
10250 ) {
10251 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010252 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010253
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010254 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010255 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10256 setKey.keyDirection);
10257
10258 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10259 pAdapter->sessionId, &setKey,
10260 &roamId);
10261
10262 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010263 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010264 pHddStaCtx->roam_info.roamingState =
10265 HDD_ROAM_STATE_NONE;
10266 return -EINVAL;
10267 }
10268 }
10269 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010270 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010271 return 0;
10272}
10273
10274static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10275 struct net_device *ndev,
10276 u8 key_index, bool pairwise,
10277 const u8 *mac_addr,
10278 struct key_params *params)
10279{
10280 int ret;
10281 cds_ssr_protect(__func__);
10282 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10283 mac_addr, params);
10284 cds_ssr_unprotect(__func__);
10285
10286 return ret;
10287}
10288
10289/*
10290 * FUNCTION: __wlan_hdd_cfg80211_get_key
10291 * This function is used to get the key information
10292 */
10293static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10294 struct net_device *ndev,
10295 u8 key_index, bool pairwise,
10296 const u8 *mac_addr, void *cookie,
10297 void (*callback)(void *cookie,
10298 struct key_params *)
10299 )
10300{
10301 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10302 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10303 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10304 struct key_params params;
10305
10306 ENTER();
10307
Anurag Chouhan6d760662016-02-20 16:05:43 +053010308 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010309 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010310 return -EINVAL;
10311 }
10312
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010313 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010314 hdd_device_mode_to_string(pAdapter->device_mode),
10315 pAdapter->device_mode);
10316
10317 memset(&params, 0, sizeof(params));
10318
10319 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010320 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010321 key_index);
10322 return -EINVAL;
10323 }
10324
10325 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10326 case eCSR_ENCRYPT_TYPE_NONE:
10327 params.cipher = IW_AUTH_CIPHER_NONE;
10328 break;
10329
10330 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10331 case eCSR_ENCRYPT_TYPE_WEP40:
10332 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10333 break;
10334
10335 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10336 case eCSR_ENCRYPT_TYPE_WEP104:
10337 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10338 break;
10339
10340 case eCSR_ENCRYPT_TYPE_TKIP:
10341 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10342 break;
10343
10344 case eCSR_ENCRYPT_TYPE_AES:
10345 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10346 break;
10347
10348 default:
10349 params.cipher = IW_AUTH_CIPHER_NONE;
10350 break;
10351 }
10352
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010353 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010354 TRACE_CODE_HDD_CFG80211_GET_KEY,
10355 pAdapter->sessionId, params.cipher));
10356
10357 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10358 params.seq_len = 0;
10359 params.seq = NULL;
10360 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10361 callback(cookie, &params);
10362
10363 EXIT();
10364 return 0;
10365}
10366
10367static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10368 struct net_device *ndev,
10369 u8 key_index, bool pairwise,
10370 const u8 *mac_addr, void *cookie,
10371 void (*callback)(void *cookie,
10372 struct key_params *)
10373 )
10374{
10375 int ret;
10376
10377 cds_ssr_protect(__func__);
10378 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10379 mac_addr, cookie, callback);
10380 cds_ssr_unprotect(__func__);
10381
10382 return ret;
10383}
10384
10385/**
10386 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10387 * @wiphy: wiphy interface context
10388 * @ndev: pointer to net device
10389 * @key_index: Key index used in 802.11 frames
10390 * @unicast: true if it is unicast key
10391 * @multicast: true if it is multicast key
10392 *
10393 * This function is required for cfg80211_ops API.
10394 * It is used to delete the key information
10395 * Underlying hardware implementation does not have API to delete the
10396 * encryption key. It is automatically deleted when the peer is
10397 * removed. Hence this function currently does nothing.
10398 * Future implementation may interprete delete key operation to
10399 * replacing the key with a random junk value, effectively making it
10400 * useless.
10401 *
10402 * Return: status code, always 0.
10403 */
10404
10405static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10406 struct net_device *ndev,
10407 u8 key_index,
10408 bool pairwise, const u8 *mac_addr)
10409{
10410 EXIT();
10411 return 0;
10412}
10413
10414/**
10415 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10416 * @wiphy: Pointer to wiphy structure.
10417 * @dev: Pointer to net_device structure.
10418 * @key_index: key index
10419 * @pairwise: pairwise
10420 * @mac_addr: mac address
10421 *
10422 * This is the cfg80211 delete key handler function which invokes
10423 * the internal function @__wlan_hdd_cfg80211_del_key with
10424 * SSR protection.
10425 *
10426 * Return: 0 for success, error number on failure.
10427 */
10428static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10429 struct net_device *dev,
10430 u8 key_index,
10431 bool pairwise, const u8 *mac_addr)
10432{
10433 int ret;
10434
10435 cds_ssr_protect(__func__);
10436 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10437 pairwise, mac_addr);
10438 cds_ssr_unprotect(__func__);
10439
10440 return ret;
10441}
10442
10443/*
10444 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10445 * This function is used to set the default tx key index
10446 */
10447static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10448 struct net_device *ndev,
10449 u8 key_index,
10450 bool unicast, bool multicast)
10451{
10452 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10453 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10454 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10455 hdd_context_t *pHddCtx;
10456 int status;
10457
10458 ENTER();
10459
Anurag Chouhan6d760662016-02-20 16:05:43 +053010460 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010461 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010462 return -EINVAL;
10463 }
10464
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010465 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10466 hdd_err("invalid session id: %d", pAdapter->sessionId);
10467 return -EINVAL;
10468 }
10469
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010470 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010471 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10472 pAdapter->sessionId, key_index));
10473
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010474 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010475 hdd_device_mode_to_string(pAdapter->device_mode),
10476 pAdapter->device_mode, key_index);
10477
10478 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010479 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010480 return -EINVAL;
10481 }
10482
10483 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10484 status = wlan_hdd_validate_context(pHddCtx);
10485
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010486 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010487 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010488
Krunal Sonib4326f22016-03-10 13:05:51 -080010489 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10490 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010491 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10492 pHddStaCtx->conn_info.ucEncryptionType) &&
10493 (eCSR_ENCRYPT_TYPE_AES !=
10494 pHddStaCtx->conn_info.ucEncryptionType)) {
10495 /* If default key index is not same as previous one,
10496 * then update the default key index */
10497
10498 tCsrRoamSetKey setKey;
10499 uint32_t roamId = 0xFF;
10500 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10501
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010502 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010503
10504 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010505 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010506 setKey.keyId = key_index;
10507 setKey.keyLength = Keys->KeyLength[key_index];
10508
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010509 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010510 &Keys->KeyMaterial[key_index][0],
10511 Keys->KeyLength[key_index]);
10512
10513 setKey.keyDirection = eSIR_TX_RX;
10514
Anurag Chouhanc5548422016-02-24 18:33:27 +053010515 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010516 &pHddStaCtx->conn_info.bssId);
10517
10518 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10519 pWextState->roamProfile.EncryptionType.
10520 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10521 /* In the case of dynamic wep supplicant hardcodes DWEP type
10522 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10523 * WEP-40 encryption. In this canse the key length is 5 but the
10524 * encryption type is 104 hence checking the key langht(5) and
10525 * encryption type(104) and switching encryption type to 40*/
10526 pWextState->roamProfile.EncryptionType.
10527 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10528 pWextState->roamProfile.mcEncryptionType.
10529 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10530 }
10531
10532 setKey.encType =
10533 pWextState->roamProfile.EncryptionType.
10534 encryptionType[0];
10535
10536 /* Issue set key request */
10537 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10538 pAdapter->sessionId, &setKey,
10539 &roamId);
10540
10541 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010542 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010543 status);
10544 return -EINVAL;
10545 }
10546 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010547 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010548 /* In SoftAp mode setting key direction for default mode */
10549 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10550 pWextState->roamProfile.EncryptionType.encryptionType[0])
10551 && (eCSR_ENCRYPT_TYPE_AES !=
10552 pWextState->roamProfile.EncryptionType.
10553 encryptionType[0])) {
10554 /* Saving key direction for default key index to TX default */
10555 hdd_ap_ctx_t *pAPCtx =
10556 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10557 pAPCtx->wepKey[key_index].keyDirection =
10558 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010559 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010560 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010561 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010562 }
10563 }
10564
10565 EXIT();
10566 return status;
10567}
10568
10569static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10570 struct net_device *ndev,
10571 u8 key_index,
10572 bool unicast, bool multicast)
10573{
10574 int ret;
10575 cds_ssr_protect(__func__);
10576 ret =
10577 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10578 multicast);
10579 cds_ssr_unprotect(__func__);
10580
10581 return ret;
10582}
10583
Abhishek Singhc9941602016-08-09 16:06:22 +053010584/*
10585 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10586 * @wiphy: wiphy pointer
10587 * @channel: channel of the BSS
10588 * @bssid: Bssid of BSS
10589 * @ssid: Ssid of the BSS
10590 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010591 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010592 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010593 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010594#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010595static
Abhishek Singhc9941602016-08-09 16:06:22 +053010596struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10597 struct ieee80211_channel *channel, const u8 *bssid,
10598 const u8 *ssid, size_t ssid_len)
10599{
10600 return cfg80211_get_bss(wiphy, channel, bssid,
10601 ssid,
10602 ssid_len,
10603 WLAN_CAPABILITY_ESS,
10604 WLAN_CAPABILITY_ESS);
10605}
10606#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010607static
Abhishek Singhc9941602016-08-09 16:06:22 +053010608struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10609 struct ieee80211_channel *channel, const u8 *bssid,
10610 const u8 *ssid, size_t ssid_len)
10611{
10612 return cfg80211_get_bss(wiphy, channel, bssid,
10613 ssid,
10614 ssid_len,
10615 IEEE80211_BSS_TYPE_ESS,
10616 IEEE80211_PRIVACY_ANY);
10617}
10618#endif
10619
10620
10621/*
10622 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10623 * interface that BSS might have been lost.
10624 * @pAdapter: adaptor
10625 * @bssid: bssid which might have been lost
10626 *
10627 * Return: bss which is unlinked from kernel cache
10628 */
10629struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10630 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010631{
10632 struct net_device *dev = pAdapter->dev;
10633 struct wireless_dev *wdev = dev->ieee80211_ptr;
10634 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010635 struct cfg80211_bss *bss = NULL;
10636
Abhishek Singhc9941602016-08-09 16:06:22 +053010637 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10638 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010639 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010640 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010641 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010642 hdd_info("cfg80211_unlink_bss called for BSSID "
10643 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010644 cfg80211_unlink_bss(wiphy, bss);
10645 }
10646 return bss;
10647}
10648
Abhishek Singhc9941602016-08-09 16:06:22 +053010649
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010650/**
10651 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10652 * @pAdapter: Pointer to adapter
10653 * @bss_desc: Pointer to bss descriptor
10654 *
10655 * This function is used to inform the BSS details to nl80211 interface.
10656 *
10657 * Return: struct cfg80211_bss pointer
10658 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010659struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10660 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010661{
10662 /*
10663 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10664 * already exists in bss data base of cfg80211 for that particular BSS
10665 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10666 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10667 * As of now there is no possibility to get the mgmt(probe response)
10668 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10669 * and passing to cfg80211_inform_bss_frame.
10670 */
10671 struct net_device *dev = pAdapter->dev;
10672 struct wireless_dev *wdev = dev->ieee80211_ptr;
10673 struct wiphy *wiphy = wdev->wiphy;
10674 int chan_no = bss_desc->channelId;
10675#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10676 qcom_ie_age *qie_age = NULL;
10677 int ie_length =
10678 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10679#else
10680 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10681#endif
10682 const char *ie =
10683 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10684 unsigned int freq;
10685 struct ieee80211_channel *chan;
10686 struct ieee80211_mgmt *mgmt = NULL;
10687 struct cfg80211_bss *bss_status = NULL;
10688 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10689 int rssi = 0;
10690 hdd_context_t *pHddCtx;
10691 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010692 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010693 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010694
10695 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10696 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010697 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010698 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010699
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010700 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010701 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10702 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010703 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010704 return NULL;
10705 }
10706
10707 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10708
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010709 /* Android does not want the timestamp from the frame.
10710 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010711 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010712 mgmt->u.probe_resp.timestamp =
10713 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010714
10715 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10716 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10717
10718#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10719 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10720 /* Assuming this is the last IE, copy at the end */
10721 ie_length -= sizeof(qcom_ie_age);
10722 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10723 qie_age->element_id = QCOM_VENDOR_IE_ID;
10724 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10725 qie_age->oui_1 = QCOM_OUI1;
10726 qie_age->oui_2 = QCOM_OUI2;
10727 qie_age->oui_3 = QCOM_OUI3;
10728 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053010729 /*
10730 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
10731 * all bss related timestamp is in units of ms. Due to this when scan
10732 * results are sent to lowi the scan age is high.To address this,
10733 * send age in units of 1/10 ms.
10734 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010735 qie_age->age =
Deepthi Gowri6acee342016-10-28 15:00:38 +053010736 (qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010737 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010738 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10739 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010740 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10741 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010742#endif
10743
10744 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10745 if (bss_desc->fProbeRsp) {
10746 mgmt->frame_control |=
10747 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10748 } else {
10749 mgmt->frame_control |=
10750 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10751 }
10752
10753 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070010754 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010755 freq =
10756 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010757 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010758 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070010759 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010760 freq =
10761 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010762 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010763 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010764 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010765 kfree(mgmt);
10766 return NULL;
10767 }
10768
10769 chan = __ieee80211_get_channel(wiphy, freq);
10770 /* When the band is changed on the fly using the GUI, three things are done
10771 * 1. scan abort
10772 * 2. flush scan results from cache
10773 * 3. update the band with the new band user specified (refer to the
10774 * hdd_set_band_helper function) as part of the scan abort, message will be
10775 * queued to PE and we proceed with flushing and changinh the band.
10776 * PE will stop the scanning further and report back the results what ever
10777 * it had till now by calling the call back function.
10778 * if the time between update band and scandone call back is sufficient
10779 * enough the band change reflects in SME, SME validates the channels
10780 * and discards the channels correponding to previous band and calls back
10781 * with zero bss results. but if the time between band update and scan done
10782 * callback is very small then band change will not reflect in SME and SME
10783 * reports to HDD all the channels correponding to previous band.this is due
10784 * to race condition.but those channels are invalid to the new band and so
10785 * this function __ieee80211_get_channel will return NULL.Each time we
10786 * report scan result with this pointer null warning kernel trace is printed.
10787 * if the scan results contain large number of APs continuosly kernel
10788 * warning trace is printed and it will lead to apps watch dog bark.
10789 * So drop the bss and continue to next bss.
10790 */
10791 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010792 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10793 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010794 kfree(mgmt);
10795 return NULL;
10796 }
10797
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010798 /* Based on .ini configuration, raw rssi can be reported for bss.
10799 * Raw rssi is typically used for estimating power.
10800 */
10801
10802 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10803 bss_desc->rssi;
10804
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010805 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010806 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010807
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010808 hdd_notice("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010809 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010810 (int)(rssi / 100),
10811 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010812
10813 bss_status =
10814 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10815 GFP_KERNEL);
10816 kfree(mgmt);
10817 return bss_status;
10818}
10819
10820/**
10821 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10822 * @pAdapter: Pointer to adapter
10823 * @pRoamInfo: Pointer to roam info
10824 *
10825 * This function is used to update the BSS data base of CFG8011
10826 *
10827 * Return: struct cfg80211_bss pointer
10828 */
10829struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10830 tCsrRoamInfo *pRoamInfo)
10831{
10832 tCsrRoamConnectedProfile roamProfile;
10833 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10834 struct cfg80211_bss *bss = NULL;
10835
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010836 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10837 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10838
10839 if (NULL != roamProfile.pBssDesc) {
10840 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10841 roamProfile.pBssDesc);
10842
10843 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010844 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010845
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010846 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010847 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010848 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010849 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010850 return bss;
10851}
10852/**
10853 * wlan_hdd_cfg80211_update_bss() - update bss
10854 * @wiphy: Pointer to wiphy
10855 * @pAdapter: Pointer to adapter
10856 * @scan_time: scan request timestamp
10857 *
10858 * Return: zero if success, non-zero otherwise
10859 */
10860int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10861 hdd_adapter_t *pAdapter,
10862 uint32_t scan_time)
10863{
10864 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10865 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010866 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010867 tScanResultHandle pResult;
10868 struct cfg80211_bss *bss_status = NULL;
10869 hdd_context_t *pHddCtx;
10870 int ret;
10871
10872 ENTER();
10873
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010874 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10875 hdd_err("invalid session id: %d", pAdapter->sessionId);
10876 return -EINVAL;
10877 }
10878
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010879 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010880 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10881 NO_SESSION, pAdapter->sessionId));
10882
10883 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10884 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010885 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010886 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010887
10888 /* start getting scan results and populate cgf80211 BSS database */
10889 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
10890
10891 /* no scan results */
10892 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010893 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053010894 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010895 }
10896
10897 pScanResult = sme_scan_result_get_first(hHal, pResult);
10898
10899 while (pScanResult) {
10900 /*
10901 * - cfg80211_inform_bss() is not updating ie field of bss
10902 * entry if entry already exists in bss data base of cfg80211
10903 * for that particular BSS ID. Using cfg80211_inform_bss_frame
10904 * to update thebss entry instead of cfg80211_inform_bss,
10905 * But this call expects mgmt packet as input. As of now
10906 * there is no possibility to get the mgmt(probe response)
10907 * frame from PE, converting bss_desc to
10908 * ieee80211_mgmt(probe response) and passing to c
10909 * fg80211_inform_bss_frame.
10910 * - Update BSS only if beacon timestamp is later than
10911 * scan request timestamp.
10912 */
10913 if ((scan_time == 0) ||
10914 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053010915 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010916 bss_status =
10917 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10918 &pScanResult->BssDescriptor);
10919
10920 if (NULL == bss_status) {
10921 hdd_info("NULL returned by cfg80211_inform_bss_frame");
10922 } else {
10923 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010924 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010925 bss_status);
10926 }
10927 } else {
10928 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
10929 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
10930 }
10931 pScanResult = sme_scan_result_get_next(hHal, pResult);
10932 }
10933
10934 sme_scan_result_purge(hHal, pResult);
10935 /*
10936 * For SAP mode, scan is invoked by hostapd during SAP start
10937 * if hostapd is restarted, we need to flush previous scan
10938 * result so that it will reflect environment change
10939 */
Krunal Sonib4326f22016-03-10 13:05:51 -080010940 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010941#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
10942 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
10943#endif
10944 )
10945 sme_scan_flush_result(hHal);
10946
10947 EXIT();
10948 return 0;
10949}
10950
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010951/**
10952 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
10953 * @pAdapter: Pointer to adapter
10954 * @pRoamInfo: Pointer to roam info
10955 * @index: Index
10956 * @preauth: Preauth flag
10957 *
10958 * This function is used to notify the supplicant of a new PMKSA candidate.
10959 *
10960 * Return: 0 for success, non-zero for failure
10961 */
10962int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
10963 tCsrRoamInfo *pRoamInfo,
10964 int index, bool preauth)
10965{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010966 struct net_device *dev = pAdapter->dev;
10967 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
10968
10969 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010970 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010971
10972 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010973 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010974 return -EINVAL;
10975 }
10976
10977 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010978 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010979 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
10980 cfg80211_pmksa_candidate_notify(dev, index,
10981 pRoamInfo->bssid.bytes,
10982 preauth, GFP_KERNEL);
10983 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010984 return 0;
10985}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010986
10987#ifdef FEATURE_WLAN_LFR_METRICS
10988/**
10989 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
10990 * @pAdapter: Pointer to adapter
10991 * @pRoamInfo: Pointer to roam info
10992 *
10993 * 802.11r/LFR metrics reporting function to report preauth initiation
10994 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010995 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010996 */
10997#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010998QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010999 tCsrRoamInfo *pRoamInfo)
11000{
11001 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11002 union iwreq_data wrqu;
11003
11004 ENTER();
11005
11006 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011007 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011008 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011009 }
11010
11011 /* create the event */
11012 memset(&wrqu, 0, sizeof(wrqu));
11013 memset(metrics_notification, 0, sizeof(metrics_notification));
11014
11015 wrqu.data.pointer = metrics_notification;
11016 wrqu.data.length = scnprintf(metrics_notification,
11017 sizeof(metrics_notification),
11018 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
11019 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11020
11021 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11022 metrics_notification);
11023
11024 EXIT();
11025
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011026 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011027}
11028
11029/**
11030 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11031 * @pAdapter: Pointer to adapter
11032 * @pRoamInfo: Pointer to roam info
11033 * @preauth_status: Preauth status
11034 *
11035 * 802.11r/LFR metrics reporting function to report handover initiation
11036 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011037 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011038 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011039QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011040wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
11041 tCsrRoamInfo *pRoamInfo,
11042 bool preauth_status)
11043{
11044 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11045 union iwreq_data wrqu;
11046
11047 ENTER();
11048
11049 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011050 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011051 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011052 }
11053
11054 /* create the event */
11055 memset(&wrqu, 0, sizeof(wrqu));
11056 memset(metrics_notification, 0, sizeof(metrics_notification));
11057
11058 scnprintf(metrics_notification, sizeof(metrics_notification),
11059 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
11060 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11061
11062 if (1 == preauth_status)
11063 strlcat(metrics_notification, " true",
11064 sizeof(metrics_notification));
11065 else
11066 strlcat(metrics_notification, " false",
11067 sizeof(metrics_notification));
11068
11069 wrqu.data.pointer = metrics_notification;
11070 wrqu.data.length = strlen(metrics_notification);
11071
11072 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11073 metrics_notification);
11074
11075 EXIT();
11076
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011077 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011078}
11079
11080/**
11081 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11082 * @pAdapter: Pointer to adapter
11083 * @pRoamInfo: Pointer to roam info
11084 *
11085 * 802.11r/LFR metrics reporting function to report handover initiation
11086 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011087 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011088 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011089QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011090 tCsrRoamInfo *pRoamInfo)
11091{
11092 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11093 union iwreq_data wrqu;
11094
11095 ENTER();
11096
11097 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011098 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011099 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011100 }
11101
11102 /* create the event */
11103 memset(&wrqu, 0, sizeof(wrqu));
11104 memset(metrics_notification, 0, sizeof(metrics_notification));
11105
11106 wrqu.data.pointer = metrics_notification;
11107 wrqu.data.length = scnprintf(metrics_notification,
11108 sizeof(metrics_notification),
11109 "QCOM: LFR_PREAUTH_HANDOVER "
11110 MAC_ADDRESS_STR,
11111 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11112
11113 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11114 metrics_notification);
11115
11116 EXIT();
11117
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011118 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011119}
11120#endif
11121
11122/**
11123 * hdd_select_cbmode() - select channel bonding mode
11124 * @pAdapter: Pointer to adapter
11125 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011126 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011127 *
11128 * Return: none
11129 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011130void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11131 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011132{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011133 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011134 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011135 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011136
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011137 /*
11138 * CDS api expects secondary channel for calculating
11139 * the channel params
11140 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011141 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011142 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11143 if (operationChannel >= 1 && operationChannel <= 5)
11144 sec_ch = operationChannel + 4;
11145 else if (operationChannel >= 6 && operationChannel <= 13)
11146 sec_ch = operationChannel - 4;
11147 }
11148
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011149 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011150 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011151
11152 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011153 eHddDot11Mode hdd_dot11_mode;
11154 uint8_t iniDot11Mode =
11155 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11156
11157 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11158 switch (iniDot11Mode) {
11159 case eHDD_DOT11_MODE_AUTO:
11160 case eHDD_DOT11_MODE_11ac:
11161 case eHDD_DOT11_MODE_11ac_ONLY:
11162 if (sme_is_feature_supported_by_fw(DOT11AC))
11163 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11164 else
11165 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11166 break;
11167 case eHDD_DOT11_MODE_11n:
11168 case eHDD_DOT11_MODE_11n_ONLY:
11169 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11170 break;
11171 default:
11172 hdd_dot11_mode = iniDot11Mode;
11173 break;
11174 }
11175 ch_info->channel_width = ch_params->ch_width;
11176 ch_info->phy_mode =
11177 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011178 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011179 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011180 hdd_info("ch_info width %d, phymode %d channel %d",
11181 ch_info->channel_width, ch_info->phy_mode,
11182 ch_info->channel);
11183 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011184}
11185
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011186/**
11187 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11188 * @adapter: STA adapter
11189 * @roam_profile: STA roam profile
11190 *
11191 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11192 *
11193 * Return: false if sta-sap conc is not allowed, else return true
11194 */
11195static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11196 tCsrRoamProfile *roam_profile)
11197{
11198 hdd_context_t *hdd_ctx;
11199 hdd_adapter_t *ap_adapter;
11200 hdd_ap_ctx_t *hdd_ap_ctx;
11201 hdd_hostapd_state_t *hostapd_state;
11202 uint8_t channel = 0;
11203 QDF_STATUS status;
11204
11205 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11206 if (!hdd_ctx) {
11207 hdd_err("HDD context is NULL");
11208 return true;
11209 }
11210
11211 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11212 /* probably no sap running, no handling required */
11213 if (ap_adapter == NULL)
11214 return true;
11215
11216 /*
11217 * sap is not in started state, so it is fine to go ahead with sta.
11218 * if sap is currently doing CAC then don't allow sta to go further.
11219 */
11220 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11221 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11222 return true;
11223
11224 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11225 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11226 return false;
11227 }
11228
11229 /*
11230 * log and return error, if we allow STA to go through, we don't
11231 * know what is going to happen better stop sta connection
11232 */
11233 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11234 if (NULL == hdd_ap_ctx) {
11235 hdd_err("AP context not found");
11236 return false;
11237 }
11238
11239 /* sap is on non-dfs channel, nothing to handle */
11240 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11241 hdd_info("sap is on non-dfs channel, sta is allowed");
11242 return true;
11243 }
11244 /*
11245 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011246 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011247 */
11248 status = cds_get_channel_from_scan_result(adapter,
11249 roam_profile, &channel);
11250
Nitesh Shah59774522016-09-16 15:14:21 +053011251 /*
11252 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11253 * channels for roaming case.
11254 */
11255 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11256 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11257 return true;
11258 }
11259
11260 /*
11261 * If channel is 0 or DFS then better to call pcl and find out the
11262 * best channel. If channel is non-dfs 5 GHz then better move SAP
11263 * to STA's channel to make scc, so we have room for 3port MCC
11264 * scenario.
11265 */
11266 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011267 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11268 true);
11269
11270 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11271 qdf_event_reset(&hostapd_state->qdf_event);
11272 status = wlansap_set_channel_change_with_csa(
11273 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11274 hdd_ap_ctx->sapConfig.ch_width_orig);
11275
11276 if (QDF_STATUS_SUCCESS != status) {
11277 hdd_err("Set channel with CSA IE failed, can't allow STA");
11278 return false;
11279 }
11280
11281 /*
11282 * wait here for SAP to finish the channel switch. When channel
11283 * switch happens, SAP sends few beacons with CSA_IE. After
11284 * successfully Transmission of those beacons, it will move its
11285 * state from started to disconnected and move to new channel.
11286 * once it moves to new channel, sap again moves its state
11287 * machine from disconnected to started and set this event.
11288 * wait for 10 secs to finish this.
11289 */
11290 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11291 if (!QDF_IS_STATUS_SUCCESS(status)) {
11292 hdd_err("wait for qdf_event failed, STA not allowed!!");
11293 return false;
11294 }
11295
11296 return true;
11297}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011298
Krunal Soni31949422016-07-29 17:17:53 -070011299/**
11300 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011301 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011302 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011303 * @ssid_len: Length of ssid
11304 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011305 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011306 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011307 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011308 *
11309 * This function is used to start the association process
11310 *
11311 * Return: 0 for success, non-zero for failure
11312 */
Krunal Soni31949422016-07-29 17:17:53 -070011313static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011314 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011315 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011316 u8 operatingChannel,
11317 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011318{
11319 int status = 0;
11320 hdd_wext_state_t *pWextState;
11321 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011322 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011323 uint32_t roamId;
11324 tCsrRoamProfile *pRoamProfile;
11325 eCsrAuthType RSNAuthType;
11326 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011327 uint8_t channel = 0;
11328 struct sir_hw_mode_params hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011329
11330 ENTER();
11331
11332 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11333 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011334 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011335
11336 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011337 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011338 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011339
11340 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011341 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011342 return -EINVAL;
11343 }
11344
11345 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011346 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11347 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011348
11349 if (pRoamProfile) {
11350 hdd_station_ctx_t *pHddStaCtx;
11351 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11352
11353 if (HDD_WMM_USER_MODE_NO_QOS ==
11354 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11355 /*QoS not enabled in cfg file */
11356 pRoamProfile->uapsd_mask = 0;
11357 } else {
11358 /*QoS enabled, update uapsd mask from cfg file */
11359 pRoamProfile->uapsd_mask =
11360 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11361 }
11362
11363 pRoamProfile->SSIDs.numOfSSIDs = 1;
11364 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011365 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011366 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011367 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011368 ssid, ssid_len);
11369
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011370 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011371 if (bssid) {
11372 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011373 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011374 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011375 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011376 /*
11377 * Save BSSID in seperate variable as
11378 * pRoamProfile's BSSID is getting zeroed out in the
11379 * association process. In case of join failure
11380 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011381 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011382 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011383 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011384 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011385 } else if (bssid_hint) {
11386 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011387 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011388 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011389 /*
11390 * Save BSSID in a separate variable as
11391 * pRoamProfile's BSSID is getting zeroed out in the
11392 * association process. In case of join failure
11393 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011394 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011395 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011396 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011397 hdd_info("bssid_hint is given by upper layer %pM",
11398 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011399 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011400 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011401 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011402 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011403 }
11404
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011405 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011406 pRoamProfile->SSIDs.SSIDList->SSID.length,
11407 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11408 operatingChannel);
11409
11410 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11411 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011412 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011413 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11414 }
11415#ifdef FEATURE_WLAN_WAPI
11416 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011417 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011418 switch (pAdapter->wapi_info.wapiAuthMode) {
11419 case WAPI_AUTH_MODE_PSK:
11420 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011421 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011422 pAdapter->wapi_info.wapiAuthMode);
11423 pRoamProfile->AuthType.authType[0] =
11424 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11425 break;
11426 }
11427 case WAPI_AUTH_MODE_CERT:
11428 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011429 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011430 pAdapter->wapi_info.wapiAuthMode);
11431 pRoamProfile->AuthType.authType[0] =
11432 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11433 break;
11434 }
11435 } /* End of switch */
11436 if (pAdapter->wapi_info.wapiAuthMode ==
11437 WAPI_AUTH_MODE_PSK
11438 || pAdapter->wapi_info.wapiAuthMode ==
11439 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011440 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011441 pRoamProfile->AuthType.numEntries = 1;
11442 pRoamProfile->EncryptionType.numEntries = 1;
11443 pRoamProfile->EncryptionType.encryptionType[0] =
11444 eCSR_ENCRYPT_TYPE_WPI;
11445 pRoamProfile->mcEncryptionType.numEntries = 1;
11446 pRoamProfile->mcEncryptionType.
11447 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11448 }
11449 }
Krunal Soni31949422016-07-29 17:17:53 -070011450#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011451#ifdef WLAN_FEATURE_GTK_OFFLOAD
11452 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011453 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11454 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011455 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11456 sizeof(tSirGtkOffloadParams));
11457 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11458 GTK_OFFLOAD_DISABLE;
11459 }
11460#endif
11461 pRoamProfile->csrPersona = pAdapter->device_mode;
11462
11463 if (operatingChannel) {
11464 pRoamProfile->ChannelInfo.ChannelList =
11465 &operatingChannel;
11466 pRoamProfile->ChannelInfo.numOfChannels = 1;
11467 } else {
11468 pRoamProfile->ChannelInfo.ChannelList = NULL;
11469 pRoamProfile->ChannelInfo.numOfChannels = 0;
11470 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011471 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011472 && operatingChannel) {
11473 /*
11474 * Need to post the IBSS power save parameters
11475 * to WMA. WMA will configure this parameters
11476 * to firmware if power save is enabled by the
11477 * firmware.
11478 */
11479 status = hdd_set_ibss_power_save_params(pAdapter);
11480
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011481 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011482 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011483 return -EINVAL;
11484 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011485 pRoamProfile->ch_params.ch_width =
11486 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011487 /*
11488 * In IBSS mode while operating in 2.4 GHz,
11489 * the device supports only 20 MHz.
11490 */
11491 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11492 pRoamProfile->ch_params.ch_width =
11493 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011494 hdd_select_cbmode(pAdapter, operatingChannel,
11495 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011496 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011497 /*
11498 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11499 * or pmf=2 is an explicit configuration in the supplicant
11500 * configuration, drop the connection request.
11501 */
11502 if (pWextState->roamProfile.MFPEnabled &&
11503 !(pWextState->roamProfile.MFPRequired ||
11504 pWextState->roamProfile.MFPCapable)) {
11505 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11506 pWextState->roamProfile.MFPEnabled,
11507 pWextState->roamProfile.MFPRequired,
11508 pWextState->roamProfile.MFPCapable);
11509 return -EINVAL;
11510 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011511
Krunal Soni3091bcc2016-06-23 12:28:21 -070011512 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011513 hdd_err("Connection refused: conn in progress");
11514 return -EINVAL;
11515 }
11516
Krunal Soni31949422016-07-29 17:17:53 -070011517 /*
11518 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011519 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011520 * enhancements, the supplicant is not issuing the scan command
11521 * now. So the unicast frames which are sent from the host are
11522 * not having the additional IEs. If it is P2P CLIENT and there
11523 * is no additional IE present in roamProfile, then use the
11524 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011525 */
11526
Krunal Sonib4326f22016-03-10 13:05:51 -080011527 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011528 (!pRoamProfile->pAddIEScan)) {
11529 pRoamProfile->pAddIEScan =
11530 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11531 pRoamProfile->nAddIEScanLength =
11532 pAdapter->scan_info.scanAddIE.length;
11533 }
11534 /*
11535 * When policy manager is enabled from ini file, we shouldn't
11536 * check for other concurrency rules.
11537 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011538 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011539 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011540 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011541 pAdapter, pRoamProfile, &roamId))
11542 return 0;
11543 }
11544
Krunal Soni3091bcc2016-06-23 12:28:21 -070011545 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011546 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11547 pRoamProfile))) {
11548 hdd_err("sap-sta conc will fail, can't allow sta");
11549 hdd_conn_set_connection_state(pAdapter,
11550 eConnectionState_NotConnected);
11551 return -ENOMEM;
11552 }
11553
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011554 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011555 if (!sme_config) {
11556 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011557 hdd_conn_set_connection_state(pAdapter,
11558 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011559 return -ENOMEM;
11560 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011561 sme_get_config_param(pHddCtx->hHal, sme_config);
11562 /* These values are not sessionized. So, any change in these SME
11563 * configs on an older or parallel interface will affect the
11564 * cb mode. So, restoring the default INI params before starting
11565 * interfaces such as sta, cli etc.,
11566 */
11567 sme_config->csrConfig.channelBondingMode5GHz =
11568 pHddCtx->config->nChannelBondingMode5GHz;
11569 sme_config->csrConfig.channelBondingMode24GHz =
11570 pHddCtx->config->nChannelBondingMode24GHz;
11571 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011572 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011573 /*
11574 * Change conn_state to connecting before sme_roam_connect(),
11575 * because sme_roam_connect() has a direct path to call
11576 * hdd_sme_roam_callback(), which will change the conn_state
11577 * If direct path, conn_state will be accordingly changed to
11578 * NotConnected or Associated by either
11579 * hdd_association_completion_handler() or
11580 * hdd_dis_connect_handler() in sme_RoamCallback()if
11581 * sme_RomConnect is to be queued,
11582 * Connecting state will remain until it is completed.
11583 *
11584 * If connection state is not changed, connection state will
11585 * remain in eConnectionState_NotConnected state.
11586 * In hdd_association_completion_handler, "hddDisconInProgress"
11587 * is set to true if conn state is
11588 * eConnectionState_NotConnected.
11589 * If "hddDisconInProgress" is set to true then cfg80211 layer
11590 * is not informed of connect result indication which
11591 * is an issue.
11592 */
11593 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011594 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011595 hdd_conn_set_connection_state(pAdapter,
11596 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011597
Komal Seelama89be8d2016-09-29 11:09:26 +053011598 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
11599 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011600 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11601 pAdapter->sessionId, pRoamProfile,
11602 &roamId);
11603
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011604 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011605 (QDF_STA_MODE == pAdapter->device_mode ||
11606 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011607 hdd_err("sme_roam_connect (session %d) failed with "
11608 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011609 pAdapter->sessionId, status);
11610 /* change back to NotAssociated */
11611 hdd_conn_set_connection_state(pAdapter,
11612 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053011613 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
11614 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011615 }
11616
11617 pRoamProfile->ChannelInfo.ChannelList = NULL;
11618 pRoamProfile->ChannelInfo.numOfChannels = 0;
11619
Nitesh Shah044fd672016-10-13 18:53:25 +053011620 if (!QDF_IS_STATUS_SUCCESS(
11621 wma_get_current_hw_mode(&hw_mode))) {
11622 hdd_err("wma_get_current_hw_mode failed");
11623 return status;
11624 }
11625
11626 if ((QDF_STA_MODE == pAdapter->device_mode)
11627 && hw_mode.dbs_cap) {
11628 cds_get_channel_from_scan_result(pAdapter,
11629 pRoamProfile, &channel);
11630 if (channel)
11631 cds_checkn_update_hw_mode_single_mac_mode
11632 (channel);
11633 }
11634
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011635 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011636 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011637 return -EINVAL;
11638 }
11639 EXIT();
11640 return status;
11641}
11642
11643/**
11644 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11645 * @pAdapter: Pointer to adapter
11646 * @auth_type: Auth type
11647 *
11648 * This function is used to set the authentication type (OPEN/SHARED).
11649 *
11650 * Return: 0 for success, non-zero for failure
11651 */
11652static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11653 enum nl80211_auth_type auth_type)
11654{
11655 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11656 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11657
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658 /*set authentication type */
11659 switch (auth_type) {
11660 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011661 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011662 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11663 break;
11664
11665 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011666 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011667 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011668 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11669 break;
11670
11671 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011672 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011673 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11674 break;
11675#ifdef FEATURE_WLAN_ESE
11676 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011677 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011678 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11679 break;
11680#endif
11681
11682 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011683 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011684 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11685 return -EINVAL;
11686 }
11687
11688 pWextState->roamProfile.AuthType.authType[0] =
11689 pHddStaCtx->conn_info.authType;
11690 return 0;
11691}
11692
11693/**
11694 * wlan_hdd_set_akm_suite() - set key management type
11695 * @pAdapter: Pointer to adapter
11696 * @key_mgmt: Key management type
11697 *
11698 * This function is used to set the key mgmt type(PSK/8021x).
11699 *
11700 * Return: 0 for success, non-zero for failure
11701 */
11702static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11703{
11704 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11705
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011706#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11707#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11708 /*set key mgmt type */
11709 switch (key_mgmt) {
11710 case WLAN_AKM_SUITE_PSK:
11711 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011712 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011713 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011714 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11715 break;
11716
11717 case WLAN_AKM_SUITE_8021X_SHA256:
11718 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011719 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011720 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011721 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11722 break;
11723#ifdef FEATURE_WLAN_ESE
11724#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11725#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11726 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011727 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011728 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11729 break;
11730#endif
11731#ifndef WLAN_AKM_SUITE_OSEN
11732#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11733#endif
11734 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011735 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011736 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11737 break;
11738
11739 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011740 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011741 return -EINVAL;
11742
11743 }
11744 return 0;
11745}
11746
11747/**
11748 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11749 * @pAdapter: Pointer to adapter
11750 * @cipher: Cipher type
11751 * @ucast: Unicast flag
11752 *
11753 * This function is used to set the encryption type
11754 * (NONE/WEP40/WEP104/TKIP/CCMP).
11755 *
11756 * Return: 0 for success, non-zero for failure
11757 */
11758static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11759 u32 cipher, bool ucast)
11760{
11761 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11762 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11763 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11764
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011765 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011766 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011767 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11768 } else {
11769
11770 /*set encryption method */
11771 switch (cipher) {
11772 case IW_AUTH_CIPHER_NONE:
11773 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11774 break;
11775
11776 case WLAN_CIPHER_SUITE_WEP40:
11777 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11778 break;
11779
11780 case WLAN_CIPHER_SUITE_WEP104:
11781 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11782 break;
11783
11784 case WLAN_CIPHER_SUITE_TKIP:
11785 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11786 break;
11787
11788 case WLAN_CIPHER_SUITE_CCMP:
11789 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11790 break;
11791#ifdef FEATURE_WLAN_WAPI
11792 case WLAN_CIPHER_SUITE_SMS4:
11793 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11794 break;
11795#endif
11796
11797#ifdef FEATURE_WLAN_ESE
11798 case WLAN_CIPHER_SUITE_KRK:
11799 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11800 break;
11801#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11802 case WLAN_CIPHER_SUITE_BTK:
11803 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11804 break;
11805#endif
11806#endif
11807 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011808 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011809 return -EOPNOTSUPP;
11810 }
11811 }
11812
11813 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011814 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011815 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11816 pWextState->roamProfile.EncryptionType.numEntries = 1;
11817 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11818 encryptionType;
11819 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011820 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011821 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11822 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11823 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11824 encryptionType;
11825 }
11826
11827 return 0;
11828}
11829
11830/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011831 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11832 * @wext_state: Pointer to wext state
11833 * @gen_ie: Pointer to IE data
11834 * @len: length of IE data
11835 *
11836 * Return: 0 for success, non-zero for failure
11837 */
11838static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11839 const uint8_t *gen_ie, uint16_t len)
11840{
11841 uint16_t cur_add_ie_len =
11842 wext_state->assocAddIE.length;
11843
11844 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11845 (wext_state->assocAddIE.length + len)) {
11846 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11847 QDF_ASSERT(0);
11848 return -ENOMEM;
11849 }
11850 memcpy(wext_state->assocAddIE.addIEdata +
11851 cur_add_ie_len, gen_ie, len);
11852 wext_state->assocAddIE.length += len;
11853
11854 wext_state->roamProfile.pAddIEAssoc =
11855 wext_state->assocAddIE.addIEdata;
11856 wext_state->roamProfile.nAddIEAssocLength =
11857 wext_state->assocAddIE.length;
11858 return 0;
11859}
11860
11861/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011862 * wlan_hdd_cfg80211_set_ie() - set IEs
11863 * @pAdapter: Pointer to adapter
11864 * @ie: Pointer ot ie
11865 * @ie: IE length
11866 *
11867 * Return: 0 for success, non-zero for failure
11868 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011869static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011870 size_t ie_len)
11871{
11872 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11873 const uint8_t *genie = ie;
11874 uint16_t remLen = ie_len;
11875#ifdef FEATURE_WLAN_WAPI
11876 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
11877 u16 *tmp;
11878 uint16_t akmsuiteCount;
11879 int *akmlist;
11880#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011881 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011882
11883 /* clear previous assocAddIE */
11884 pWextState->assocAddIE.length = 0;
11885 pWextState->roamProfile.bWPSAssociation = false;
11886 pWextState->roamProfile.bOSENAssociation = false;
11887
11888 while (remLen >= 2) {
11889 uint16_t eLen = 0;
11890 uint8_t elementId;
11891 elementId = *genie++;
11892 eLen = *genie++;
11893 remLen -= 2;
11894
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011895 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011896
11897 switch (elementId) {
11898 case DOT11F_EID_WPA:
11899 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 -070011900 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011901 return -EINVAL;
11902 } else if (0 ==
11903 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
11904 uint16_t curAddIELen =
11905 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011906 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011907
11908 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11909 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011910 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011911 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011912 return -ENOMEM;
11913 }
11914 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11915 memcpy(pWextState->assocAddIE.addIEdata +
11916 curAddIELen, genie - 2, eLen + 2);
11917 pWextState->assocAddIE.length += eLen + 2;
11918
11919 pWextState->roamProfile.bWPSAssociation = true;
11920 pWextState->roamProfile.pAddIEAssoc =
11921 pWextState->assocAddIE.addIEdata;
11922 pWextState->roamProfile.nAddIEAssocLength =
11923 pWextState->assocAddIE.length;
11924 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011925 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011926 memset(pWextState->WPARSNIE, 0,
11927 MAX_WPA_RSN_IE_LEN);
11928 memcpy(pWextState->WPARSNIE, genie - 2,
11929 (eLen + 2));
11930 pWextState->roamProfile.pWPAReqIE =
11931 pWextState->WPARSNIE;
11932 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
11933 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
11934 P2P_OUI_TYPE_SIZE))) {
11935 uint16_t curAddIELen =
11936 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011937 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011938
11939 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11940 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011941 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011942 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011943 return -ENOMEM;
11944 }
11945 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11946 memcpy(pWextState->assocAddIE.addIEdata +
11947 curAddIELen, genie - 2, eLen + 2);
11948 pWextState->assocAddIE.length += eLen + 2;
11949
11950 pWextState->roamProfile.pAddIEAssoc =
11951 pWextState->assocAddIE.addIEdata;
11952 pWextState->roamProfile.nAddIEAssocLength =
11953 pWextState->assocAddIE.length;
11954 }
11955#ifdef WLAN_FEATURE_WFD
11956 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
11957 WFD_OUI_TYPE_SIZE)) &&
11958 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080011959 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011960 pAdapter->device_mode)) {
11961 uint16_t curAddIELen =
11962 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011963 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011964
11965 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11966 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011967 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011968 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011969 return -ENOMEM;
11970 }
11971 /* WFD IE is saved to Additional IE ; it should
11972 * be accumulated to handle WPS IE + P2P IE +
11973 * WFD IE */
11974 memcpy(pWextState->assocAddIE.addIEdata +
11975 curAddIELen, genie - 2, eLen + 2);
11976 pWextState->assocAddIE.length += eLen + 2;
11977
11978 pWextState->roamProfile.pAddIEAssoc =
11979 pWextState->assocAddIE.addIEdata;
11980 pWextState->roamProfile.nAddIEAssocLength =
11981 pWextState->assocAddIE.length;
11982 }
11983#endif
11984 /* Appending HS 2.0 Indication Element in Assiciation Request */
11985 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
11986 HS20_OUI_TYPE_SIZE))) {
11987 uint16_t curAddIELen =
11988 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011989 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011990
11991 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11992 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011993 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011994 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011995 return -ENOMEM;
11996 }
11997 memcpy(pWextState->assocAddIE.addIEdata +
11998 curAddIELen, genie - 2, eLen + 2);
11999 pWextState->assocAddIE.length += eLen + 2;
12000
12001 pWextState->roamProfile.pAddIEAssoc =
12002 pWextState->assocAddIE.addIEdata;
12003 pWextState->roamProfile.nAddIEAssocLength =
12004 pWextState->assocAddIE.length;
12005 }
12006 /* Appending OSEN Information Element in Assiciation Request */
12007 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
12008 OSEN_OUI_TYPE_SIZE))) {
12009 uint16_t curAddIELen =
12010 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012011 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012012
12013 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12014 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012015 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012016 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012017 return -ENOMEM;
12018 }
12019 memcpy(pWextState->assocAddIE.addIEdata +
12020 curAddIELen, genie - 2, eLen + 2);
12021 pWextState->assocAddIE.length += eLen + 2;
12022
12023 pWextState->roamProfile.bOSENAssociation = true;
12024 pWextState->roamProfile.pAddIEAssoc =
12025 pWextState->assocAddIE.addIEdata;
12026 pWextState->roamProfile.nAddIEAssocLength =
12027 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012028 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
12029 MBO_OUI_TYPE_SIZE))){
12030 hdd_info("Set MBO IE(len %d)", eLen + 2);
12031 status = wlan_hdd_add_assoc_ie(pWextState,
12032 genie - 2, eLen + 2);
12033 if (status)
12034 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012035 } else {
12036 uint16_t add_ie_len =
12037 pWextState->assocAddIE.length;
12038
12039 hdd_info("Set OSEN IE(len %d)", eLen + 2);
12040
12041 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12042 (pWextState->assocAddIE.length + eLen)) {
12043 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012044 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012045 return -ENOMEM;
12046 }
12047
12048 memcpy(pWextState->assocAddIE.addIEdata +
12049 add_ie_len, genie - 2, eLen + 2);
12050 pWextState->assocAddIE.length += eLen + 2;
12051
12052 pWextState->roamProfile.pAddIEAssoc =
12053 pWextState->assocAddIE.addIEdata;
12054 pWextState->roamProfile.nAddIEAssocLength =
12055 pWextState->assocAddIE.length;
12056 }
12057 break;
12058 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012059 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012060 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
12061 memcpy(pWextState->WPARSNIE, genie - 2,
12062 (eLen + 2));
12063 pWextState->roamProfile.pRSNReqIE =
12064 pWextState->WPARSNIE;
12065 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12066 break;
12067 /*
12068 * Appending Extended Capabilities with Interworking bit set
12069 * in Assoc Req.
12070 *
12071 * In assoc req this EXT Cap will only be taken into account if
12072 * interworkingService bit is set to 1. Currently
12073 * driver is only interested in interworkingService capability
12074 * from supplicant. If in future any other EXT Cap info is
12075 * required from supplicat, it needs to be handled while
12076 * sending Assoc Req in LIM.
12077 */
12078 case DOT11F_EID_EXTCAP:
12079 {
12080 uint16_t curAddIELen =
12081 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012082 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012083
12084 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12085 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012086 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012087 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012088 return -ENOMEM;
12089 }
12090 memcpy(pWextState->assocAddIE.addIEdata +
12091 curAddIELen, genie - 2, eLen + 2);
12092 pWextState->assocAddIE.length += eLen + 2;
12093
12094 pWextState->roamProfile.pAddIEAssoc =
12095 pWextState->assocAddIE.addIEdata;
12096 pWextState->roamProfile.nAddIEAssocLength =
12097 pWextState->assocAddIE.length;
12098 break;
12099 }
12100#ifdef FEATURE_WLAN_WAPI
12101 case WLAN_EID_WAPI:
12102 /* Setting WAPI Mode to ON=1 */
12103 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012104 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012105 tmp = (u16 *) ie;
12106 tmp = tmp + 2; /* Skip element Id and Len, Version */
12107 akmsuiteCount = WPA_GET_LE16(tmp);
12108 tmp = tmp + 1;
12109 akmlist = (int *)(tmp);
12110 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12111 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12112 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012113 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012114 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012115 return -EINVAL;
12116 }
12117
12118 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012119 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012120 pAdapter->wapi_info.wapiAuthMode =
12121 WAPI_AUTH_MODE_PSK;
12122 }
12123 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012124 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012125 pAdapter->wapi_info.wapiAuthMode =
12126 WAPI_AUTH_MODE_CERT;
12127 }
12128 break;
12129#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012130 case DOT11F_EID_SUPPOPERATINGCLASSES:
12131 {
12132 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12133 status = wlan_hdd_add_assoc_ie(pWextState,
12134 genie - 2, eLen + 2);
12135 if (status)
12136 return status;
12137 break;
12138 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012139 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012140 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012141 /* when Unknown IE is received we should break and continue
12142 * to the next IE in the buffer instead we were returning
12143 * so changing this to break */
12144 break;
12145 }
12146 genie += eLen;
12147 remLen -= eLen;
12148 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012149 return 0;
12150}
12151
12152/**
12153 * hdd_is_wpaie_present() - check for WPA ie
12154 * @ie: Pointer to ie
12155 * @ie_len: Ie length
12156 *
12157 * Parse the received IE to find the WPA IE
12158 *
12159 * Return: true if wpa ie is found else false
12160 */
12161static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12162{
12163 uint8_t eLen = 0;
12164 uint16_t remLen = ie_len;
12165 uint8_t elementId = 0;
12166
12167 while (remLen >= 2) {
12168 elementId = *ie++;
12169 eLen = *ie++;
12170 remLen -= 2;
12171 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012172 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012173 return false;
12174 }
12175 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12176 /* OUI - 0x00 0X50 0XF2
12177 * WPA Information Element - 0x01
12178 * WPA version - 0x01
12179 */
12180 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12181 return true;
12182 }
12183 ie += eLen;
12184 remLen -= eLen;
12185 }
12186 return false;
12187}
12188
12189/**
12190 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12191 * @pAdapter: Pointer to adapter
12192 * @req: Pointer to security parameters
12193 *
12194 * Return: 0 for success, non-zero for failure
12195 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012196static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12197 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012198{
12199 int status = 0;
12200 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12201 ENTER();
12202
12203 /*set wpa version */
12204 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12205
12206 if (req->crypto.wpa_versions) {
12207 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12208 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12209 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12210 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12211 }
12212 }
12213
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012214 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012215
12216 /*set authentication type */
12217 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12218
12219 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012220 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012221 return status;
12222 }
12223
12224 /*set key mgmt type */
12225 if (req->crypto.n_akm_suites) {
12226 status =
12227 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12228 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012229 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012230 return status;
12231 }
12232 }
12233
12234 /*set pairwise cipher type */
12235 if (req->crypto.n_ciphers_pairwise) {
12236 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12237 req->crypto.
12238 ciphers_pairwise[0],
12239 true);
12240 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012241 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012242 return status;
12243 }
12244 } else {
12245 /*Reset previous cipher suite to none */
12246 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12247 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012248 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012249 return status;
12250 }
12251 }
12252
12253 /*set group cipher type */
12254 status =
12255 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12256 false);
12257
12258 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012259 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012260 return status;
12261 }
12262#ifdef WLAN_FEATURE_11W
12263 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12264#endif
12265
12266 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12267 if (req->ie_len) {
12268 status =
12269 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12270 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012271 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012272 return status;
12273 }
12274 }
12275
12276 /*incase of WEP set default key information */
12277 if (req->key && req->key_len) {
12278 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12279 || (WLAN_CIPHER_SUITE_WEP104 ==
12280 req->crypto.ciphers_pairwise[0])
12281 ) {
12282 if (IW_AUTH_KEY_MGMT_802_1X
12283 ==
12284 (pWextState->
12285 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012286 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012287 return -EOPNOTSUPP;
12288 } else {
12289 u8 key_len = req->key_len;
12290 u8 key_idx = req->key_idx;
12291
12292 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12293 key_len)
12294 && (CSR_MAX_NUM_KEY > key_idx)
12295 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012296 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012297 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012298 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012299 Keys.
12300 KeyMaterial[key_idx][0],
12301 req->key, key_len);
12302 pWextState->roamProfile.Keys.
12303 KeyLength[key_idx] = (u8) key_len;
12304 pWextState->roamProfile.Keys.
12305 defaultIndex = (u8) key_idx;
12306 }
12307 }
12308 }
12309 }
12310
12311 return status;
12312}
12313
12314/**
12315 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12316 * @pAdapter: Pointer to adapter
12317 *
12318 * This function is used to disconnect from previous connection
12319 *
12320 * Return: 0 for success, non-zero for failure
12321 */
12322static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12323{
12324 unsigned long rc;
12325 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012326 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012327
12328 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12329
Jeff Johnson9edf9572016-10-03 15:24:49 -070012330 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012331 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12332 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12333 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334 hdd_conn_set_connection_state(pAdapter,
12335 eConnectionState_Disconnecting);
12336 /* Issue disconnect to CSR */
12337 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012338
12339 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12340 pAdapter->sessionId,
12341 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12342 /*
12343 * Wait here instead of returning directly, this will block the
12344 * next connect command and allow processing of the scan for
12345 * ssid and the previous connect command in CSR. Else we might
12346 * hit some race conditions leading to SME and HDD out of sync.
12347 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012348 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012349 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12350 } else if (0 != status) {
12351 hdd_err("csrRoamDisconnect failure, returned %d",
12352 (int)status);
12353 pHddStaCtx->staDebugState = status;
12354 result = -EINVAL;
12355 goto disconnected;
12356 }
12357
12358 rc = wait_for_completion_timeout(
12359 &pAdapter->disconnect_comp_var,
12360 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012361 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012362 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12363 pAdapter->sessionId, pHddStaCtx->staDebugState);
12364 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012365 }
12366 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012367 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012368 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012369 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012370 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012371 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012372 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012373 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012374 }
12375 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012376disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012377 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12378 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012379}
12380
12381/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012382 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12383 * @adapter: Pointer to the HDD adapter
12384 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012385 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012386 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012387 * This function will start reassociation if prev_bssid is set and bssid/
12388 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012389 *
Naveen Rawat07332902016-07-27 09:13:17 -070012390 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012391 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012392#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12393 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012394static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12395 struct cfg80211_connect_params *req,
12396 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012397{
Naveen Rawat07332902016-07-27 09:13:17 -070012398 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012399 const uint8_t *bssid = NULL;
12400 uint16_t channel = 0;
12401
12402 if (req->bssid)
12403 bssid = req->bssid;
12404 else if (req->bssid_hint)
12405 bssid = req->bssid_hint;
12406
12407 if (req->channel)
12408 channel = req->channel->hw_value;
12409 else if (req->channel_hint)
12410 channel = req->channel_hint->hw_value;
12411
12412 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012413 reassoc = true;
12414 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012415 channel, MAC_ADDR_ARRAY(bssid));
12416 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012417 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012418 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012419 }
Naveen Rawat07332902016-07-27 09:13:17 -070012420 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012421}
12422#else
Naveen Rawat07332902016-07-27 09:13:17 -070012423static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12424 struct cfg80211_connect_params *req,
12425 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012426{
Naveen Rawat07332902016-07-27 09:13:17 -070012427 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012428}
12429#endif
12430
12431/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012432 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12433 * @wiphy: Pointer to wiphy
12434 * @dev: Pointer to network device
12435 * @req: Pointer to cfg80211 connect request
12436 *
12437 * This function is used to start the association process
12438 *
12439 * Return: 0 for success, non-zero for failure
12440 */
12441static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12442 struct net_device *ndev,
12443 struct cfg80211_connect_params *req)
12444{
12445 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012446 u16 channel;
12447#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12448 const u8 *bssid_hint = req->bssid_hint;
12449#else
12450 const u8 *bssid_hint = NULL;
12451#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012452 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12453 hdd_context_t *pHddCtx;
12454
12455 ENTER();
12456
Anurag Chouhan6d760662016-02-20 16:05:43 +053012457 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012458 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012459 return -EINVAL;
12460 }
12461
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012462 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12463 hdd_err("invalid session id: %d", pAdapter->sessionId);
12464 return -EINVAL;
12465 }
12466
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012467 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012468 TRACE_CODE_HDD_CFG80211_CONNECT,
12469 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012470 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012471 hdd_device_mode_to_string(pAdapter->device_mode),
12472 pAdapter->device_mode);
12473
Krunal Sonib4326f22016-03-10 13:05:51 -080012474 if (pAdapter->device_mode != QDF_STA_MODE &&
12475 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012476 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012477 hdd_device_mode_to_string(pAdapter->device_mode),
12478 pAdapter->device_mode);
12479 return -EINVAL;
12480 }
12481
12482 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12483 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012484 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012485 return -EINVAL;
12486 }
12487
12488 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012489 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012490 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012491
Naveen Rawat07332902016-07-27 09:13:17 -070012492 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012493 return status;
12494
Agrawal Ashishf156e942016-08-04 14:54:47 +053012495 wlan_hdd_disable_roaming(pAdapter);
12496
12497 /* Try disconnecting if already in connected state */
12498 status = wlan_hdd_try_disconnect(pAdapter);
12499 if (0 > status) {
12500 hdd_err("Failed to disconnect the existing connection");
12501 return -EALREADY;
12502 }
12503
12504 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012505 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012506 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012507 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012508 pAdapter->device_mode),
12509 req->channel->hw_value, HW_MODE_20_MHZ)) {
12510 hdd_err("This concurrency combination is not allowed");
12511 return -ECONNREFUSED;
12512 }
12513 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012514 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012515 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012516 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12517 hdd_err("This concurrency combination is not allowed");
12518 return -ECONNREFUSED;
12519 }
12520 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012521
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012522 /*initialise security parameters */
12523 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12524
12525 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012526 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012527 return status;
12528 }
12529
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012530 if (req->channel)
12531 channel = req->channel->hw_value;
12532 else
12533 channel = 0;
12534 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12535 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012536 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012537 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012538 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012539 return status;
12540 }
12541 EXIT();
12542 return status;
12543}
12544
12545/**
12546 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12547 * @wiphy: Pointer to wiphy
12548 * @dev: Pointer to network device
12549 * @req: Pointer to cfg80211 connect request
12550 *
12551 * Return: 0 for success, non-zero for failure
12552 */
12553static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12554 struct net_device *ndev,
12555 struct cfg80211_connect_params *req)
12556{
12557 int ret;
12558 cds_ssr_protect(__func__);
12559 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12560 cds_ssr_unprotect(__func__);
12561
12562 return ret;
12563}
12564
12565/**
12566 * wlan_hdd_disconnect() - hdd disconnect api
12567 * @pAdapter: Pointer to adapter
12568 * @reason: Disconnect reason code
12569 *
12570 * This function is used to issue a disconnect request to SME
12571 *
12572 * Return: 0 for success, non-zero for failure
12573 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012574static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012575{
12576 int status, result = 0;
12577 unsigned long rc;
12578 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12579 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12580
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012581 ENTER();
12582
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012583 status = wlan_hdd_validate_context(pHddCtx);
12584
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012585 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012586 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012587
12588 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012589 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012590 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12591 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012592 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012593 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12594 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12595
12596 /*issue disconnect */
12597
12598 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12599 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012600 /*
12601 * Wait here instead of returning directly, this will block the next
12602 * connect command and allow processing of the scan for ssid and
12603 * the previous connect command in CSR. Else we might hit some
12604 * race conditions leading to SME and HDD out of sync.
12605 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012606 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012607 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012608 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012609 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012610 (int)status);
12611 pHddStaCtx->staDebugState = status;
12612 result = -EINVAL;
12613 goto disconnected;
12614 }
12615 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12616 msecs_to_jiffies
12617 (WLAN_WAIT_TIME_DISCONNECT));
12618
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012619 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012620 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012621 result = -ETIMEDOUT;
12622 }
12623disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012624 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12625#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12626 /* Sending disconnect event to userspace for kernel version < 3.11
12627 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12628 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012629 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012630 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12631 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012632#endif
12633
12634 return result;
12635}
12636
12637/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012638 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12639 * @reason: ieee80211 reason code.
12640 *
12641 * This utility function helps log string conversion of reason code.
12642 *
12643 * Return: string conversion of reason code, if match found;
12644 * "Unknown" otherwise.
12645 */
12646static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12647{
12648 switch (reason) {
12649 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12650 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12651 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12652 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12653 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12654 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12655 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12656 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12657 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12658 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12659 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12660 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12661 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12662 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12663 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12664 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12665 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12666 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12667 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12668 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12669 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12670 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12671 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12672 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12673 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12674 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12675 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12676 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12677 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12678 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12679 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12680 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12681 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12682 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12683 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12684 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12685 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12686 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12687 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12688 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12689 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12690 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12691 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12692 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12693 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12694 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12695 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12696 default:
12697 return "Unknown";
12698 }
12699}
12700
12701/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012702 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12703 * @wiphy: Pointer to wiphy
12704 * @dev: Pointer to network device
12705 * @reason: Disconnect reason code
12706 *
12707 * This function is used to issue a disconnect request to SME
12708 *
12709 * Return: 0 for success, non-zero for failure
12710 */
12711static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12712 struct net_device *dev, u16 reason)
12713{
12714 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12715 int status;
12716 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12717 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12718#ifdef FEATURE_WLAN_TDLS
12719 uint8_t staIdx;
12720#endif
12721
12722 ENTER();
12723
Anurag Chouhan6d760662016-02-20 16:05:43 +053012724 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012725 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012726 return -EINVAL;
12727 }
12728
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012729 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12730 hdd_err("invalid session id: %d", pAdapter->sessionId);
12731 return -EINVAL;
12732 }
12733
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012734 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012735 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12736 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012737 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012738 hdd_device_mode_to_string(pAdapter->device_mode),
12739 pAdapter->device_mode, reason);
12740
12741 status = wlan_hdd_validate_context(pHddCtx);
12742
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012743 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012744 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012745
12746 /* Issue disconnect request to SME, if station is in connected state */
12747 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12748 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12749 eCsrRoamDisconnectReason reasonCode =
12750 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12751 hdd_scaninfo_t *pScanInfo;
12752
12753 switch (reason) {
12754 case WLAN_REASON_MIC_FAILURE:
12755 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12756 break;
12757
12758 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12759 case WLAN_REASON_DISASSOC_AP_BUSY:
12760 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12761 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12762 break;
12763
12764 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12765 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12766 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12767 break;
12768
12769 case WLAN_REASON_DEAUTH_LEAVING:
12770 reasonCode =
12771 pHddCtx->config->
12772 gEnableDeauthToDisassocMap ?
12773 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12774 eCSR_DISCONNECT_REASON_DEAUTH;
12775 break;
12776 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12777 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12778 break;
12779 default:
12780 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12781 break;
12782 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012783 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012784 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012785 pScanInfo = &pAdapter->scan_info;
12786 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012787 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012788 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12789 eCSR_SCAN_ABORT_DEFAULT);
12790 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012791 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012792#ifdef FEATURE_WLAN_TDLS
12793 /* First clean up the tdls peers if any */
12794 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12795 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12796 pAdapter->sessionId)
12797 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12798 uint8_t *mac;
12799 mac =
12800 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012801 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12802 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012803 pHddCtx->tdlsConnInfo[staIdx].staId,
12804 pAdapter->sessionId,
12805 MAC_ADDR_ARRAY(mac));
12806 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12807 (pAdapter),
12808 pAdapter->sessionId, mac);
12809 }
12810 }
12811#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012812 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012813 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012814 hdd_info("Disconnect request from user space with reason: %s",
12815 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012816 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12817 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012818 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012819 return -EINVAL;
12820 }
12821 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012822 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012823 pHddStaCtx->conn_info.connState);
12824 }
12825
12826 return status;
12827}
12828
12829/**
12830 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12831 * @wiphy: Pointer to wiphy
12832 * @dev: Pointer to network device
12833 * @reason: Disconnect reason code
12834 *
12835 * Return: 0 for success, non-zero for failure
12836 */
12837static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12838 struct net_device *dev, u16 reason)
12839{
12840 int ret;
12841 cds_ssr_protect(__func__);
12842 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12843 cds_ssr_unprotect(__func__);
12844
12845 return ret;
12846}
12847
12848/**
12849 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12850 * @pAdapter: Pointer to adapter
12851 * @param: Pointer to IBSS parameters
12852 *
12853 * This function is used to initialize the security settings in IBSS mode
12854 *
12855 * Return: 0 for success, non-zero for failure
12856 */
12857static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12858 struct cfg80211_ibss_params
12859 *params)
12860{
12861 int status = 0;
12862 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12863 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12864 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12865
12866 ENTER();
12867
12868 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012869 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012870 pHddStaCtx->ibss_enc_key_installed = 0;
12871
12872 if (params->ie_len && (NULL != params->ie)) {
12873 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12874 params->ie_len, WLAN_EID_RSN)) {
12875 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12876 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12877 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
12878 tDot11fIEWPA dot11WPAIE;
12879 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12880 u8 *ie;
12881
12882 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12883 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12884 params->ie_len,
12885 DOT11F_EID_WPA);
12886 if (NULL != ie) {
12887 pWextState->wpaVersion =
12888 IW_AUTH_WPA_VERSION_WPA;
12889 /* Unpack the WPA IE */
12890 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
12891 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
12892 &ie[2 + 4],
12893 ie[1] - 4, &dot11WPAIE);
12894 /*Extract the multicast cipher, the encType for unicast
12895 cipher for wpa-none is none */
12896 encryptionType =
12897 hdd_translate_wpa_to_csr_encryption_type
12898 (dot11WPAIE.multicast_cipher);
12899 }
12900 }
12901
12902 status =
12903 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
12904 params->ie_len);
12905
12906 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012907 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012908 return status;
12909 }
12910 }
12911
12912 pWextState->roamProfile.AuthType.authType[0] =
12913 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12914
12915 if (params->privacy) {
12916 /* Security enabled IBSS, At this time there is no information
12917 * available about the security paramters, so initialise the
12918 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
12919 * The correct security parameters will be updated later in
12920 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
12921 * set inorder enable privacy bit in beacons
12922 */
12923
12924 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12925 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012926 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012927 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12928 pWextState->roamProfile.EncryptionType.numEntries = 1;
12929 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12930 encryptionType;
12931 return status;
12932}
12933
12934/**
12935 * __wlan_hdd_cfg80211_join_ibss() - join ibss
12936 * @wiphy: Pointer to wiphy
12937 * @dev: Pointer to network device
12938 * @param: Pointer to IBSS join parameters
12939 *
12940 * This function is used to create/join an IBSS network
12941 *
12942 * Return: 0 for success, non-zero for failure
12943 */
12944static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12945 struct net_device *dev,
12946 struct cfg80211_ibss_params *params)
12947{
12948 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12949 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12950 tCsrRoamProfile *pRoamProfile;
12951 int status;
12952 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12953 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053012954 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012955 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012956
12957 ENTER();
12958
Anurag Chouhan6d760662016-02-20 16:05:43 +053012959 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012960 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012961 return -EINVAL;
12962 }
12963
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012964 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12965 hdd_err("invalid session id: %d", pAdapter->sessionId);
12966 return -EINVAL;
12967 }
12968
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012969 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012970 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
12971 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012972 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012973 hdd_device_mode_to_string(pAdapter->device_mode),
12974 pAdapter->device_mode);
12975
12976 status = wlan_hdd_validate_context(pHddCtx);
12977
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012978 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012979 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012980
12981 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053012982 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012983 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12984 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
12985 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12986 int indx;
12987
12988 /* Get channel number */
12989 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012990 params->
12991 chandef.
12992 chan->
12993 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012994
12995 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12996 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012997 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012998 return -EOPNOTSUPP;
12999 }
13000
13001 for (indx = 0; indx < numChans; indx++) {
13002 if (channelNum == validChan[indx]) {
13003 break;
13004 }
13005 }
13006 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013007 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013008 return -EINVAL;
13009 }
13010 }
13011
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013012 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013013 HW_MODE_20_MHZ)) {
13014 hdd_err("This concurrency combination is not allowed");
13015 return -ECONNREFUSED;
13016 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013017
Krunal Soni3091bcc2016-06-23 12:28:21 -070013018 status = qdf_reset_connection_update();
13019 if (!QDF_IS_STATUS_SUCCESS(status))
13020 hdd_err("ERR: clear event failed");
13021
13022 status = cds_current_connections_update(pAdapter->sessionId,
13023 channelNum,
13024 SIR_UPDATE_REASON_JOIN_IBSS);
13025 if (QDF_STATUS_E_FAILURE == status) {
13026 hdd_err("ERROR: connections update failed!!");
13027 return -EINVAL;
13028 }
13029
13030 if (QDF_STATUS_SUCCESS == status) {
13031 status = qdf_wait_for_connection_update();
13032 if (!QDF_IS_STATUS_SUCCESS(status)) {
13033 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013034 return -EINVAL;
13035 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013036 }
13037
13038 /*Try disconnecting if already in connected state */
13039 status = wlan_hdd_try_disconnect(pAdapter);
13040 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013041 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013042 return -EALREADY;
13043 }
13044
13045 pRoamProfile = &pWextState->roamProfile;
13046
13047 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013048 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013049 return -EINVAL;
13050 }
13051
13052 /* enable selected protection checks in IBSS mode */
13053 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
13054
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013055 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013056 WNI_CFG_IBSS_ATIM_WIN_SIZE,
13057 pHddCtx->config->
13058 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013059 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013060 }
13061
13062 /* BSSID is provided by upper layers hence no need to AUTO generate */
13063 if (NULL != params->bssid) {
13064 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013065 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013066 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013067 return -EIO;
13068 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013069 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013070 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
13071 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013072 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013073 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013074 return -EIO;
13075 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053013076 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013077 }
13078 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13079 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13080 pRoamProfile->beaconInterval = params->beacon_interval;
13081 else {
13082 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013083 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013084 params->beacon_interval, pRoamProfile->beaconInterval);
13085 }
13086
13087 /* Set Channel */
13088 if (channelNum) {
13089 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013090 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013091 pRoamProfile->ChannelInfo.numOfChannels = 1;
13092 pHddStaCtx->conn_info.operationChannel = channelNum;
13093 pRoamProfile->ChannelInfo.ChannelList =
13094 &pHddStaCtx->conn_info.operationChannel;
13095 }
13096
13097 /* Initialize security parameters */
13098 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13099 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013100 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013101 return status;
13102 }
13103
13104 /* Issue connect start */
13105 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13106 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013107 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013108 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013109 operationChannel,
13110 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013111
13112 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013113 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013114 return status;
13115 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013116 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013117 return 0;
13118}
13119
13120/**
13121 * wlan_hdd_cfg80211_join_ibss() - join ibss
13122 * @wiphy: Pointer to wiphy
13123 * @dev: Pointer to network device
13124 * @param: Pointer to IBSS join parameters
13125 *
13126 * This function is used to create/join an IBSS network
13127 *
13128 * Return: 0 for success, non-zero for failure
13129 */
13130static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13131 struct net_device *dev,
13132 struct cfg80211_ibss_params *params)
13133{
13134 int ret = 0;
13135
13136 cds_ssr_protect(__func__);
13137 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13138 cds_ssr_unprotect(__func__);
13139
13140 return ret;
13141}
13142
13143/**
13144 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13145 * @wiphy: Pointer to wiphy
13146 * @dev: Pointer to network device
13147 *
13148 * This function is used to leave an IBSS network
13149 *
13150 * Return: 0 for success, non-zero for failure
13151 */
13152static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13153 struct net_device *dev)
13154{
13155 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13156 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13157 tCsrRoamProfile *pRoamProfile;
13158 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13159 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013160 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013161 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013162 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013163
13164 ENTER();
13165
Anurag Chouhan6d760662016-02-20 16:05:43 +053013166 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013167 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013168 return -EINVAL;
13169 }
13170
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013171 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13172 hdd_err("invalid session id: %d", pAdapter->sessionId);
13173 return -EINVAL;
13174 }
13175
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013176 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013177 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13178 pAdapter->sessionId,
13179 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13180 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013181 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013182 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013183
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013184 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013185 hdd_device_mode_to_string(pAdapter->device_mode),
13186 pAdapter->device_mode);
13187 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013188 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013189 return -EIO;
13190 }
13191
13192 pRoamProfile = &pWextState->roamProfile;
13193
13194 /* Issue disconnect only if interface type is set to IBSS */
13195 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013196 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013197 return -EINVAL;
13198 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013199 /* Clearing add IE of beacon */
13200 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13201 sizeof(tSirMacAddr));
13202 updateIE.smeSessionId = pAdapter->sessionId;
13203 updateIE.ieBufferlength = 0;
13204 updateIE.pAdditionIEBuffer = NULL;
13205 updateIE.append = true;
13206 updateIE.notify = true;
13207 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13208 &updateIE,
13209 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013210 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013211 }
13212
13213 /* Reset WNI_CFG_PROBE_RSP Flags */
13214 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013215
13216 /* Issue Disconnect request */
13217 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13218 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13219 pAdapter->sessionId,
13220 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013221 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013222 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013223 hal_status);
13224 return -EAGAIN;
13225 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013226
13227 /* wait for mc thread to cleanup and then return to upper stack
13228 * so by the time upper layer calls the change interface, we are
13229 * all set to proceed further
13230 */
13231 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13232 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13233 if (!rc) {
13234 hdd_err("Failed to disconnect, timed out");
13235 return -ETIMEDOUT;
13236 }
13237
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013238 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013239 return 0;
13240}
13241
13242/**
13243 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13244 * @wiphy: Pointer to wiphy
13245 * @dev: Pointer to network device
13246 *
13247 * This function is used to leave an IBSS network
13248 *
13249 * Return: 0 for success, non-zero for failure
13250 */
13251static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13252 struct net_device *dev)
13253{
13254 int ret = 0;
13255
13256 cds_ssr_protect(__func__);
13257 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13258 cds_ssr_unprotect(__func__);
13259
13260 return ret;
13261}
13262
13263/**
13264 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13265 * @wiphy: Pointer to wiphy
13266 * @changed: Parameters changed
13267 *
13268 * This function is used to set the phy parameters. RTS Threshold/FRAG
13269 * Threshold/Retry Count etc.
13270 *
13271 * Return: 0 for success, non-zero for failure
13272 */
13273static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13274 u32 changed)
13275{
13276 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13277 tHalHandle hHal = pHddCtx->hHal;
13278 int status;
13279
13280 ENTER();
13281
Anurag Chouhan6d760662016-02-20 16:05:43 +053013282 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013283 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013284 return -EINVAL;
13285 }
13286
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013287 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013288 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13289 NO_SESSION, wiphy->rts_threshold));
13290 status = wlan_hdd_validate_context(pHddCtx);
13291
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013292 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013293 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013294
13295 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13296 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13297 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13298
13299 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13300 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013301 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013302 rts_threshold);
13303 return -EINVAL;
13304 }
13305
13306 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13307 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013308 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013309 rts_threshold);
13310 return -EIO;
13311 }
13312
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013313 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013314 }
13315
13316 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13317 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13318 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13319 wiphy->frag_threshold;
13320
13321 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13322 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013323 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013324 frag_threshold);
13325 return -EINVAL;
13326 }
13327
13328 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13329 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013330 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013331 frag_threshold);
13332 return -EIO;
13333 }
13334
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013335 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013336 }
13337
13338 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13339 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13340 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13341 wiphy->retry_short : wiphy->retry_long;
13342
13343 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13344 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013345 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013346 return -EINVAL;
13347 }
13348
13349 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13350 if (0 != sme_cfg_set_int(hHal,
13351 WNI_CFG_LONG_RETRY_LIMIT,
13352 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013353 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013354 retry_value);
13355 return -EIO;
13356 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013357 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013358 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13359 if (0 != sme_cfg_set_int(hHal,
13360 WNI_CFG_SHORT_RETRY_LIMIT,
13361 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013362 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013363 retry_value);
13364 return -EIO;
13365 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013366 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013367 }
13368 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013369 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013370 return 0;
13371}
13372
13373/**
13374 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13375 * @wiphy: Pointer to wiphy
13376 * @changed: Parameters changed
13377 *
13378 * Return: 0 for success, non-zero for failure
13379 */
13380static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13381{
13382 int ret;
13383
13384 cds_ssr_protect(__func__);
13385 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13386 cds_ssr_unprotect(__func__);
13387
13388 return ret;
13389}
13390
13391/**
13392 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13393 * key
13394 * @wiphy: Pointer to wiphy
13395 * @dev: Pointer to network device
13396 * @key_index: Key index
13397 *
13398 * Return: 0
13399 */
13400static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13401 struct net_device *netdev,
13402 u8 key_index)
13403{
13404 ENTER();
13405 return 0;
13406}
13407
13408/**
13409 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13410 * wlan_hdd_set_default_mgmt_key
13411 * @wiphy: pointer to wiphy
13412 * @netdev: pointer to net_device structure
13413 * @key_index: key index
13414 *
13415 * Return: 0 on success, error number on failure
13416 */
13417static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13418 struct net_device *netdev,
13419 u8 key_index)
13420{
13421 int ret;
13422
13423 cds_ssr_protect(__func__);
13424 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13425 cds_ssr_unprotect(__func__);
13426
13427 return ret;
13428}
13429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013430/**
13431 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13432 * @wiphy: Pointer to wiphy
13433 * @dev: Pointer to network device
13434 * @params: Pointer to tx queue parameters
13435 *
13436 * Return: 0
13437 */
13438static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13439 struct net_device *dev,
13440 struct ieee80211_txq_params *params)
13441{
13442 ENTER();
13443 return 0;
13444}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013445
13446/**
13447 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13448 * @wiphy: pointer to wiphy
13449 * @netdev: pointer to net_device structure
13450 * @params: pointer to ieee80211_txq_params
13451 *
13452 * Return: 0 on success, error number on failure
13453 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013454static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13455 struct net_device *dev,
13456 struct ieee80211_txq_params *params)
13457{
13458 int ret;
13459
13460 cds_ssr_protect(__func__);
13461 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13462 cds_ssr_unprotect(__func__);
13463
13464 return ret;
13465}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013466
13467/**
13468 * __wlan_hdd_cfg80211_del_station() - delete station v2
13469 * @wiphy: Pointer to wiphy
13470 * @param: Pointer to delete station parameter
13471 *
13472 * Return: 0 for success, non-zero for failure
13473 */
13474static
13475int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13476 struct net_device *dev,
13477 struct tagCsrDelStaParams *pDelStaParams)
13478{
13479 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13480 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013481 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013482 hdd_hostapd_state_t *hapd_state;
13483 int status;
13484 uint8_t staId;
13485 uint8_t *mac;
13486
13487 ENTER();
13488
Anurag Chouhan6d760662016-02-20 16:05:43 +053013489 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013490 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013491 return -EINVAL;
13492 }
13493
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013494 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13495 hdd_err("invalid session id: %d", pAdapter->sessionId);
13496 return -EINVAL;
13497 }
13498
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013499 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013500 TRACE_CODE_HDD_CFG80211_DEL_STA,
13501 pAdapter->sessionId, pAdapter->device_mode));
13502
13503 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13504 status = wlan_hdd_validate_context(pHddCtx);
13505
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013506 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013507 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013508
13509 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13510
Krunal Sonib4326f22016-03-10 13:05:51 -080013511 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13512 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013513
13514 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13515 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013516 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013517 return 0;
13518 }
13519
Anurag Chouhanc5548422016-02-24 18:33:27 +053013520 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013521 uint16_t i;
13522 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13523 if ((pAdapter->aStaInfo[i].isUsed) &&
13524 (!pAdapter->aStaInfo[i].
13525 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013526 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013527 mac,
13528 pAdapter->aStaInfo[i].
13529 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013530 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013531 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13532 hdd_ipa_wlan_evt(pAdapter,
13533 pAdapter->
13534 aStaInfo[i].
13535 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013536 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013537 mac);
13538 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013539 hdd_notice("Delete STA with MAC::"
13540 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013541 MAC_ADDR_ARRAY(mac));
13542
13543 if (pHddCtx->dev_dfs_cac_status ==
13544 DFS_CAC_IN_PROGRESS)
13545 goto fn_end;
13546
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013547 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013548 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013549 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013550 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013551 hdd_softap_sta_deauth(pAdapter,
13552 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013553 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013554 pAdapter->aStaInfo[i].
13555 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013556 qdf_status =
13557 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013558 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013559 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013560 if (!QDF_IS_STATUS_SUCCESS(
13561 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013562 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013563 }
13564 }
13565 }
13566 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013567 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013568 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013569 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013570 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013571 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013572 hdd_notice("Skip DEL STA as this is not used::"
13573 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013574 MAC_ADDR_ARRAY(mac));
13575 return -ENOENT;
13576 }
13577
13578 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13579 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013580 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013581 }
13582
13583 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13584 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013585 hdd_notice("Skip DEL STA as deauth is in progress::"
13586 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013587 MAC_ADDR_ARRAY(mac));
13588 return -ENOENT;
13589 }
13590
13591 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13592
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013593 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013594 MAC_ADDR_ARRAY(mac));
13595
13596 /* Case: SAP in ACS selected DFS ch and client connected
13597 * Now Radar detected. Then if random channel is another
13598 * DFS ch then new CAC is initiated and no TX allowed.
13599 * So do not send any mgmt frames as it will timeout
13600 * during CAC.
13601 */
13602
13603 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13604 goto fn_end;
13605
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013606 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013607 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13608 (pAdapter), pAdapter->sessionId,
13609 (uint8_t *)&pDelStaParams->peerMacAddr,
13610 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013611 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013612 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013613 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013614 pAdapter->aStaInfo[staId].isDeauthInProgress =
13615 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013616 hdd_notice("STA removal failed for ::"
13617 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013618 MAC_ADDR_ARRAY(mac));
13619 return -ENOENT;
13620 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013621 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013622 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013623 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013624 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013625 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013626 }
13627 }
13628 }
13629
13630fn_end:
13631 EXIT();
13632 return 0;
13633}
13634
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013635#if defined(USE_CFG80211_DEL_STA_V2)
13636/**
13637 * wlan_hdd_del_station() - delete station wrapper
13638 * @adapter: pointer to the hdd adapter
13639 *
13640 * Return: None
13641 */
13642void wlan_hdd_del_station(hdd_adapter_t *adapter)
13643{
13644 struct station_del_parameters del_sta;
13645 del_sta.mac = NULL;
13646 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13647 del_sta.reason_code = eCsrForcedDeauthSta;
13648
13649 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13650 &del_sta);
13651}
13652#else
13653void wlan_hdd_del_station(hdd_adapter_t *adapter)
13654{
13655 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13656}
13657#endif
13658
13659#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660/**
13661 * wlan_hdd_cfg80211_del_station() - delete station v2
13662 * @wiphy: Pointer to wiphy
13663 * @param: Pointer to delete station parameter
13664 *
13665 * Return: 0 for success, non-zero for failure
13666 */
13667int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13668 struct net_device *dev,
13669 struct station_del_parameters *param)
13670#else
13671/**
13672 * wlan_hdd_cfg80211_del_station() - delete station
13673 * @wiphy: Pointer to wiphy
13674 * @mac: Pointer to station mac address
13675 *
13676 * Return: 0 for success, non-zero for failure
13677 */
13678#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13679int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13680 struct net_device *dev,
13681 const uint8_t *mac)
13682#else
13683int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13684 struct net_device *dev,
13685 uint8_t *mac)
13686#endif
13687#endif
13688{
13689 int ret;
13690 struct tagCsrDelStaParams delStaParams;
13691
13692 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013693#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013694 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013695 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013696 return -EINVAL;
13697 }
13698 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13699 param->subtype, &delStaParams);
13700#else
13701 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13702 (SIR_MAC_MGMT_DEAUTH >> 4),
13703 &delStaParams);
13704#endif
13705 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13706 cds_ssr_unprotect(__func__);
13707
13708 return ret;
13709}
13710
13711/**
13712 * __wlan_hdd_cfg80211_add_station() - add station
13713 * @wiphy: Pointer to wiphy
13714 * @mac: Pointer to station mac address
13715 * @pmksa: Pointer to add station parameter
13716 *
13717 * Return: 0 for success, non-zero for failure
13718 */
13719static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13720 struct net_device *dev,
13721 const uint8_t *mac,
13722 struct station_parameters *params)
13723{
13724 int status = -EPERM;
13725#ifdef FEATURE_WLAN_TDLS
13726 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13727 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13728 u32 mask, set;
13729
13730 ENTER();
13731
Anurag Chouhan6d760662016-02-20 16:05:43 +053013732 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013733 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013734 return -EINVAL;
13735 }
13736
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013737 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13738 hdd_err("invalid session id: %d", pAdapter->sessionId);
13739 return -EINVAL;
13740 }
13741
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013742 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013743 TRACE_CODE_HDD_CFG80211_ADD_STA,
13744 pAdapter->sessionId, params->listen_interval));
13745
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013746 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013747 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013748
13749 mask = params->sta_flags_mask;
13750
13751 set = params->sta_flags_set;
13752
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013753 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013754 MAC_ADDR_ARRAY(mac));
13755
13756 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13757 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13758 status =
13759 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13760 }
13761 }
13762#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013763 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013764 return status;
13765}
13766
13767/**
13768 * wlan_hdd_cfg80211_add_station() - add station
13769 * @wiphy: Pointer to wiphy
13770 * @mac: Pointer to station mac address
13771 * @pmksa: Pointer to add station parameter
13772 *
13773 * Return: 0 for success, non-zero for failure
13774 */
13775#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13776static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13777 struct net_device *dev,
13778 const uint8_t *mac,
13779 struct station_parameters *params)
13780#else
13781static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13782 struct net_device *dev, uint8_t *mac,
13783 struct station_parameters *params)
13784#endif
13785{
13786 int ret;
13787
13788 cds_ssr_protect(__func__);
13789 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13790 cds_ssr_unprotect(__func__);
13791
13792 return ret;
13793}
13794
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013795/**
13796 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13797 * @wiphy: Pointer to wiphy
13798 * @dev: Pointer to network device
13799 * @pmksa: Pointer to set pmksa parameter
13800 *
13801 * Return: 0 for success, non-zero for failure
13802 */
13803static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13804 struct net_device *dev,
13805 struct cfg80211_pmksa *pmksa)
13806{
13807 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13808 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13809 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013810 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013811 int status;
13812 tPmkidCacheInfo pmk_id;
13813
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013814 ENTER();
13815
Anurag Chouhan6d760662016-02-20 16:05:43 +053013816 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013817 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013818 return -EINVAL;
13819 }
13820
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013821 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13822 hdd_err("invalid session id: %d", pAdapter->sessionId);
13823 return -EINVAL;
13824 }
13825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013826 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013827 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013828 return -EINVAL;
13829 }
13830
13831 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013832 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013833 pmksa->bssid, pmksa->pmkid);
13834 return -EINVAL;
13835 }
13836
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013837 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013838 MAC_ADDR_ARRAY(pmksa->bssid));
13839
13840 status = wlan_hdd_validate_context(pHddCtx);
13841
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013842 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013843 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013844
13845 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13846
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013847 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13848 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013849
13850 /* Add to the PMKSA ID Cache in CSR */
13851 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13852 &pmk_id, 1, false);
13853
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013854 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013855 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
13856 pAdapter->sessionId, result));
13857
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013858 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013859 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013860}
13861
13862/**
13863 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13864 * @wiphy: Pointer to wiphy
13865 * @dev: Pointer to network device
13866 * @pmksa: Pointer to set pmksa parameter
13867 *
13868 * Return: 0 for success, non-zero for failure
13869 */
13870static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13871 struct net_device *dev,
13872 struct cfg80211_pmksa *pmksa)
13873{
13874 int ret;
13875
13876 cds_ssr_protect(__func__);
13877 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
13878 cds_ssr_unprotect(__func__);
13879
13880 return ret;
13881}
13882
13883/**
13884 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13885 * @wiphy: Pointer to wiphy
13886 * @dev: Pointer to network device
13887 * @pmksa: Pointer to pmksa parameter
13888 *
13889 * Return: 0 for success, non-zero for failure
13890 */
13891static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13892 struct net_device *dev,
13893 struct cfg80211_pmksa *pmksa)
13894{
13895 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13896 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13897 tHalHandle halHandle;
13898 int status = 0;
13899
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013900 ENTER();
13901
Anurag Chouhan6d760662016-02-20 16:05:43 +053013902 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013903 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013904 return -EINVAL;
13905 }
13906
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013907 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13908 hdd_err("invalid session id: %d", pAdapter->sessionId);
13909 return -EINVAL;
13910 }
13911
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013912 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013913 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013914 return -EINVAL;
13915 }
13916
13917 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013918 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013919 return -EINVAL;
13920 }
13921
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013922 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013923 MAC_ADDR_ARRAY(pmksa->bssid));
13924
13925 status = wlan_hdd_validate_context(pHddCtx);
13926
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013927 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013928 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013929
13930 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13931
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013932 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053013933 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
13934 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013935 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013936 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013937 sme_roam_del_pmkid_from_cache(halHandle,
13938 pAdapter->sessionId, pmksa->bssid,
13939 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013940 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013941 MAC_ADDR_ARRAY(pmksa->bssid));
13942 status = -EINVAL;
13943 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013944 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013945 return status;
13946}
13947
13948/**
13949 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13950 * @wiphy: Pointer to wiphy
13951 * @dev: Pointer to network device
13952 * @pmksa: Pointer to pmksa parameter
13953 *
13954 * Return: 0 for success, non-zero for failure
13955 */
13956static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13957 struct net_device *dev,
13958 struct cfg80211_pmksa *pmksa)
13959{
13960 int ret;
13961
13962 cds_ssr_protect(__func__);
13963 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
13964 cds_ssr_unprotect(__func__);
13965
13966 return ret;
13967
13968}
13969
13970/**
13971 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13972 * @wiphy: Pointer to wiphy
13973 * @dev: Pointer to network device
13974 *
13975 * Return: 0 for success, non-zero for failure
13976 */
13977static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13978 struct net_device *dev)
13979{
13980 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13981 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13982 tHalHandle halHandle;
13983 int status = 0;
13984
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013985 ENTER();
13986
Anurag Chouhan6d760662016-02-20 16:05:43 +053013987 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013988 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013989 return -EINVAL;
13990 }
13991
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013992 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13993 hdd_err("invalid session id: %d", pAdapter->sessionId);
13994 return -EINVAL;
13995 }
13996
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013997 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013998
13999 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14000 status = wlan_hdd_validate_context(pHddCtx);
14001
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014002 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014003 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014004
14005 /* Retrieve halHandle */
14006 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14007
14008 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014009 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014010 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
14011 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014012 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014013 status = -EINVAL;
14014 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014015 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014016 return status;
14017}
14018
14019/**
14020 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14021 * @wiphy: Pointer to wiphy
14022 * @dev: Pointer to network device
14023 *
14024 * Return: 0 for success, non-zero for failure
14025 */
14026static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14027 struct net_device *dev)
14028{
14029 int ret;
14030
14031 cds_ssr_protect(__func__);
14032 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
14033 cds_ssr_unprotect(__func__);
14034
14035 return ret;
14036}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014037
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014038#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014039/**
14040 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14041 * @wiphy: Pointer to wiphy
14042 * @dev: Pointer to network device
14043 * @ftie: Pointer to fast transition ie parameter
14044 *
14045 * Return: 0 for success, non-zero for failure
14046 */
14047static int
14048__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14049 struct net_device *dev,
14050 struct cfg80211_update_ft_ies_params *ftie)
14051{
14052 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14053 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14054 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14055 int status;
14056
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014057 ENTER();
14058
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014059 status = wlan_hdd_validate_context(hdd_ctx);
14060 if (status)
14061 return status;
14062
Anurag Chouhan6d760662016-02-20 16:05:43 +053014063 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014064 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014065 return -EINVAL;
14066 }
14067
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014068 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14069 hdd_err("invalid session id: %d", pAdapter->sessionId);
14070 return -EINVAL;
14071 }
14072
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014073 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014074 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
14075 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
14076 /* Added for debug on reception of Re-assoc Req. */
14077 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014078 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014079 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014080 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014081 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014082 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014083 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014084
14085 /* Pass the received FT IEs to SME */
14086 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
14087 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014088 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014089 return 0;
14090}
14091
14092/**
14093 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14094 * @wiphy: Pointer to wiphy
14095 * @dev: Pointer to network device
14096 * @ftie: Pointer to fast transition ie parameter
14097 *
14098 * Return: 0 for success, non-zero for failure
14099 */
14100static int
14101wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14102 struct net_device *dev,
14103 struct cfg80211_update_ft_ies_params *ftie)
14104{
14105 int ret;
14106
14107 cds_ssr_protect(__func__);
14108 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14109 cds_ssr_unprotect(__func__);
14110
14111 return ret;
14112}
14113#endif
14114
14115#ifdef WLAN_FEATURE_GTK_OFFLOAD
14116/**
14117 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14118 * @callbackContext: Callback context
14119 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14120 *
14121 * Callback rountine called upon receiving response for get offload info
14122 *
14123 * Return: none
14124 */
14125void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14126 tpSirGtkOffloadGetInfoRspParams
14127 pGtkOffloadGetInfoRsp)
14128{
14129 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14130 uint8_t tempReplayCounter[8];
14131 hdd_station_ctx_t *pHddStaCtx;
14132
14133 ENTER();
14134
14135 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014136 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014137 return;
14138 }
14139
14140 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014141 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014142 return;
14143 }
14144
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014145 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014146 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014147 return;
14148 }
14149
14150 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14151 /* Update replay counter */
14152 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14153 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14154
14155 {
14156 /* changing from little to big endian since supplicant
14157 * works on big endian format
14158 */
14159 int i;
14160 uint8_t *p =
14161 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14162
14163 for (i = 0; i < 8; i++) {
14164 tempReplayCounter[7 - i] = (uint8_t) p[i];
14165 }
14166 }
14167
14168 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014169 cfg80211_gtk_rekey_notify(pAdapter->dev,
14170 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014171 tempReplayCounter, GFP_KERNEL);
14172}
14173
14174/**
14175 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14176 * @wiphy: Pointer to wiphy
14177 * @dev: Pointer to network device
14178 * @data: Pointer to rekey data
14179 *
14180 * This function is used to offload GTK rekeying job to the firmware.
14181 *
14182 * Return: 0 for success, non-zero for failure
14183 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014184static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014185int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14186 struct net_device *dev,
14187 struct cfg80211_gtk_rekey_data *data)
14188{
14189 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14190 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14191 hdd_station_ctx_t *pHddStaCtx;
14192 tHalHandle hHal;
14193 int result;
14194 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014195 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014196
14197 ENTER();
14198
Anurag Chouhan6d760662016-02-20 16:05:43 +053014199 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014200 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014201 return -EINVAL;
14202 }
14203
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014204 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14205 hdd_err("invalid session id: %d", pAdapter->sessionId);
14206 return -EINVAL;
14207 }
14208
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014209 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014210 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14211 pAdapter->sessionId, pAdapter->device_mode));
14212
14213 result = wlan_hdd_validate_context(pHddCtx);
14214
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014215 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014216 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014217
14218 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14219 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14220 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014221 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014222 return -EAGAIN;
14223 }
14224
14225 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14226 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14227 NL80211_KCK_LEN);
14228 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14229 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014230 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014231 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014232 {
14233 /* changing from big to little endian since driver
14234 * works on little endian format
14235 */
14236 uint8_t *p =
14237 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14238 ullKeyReplayCounter;
14239 int i;
14240
14241 for (i = 0; i < 8; i++) {
14242 p[7 - i] = data->replay_ctr[i];
14243 }
14244 }
14245
14246 if (true == pHddCtx->hdd_wlan_suspended) {
14247 /* if wlan is suspended, enable GTK offload directly from here */
14248 memcpy(&hddGtkOffloadReqParams,
14249 &pHddStaCtx->gtkOffloadReqParams,
14250 sizeof(tSirGtkOffloadParams));
14251 status =
14252 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14253 pAdapter->sessionId);
14254
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014255 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014256 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014257 status);
14258 return -EINVAL;
14259 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014260 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014261 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014262 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014263 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014264 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014265 return result;
14266}
14267
14268/**
14269 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14270 * @wiphy: Pointer to wiphy
14271 * @dev: Pointer to network device
14272 * @data: Pointer to rekey data
14273 *
14274 * This function is used to offload GTK rekeying job to the firmware.
14275 *
14276 * Return: 0 for success, non-zero for failure
14277 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014278static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014279int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14280 struct net_device *dev,
14281 struct cfg80211_gtk_rekey_data *data)
14282{
14283 int ret;
14284
14285 cds_ssr_protect(__func__);
14286 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14287 cds_ssr_unprotect(__func__);
14288
14289 return ret;
14290}
14291#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14292
14293/**
14294 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14295 * @wiphy: Pointer to wiphy
14296 * @dev: Pointer to network device
14297 * @param: Pointer to access control parameter
14298 *
14299 * Return: 0 for success, non-zero for failure
14300 */
14301static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14302 struct net_device *dev,
14303 const struct cfg80211_acl_data *params)
14304{
14305 int i;
14306 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14307 hdd_hostapd_state_t *pHostapdState;
14308 tsap_Config_t *pConfig;
14309 v_CONTEXT_t p_cds_context = NULL;
14310 hdd_context_t *pHddCtx;
14311 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014312 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014313
14314 ENTER();
14315
Anurag Chouhan6d760662016-02-20 16:05:43 +053014316 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014317 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014318 return -EINVAL;
14319 }
14320
14321 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014322 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014323 return -EINVAL;
14324 }
14325
14326 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14327 status = wlan_hdd_validate_context(pHddCtx);
14328
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014329 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014330 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014331
14332 p_cds_context = pHddCtx->pcds_context;
14333 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14334
14335 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014336 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014337 return -EINVAL;
14338 }
14339
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014340 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014341 params->n_acl_entries);
14342
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014343 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014344 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14345 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014346 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14348
14349 /* default value */
14350 pConfig->num_accept_mac = 0;
14351 pConfig->num_deny_mac = 0;
14352
14353 /**
14354 * access control policy
14355 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14356 * listed in hostapd.deny file.
14357 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14358 * listed in hostapd.accept file.
14359 */
14360 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14361 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14362 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14363 params->acl_policy) {
14364 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14365 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014366 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014367 params->acl_policy);
14368 return -ENOTSUPP;
14369 }
14370
14371 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14372 pConfig->num_accept_mac = params->n_acl_entries;
14373 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014374 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14375 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014376 MAC_ADDR_ARRAY(
14377 params->mac_addrs[i].addr));
14378
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014379 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014380 params->mac_addrs[i].addr,
14381 sizeof(qcmacaddr));
14382 }
14383 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14384 pConfig->num_deny_mac = params->n_acl_entries;
14385 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014386 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14387 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014388 MAC_ADDR_ARRAY(
14389 params->mac_addrs[i].addr));
14390
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014391 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014392 params->mac_addrs[i].addr,
14393 sizeof(qcmacaddr));
14394 }
14395 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014396 qdf_status = wlansap_set_mac_acl(
14397 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014398 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014399 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014400 return -EINVAL;
14401 }
14402 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014403 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014404 hdd_device_mode_to_string(pAdapter->device_mode),
14405 pAdapter->device_mode);
14406 return -EINVAL;
14407 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014408 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014409 return 0;
14410}
14411
14412/**
14413 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14414 * __wlan_hdd_cfg80211_set_mac_acl
14415 * @wiphy: pointer to wiphy structure
14416 * @dev: pointer to net_device
14417 * @params: pointer to cfg80211_acl_data
14418 *
14419 * Return; 0 on success, error number otherwise
14420 */
14421static int
14422wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14423 struct net_device *dev,
14424 const struct cfg80211_acl_data *params)
14425{
14426 int ret;
14427
14428 cds_ssr_protect(__func__);
14429 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14430 cds_ssr_unprotect(__func__);
14431
14432 return ret;
14433}
14434
14435#ifdef WLAN_NL80211_TESTMODE
14436#ifdef FEATURE_WLAN_LPHB
14437/**
14438 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14439 * @pHddCtx: Pointer to hdd context
14440 * @lphbInd: Pointer to low power heart beat indication parameter
14441 *
14442 * Return: none
14443 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014444static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14445 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014446{
14447 struct sk_buff *skb;
14448
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014449 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014450
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014451 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014452 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014453
14454 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014455 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014456 return;
14457 }
14458
14459 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14460 wiphy, sizeof(tSirLPHBInd),
14461 GFP_ATOMIC);
14462 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014463 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014464 return;
14465 }
14466
14467 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014468 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014469 goto nla_put_failure;
14470 }
14471 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014472 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014473 goto nla_put_failure;
14474 }
14475 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014476 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014477 goto nla_put_failure;
14478 }
14479 cfg80211_testmode_event(skb, GFP_ATOMIC);
14480 return;
14481
14482nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014483 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014484 kfree_skb(skb);
14485
14486 return;
14487}
14488#endif /* FEATURE_WLAN_LPHB */
14489
14490/**
14491 * __wlan_hdd_cfg80211_testmode() - test mode
14492 * @wiphy: Pointer to wiphy
14493 * @data: Data pointer
14494 * @len: Data length
14495 *
14496 * Return: 0 for success, non-zero for failure
14497 */
14498static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14499 void *data, int len)
14500{
14501 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14502 int err;
14503 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14504
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014505 ENTER();
14506
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014507 err = wlan_hdd_validate_context(pHddCtx);
14508 if (err)
14509 return err;
14510
14511 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14512 len, wlan_hdd_tm_policy);
14513 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014514 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014515 return err;
14516 }
14517
14518 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014519 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014520 return -EINVAL;
14521 }
14522
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014523 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014524 TRACE_CODE_HDD_CFG80211_TESTMODE,
14525 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014526 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14527#ifdef FEATURE_WLAN_LPHB
14528 /* Low Power Heartbeat configuration request */
14529 case WLAN_HDD_TM_CMD_WLAN_HB:
14530 {
14531 int buf_len;
14532 void *buf;
14533 tSirLPHBReq *hb_params = NULL;
14534 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014535 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014536
14537 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014538 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014539 return -EINVAL;
14540 }
14541
14542 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14543 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14544
14545 hb_params_temp = (tSirLPHBReq *) buf;
14546 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14547 && (hb_params_temp->params.lphbTcpParamReq.
14548 timePeriodSec == 0))
14549 return -EINVAL;
14550
14551 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014552 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014553 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014554 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014555 return -ENOMEM;
14556 }
14557
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014558 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014559 smeStatus =
14560 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14561 hb_params,
14562 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014563 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014564 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014565 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014566 }
14567 return 0;
14568 }
14569#endif /* FEATURE_WLAN_LPHB */
14570
14571#if defined(QCA_WIFI_FTM)
14572 case WLAN_HDD_TM_CMD_WLAN_FTM:
14573 {
14574 int buf_len;
14575 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014576 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014577 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014578 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014579 return -EINVAL;
14580 }
14581
14582 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14583 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14584
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014585 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014586
14587 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14588
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014589 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014590 err = -EBUSY;
14591 break;
14592 }
14593#endif
14594
14595 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014596 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014597 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14598 return -EOPNOTSUPP;
14599 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014600 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014601 return err;
14602}
14603
14604/**
14605 * wlan_hdd_cfg80211_testmode() - test mode
14606 * @wiphy: Pointer to wiphy
14607 * @dev: Pointer to network device
14608 * @data: Data pointer
14609 * @len: Data length
14610 *
14611 * Return: 0 for success, non-zero for failure
14612 */
14613static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14614#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14615 struct wireless_dev *wdev,
14616#endif
14617 void *data, int len)
14618{
14619 int ret;
14620
14621 cds_ssr_protect(__func__);
14622 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14623 cds_ssr_unprotect(__func__);
14624
14625 return ret;
14626}
14627
14628#if defined(QCA_WIFI_FTM)
14629/**
14630 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14631 * @buf: Pointer to buffer
14632 * @buf_len: Buffer length
14633 *
14634 * Return: none
14635 */
14636void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14637{
14638 struct sk_buff *skb;
14639 hdd_context_t *hdd_ctx;
14640
14641 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014642 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014643 return;
14644 }
14645
Anurag Chouhan6d760662016-02-20 16:05:43 +053014646 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014647 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014648 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014649 return;
14650 }
14651
14652 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14653 buf_len, GFP_KERNEL);
14654 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014655 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014656 return;
14657 }
14658
14659 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14660 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14661 goto nla_put_failure;
14662
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014663 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014664
14665 cfg80211_testmode_event(skb, GFP_KERNEL);
14666 return;
14667
14668nla_put_failure:
14669 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014670 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014671}
14672#endif
14673#endif /* CONFIG_NL80211_TESTMODE */
14674
14675#ifdef QCA_HT_2040_COEX
14676/**
14677 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14678 * @wiphy: Pointer to wiphy
14679 * @dev: Pointer to network device
14680 * @chandef: Pointer to channel definition parameter
14681 *
14682 * Return: 0 for success, non-zero for failure
14683 */
14684static int
14685__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14686 struct net_device *dev,
14687 struct cfg80211_chan_def *chandef)
14688{
14689 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14690 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014691 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014692 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053014693 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014694
Anurag Chouhan6d760662016-02-20 16:05:43 +053014695 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014696 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014697 return -EINVAL;
14698 }
14699
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014700 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14701 hdd_err("invalid session id: %d", pAdapter->sessionId);
14702 return -EINVAL;
14703 }
14704
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014705 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14706 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014707 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014708 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014709
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014710 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014711 sme_get_config_param(pHddCtx->hHal, &sme_config);
14712 switch (chandef->width) {
14713 case NL80211_CHAN_WIDTH_20:
14714 if (sme_config.csrConfig.channelBondingMode24GHz !=
14715 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14716 sme_config.csrConfig.channelBondingMode24GHz =
14717 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14718 sme_update_config(pHddCtx->hHal, &sme_config);
14719 cbModeChange = true;
14720 }
14721 break;
14722
14723 case NL80211_CHAN_WIDTH_40:
14724 if (sme_config.csrConfig.channelBondingMode24GHz ==
14725 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14726 if (NL80211_CHAN_HT40MINUS ==
14727 cfg80211_get_chandef_type(chandef))
14728 sme_config.csrConfig.channelBondingMode24GHz =
14729 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14730 else
14731 sme_config.csrConfig.channelBondingMode24GHz =
14732 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14733 sme_update_config(pHddCtx->hHal, &sme_config);
14734 cbModeChange = true;
14735 }
14736 break;
14737
14738 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014739 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014740 return -EINVAL;
14741 }
14742
14743 if (!cbModeChange)
14744 return 0;
14745
Krunal Sonib4326f22016-03-10 13:05:51 -080014746 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014747 return 0;
14748
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014749 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014750 sme_config.csrConfig.channelBondingMode24GHz);
14751
14752 /* Change SAP ht2040 mode */
14753 status = hdd_set_sap_ht2040_mode(pAdapter,
14754 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014755 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014756 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014757 return -EINVAL;
14758 }
14759
14760 return 0;
14761}
14762
14763/**
14764 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14765 * @wiphy: Pointer to wiphy
14766 * @dev: Pointer to network device
14767 * @chandef: Pointer to channel definition parameter
14768 *
14769 * Return: 0 for success, non-zero for failure
14770 */
14771static int
14772wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14773 struct net_device *dev,
14774 struct cfg80211_chan_def *chandef)
14775{
14776 int ret;
14777
14778 cds_ssr_protect(__func__);
14779 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14780 cds_ssr_unprotect(__func__);
14781
14782 return ret;
14783}
14784#endif
14785
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014786#ifdef CHANNEL_SWITCH_SUPPORTED
14787/**
14788 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14789 * channel in SAP/GO
14790 * @wiphy: wiphy pointer
14791 * @dev: dev pointer.
14792 * @csa_params: Change channel params
14793 *
14794 * This function is called to switch channel in SAP/GO
14795 *
14796 * Return: 0 if success else return non zero
14797 */
14798static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14799 struct net_device *dev,
14800 struct cfg80211_csa_settings *csa_params)
14801{
14802 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14803 hdd_context_t *hdd_ctx;
14804 uint8_t channel;
14805 uint16_t freq;
14806 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014807 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014808
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014809 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014810 csa_params->chandef.chan->center_freq);
14811
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014812 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
14813 hdd_err("invalid session id: %d", adapter->sessionId);
14814 return -EINVAL;
14815 }
14816
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014817 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14818 ret = wlan_hdd_validate_context(hdd_ctx);
14819
14820 if (0 != ret)
14821 return ret;
14822
Krunal Sonib4326f22016-03-10 13:05:51 -080014823 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14824 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014825 return -ENOTSUPP;
14826
14827 freq = csa_params->chandef.chan->center_freq;
14828 channel = cds_freq_to_chan(freq);
14829
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014830 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14831
14832 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014833 return ret;
14834}
14835
14836/**
14837 * wlan_hdd_cfg80211_channel_switch()- function to switch
14838 * channel in SAP/GO
14839 * @wiphy: wiphy pointer
14840 * @dev: dev pointer.
14841 * @csa_params: Change channel params
14842 *
14843 * This function is called to switch channel in SAP/GO
14844 *
14845 * Return: 0 if success else return non zero
14846 */
14847static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14848 struct net_device *dev,
14849 struct cfg80211_csa_settings *csa_params)
14850{
14851 int ret;
14852
14853 cds_ssr_protect(__func__);
14854 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14855 cds_ssr_unprotect(__func__);
14856 return ret;
14857}
14858#endif
14859
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014860/**
14861 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14862 * translation from NL to policy manager type
14863 * @type: Generic connection mode type defined in NL
14864 *
14865 *
14866 * This function provides the type translation
14867 *
14868 * Return: cds_con_mode enum
14869 */
14870enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
14871 enum nl80211_iftype type)
14872{
14873 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
14874 switch (type) {
14875 case NL80211_IFTYPE_STATION:
14876 mode = CDS_STA_MODE;
14877 break;
14878 case NL80211_IFTYPE_P2P_CLIENT:
14879 mode = CDS_P2P_CLIENT_MODE;
14880 break;
14881 case NL80211_IFTYPE_P2P_GO:
14882 mode = CDS_P2P_GO_MODE;
14883 break;
14884 case NL80211_IFTYPE_AP:
14885 mode = CDS_SAP_MODE;
14886 break;
14887 case NL80211_IFTYPE_ADHOC:
14888 mode = CDS_IBSS_MODE;
14889 break;
14890 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014891 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014892 type);
14893 }
14894 return mode;
14895}
14896
14897/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014898 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14899 * @wiphy: Handle to struct wiphy to get handle to module context.
14900 * @chandef: Contains information about the capture channel to be set.
14901 *
14902 * This interface is called if and only if monitor mode interface alone is
14903 * active.
14904 *
14905 * Return: 0 success or error code on failure.
14906 */
14907static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14908 struct cfg80211_chan_def *chandef)
14909{
14910 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14911 hdd_adapter_t *adapter;
14912 hdd_station_ctx_t *sta_ctx;
14913 struct hdd_mon_set_ch_info *ch_info;
14914 QDF_STATUS status;
14915 tHalHandle hal_hdl;
14916 struct qdf_mac_addr bssid;
14917 tCsrRoamProfile roam_profile;
14918 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014919 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014920 int ret;
14921 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
14922
14923 ENTER();
14924
14925 ret = wlan_hdd_validate_context(hdd_ctx);
14926 if (ret)
14927 return ret;
14928
14929 hal_hdl = hdd_ctx->hHal;
14930
14931 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
14932 if (!adapter)
14933 return -EIO;
14934
14935 hdd_info("%s: set monitor mode Channel %d and freq %d",
14936 adapter->dev->name, chan_num, chandef->chan->center_freq);
14937
14938 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14939 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014940 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
14941 roam_profile.ChannelInfo.numOfChannels = 1;
14942 roam_profile.phyMode = ch_info->phy_mode;
14943 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014944 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014945
14946 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
14947 QDF_MAC_ADDR_SIZE);
14948
14949 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014950 /*
14951 * CDS api expects secondary channel for calculating
14952 * the channel params
14953 */
14954 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
14955 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
14956 if (chan_num >= 1 && chan_num <= 5)
14957 sec_ch = chan_num + 4;
14958 else if (chan_num >= 6 && chan_num <= 13)
14959 sec_ch = chan_num - 4;
14960 }
14961 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014962 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
14963 &roam_profile);
14964 if (status) {
14965 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
14966 status);
14967 ret = qdf_status_to_os_return(status);
14968 return ret;
14969 }
14970 EXIT();
14971 return 0;
14972}
14973
14974/**
14975 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14976 * @wiphy: Handle to struct wiphy to get handle to module context.
14977 * @chandef: Contains information about the capture channel to be set.
14978 *
14979 * This interface is called if and only if monitor mode interface alone is
14980 * active.
14981 *
14982 * Return: 0 success or error code on failure.
14983 */
14984static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14985 struct cfg80211_chan_def *chandef)
14986{
14987 int ret;
14988
14989 cds_ssr_protect(__func__);
14990 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
14991 cds_ssr_unprotect(__func__);
14992 return ret;
14993}
14994
14995/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014996 * struct cfg80211_ops - cfg80211_ops
14997 *
14998 * @add_virtual_intf: Add virtual interface
14999 * @del_virtual_intf: Delete virtual interface
15000 * @change_virtual_intf: Change virtual interface
15001 * @change_station: Change station
15002 * @add_beacon: Add beacon in sap mode
15003 * @del_beacon: Delete beacon in sap mode
15004 * @set_beacon: Set beacon in sap mode
15005 * @start_ap: Start ap
15006 * @change_beacon: Change beacon
15007 * @stop_ap: Stop ap
15008 * @change_bss: Change bss
15009 * @add_key: Add key
15010 * @get_key: Get key
15011 * @del_key: Delete key
15012 * @set_default_key: Set default key
15013 * @set_channel: Set channel
15014 * @scan: Scan
15015 * @connect: Connect
15016 * @disconnect: Disconnect
15017 * @join_ibss = Join ibss
15018 * @leave_ibss = Leave ibss
15019 * @set_wiphy_params = Set wiphy params
15020 * @set_tx_power = Set tx power
15021 * @get_tx_power = get tx power
15022 * @remain_on_channel = Remain on channel
15023 * @cancel_remain_on_channel = Cancel remain on channel
15024 * @mgmt_tx = Tx management frame
15025 * @mgmt_tx_cancel_wait = Cancel management tx wait
15026 * @set_default_mgmt_key = Set default management key
15027 * @set_txq_params = Set tx queue parameters
15028 * @get_station = Get station
15029 * @set_power_mgmt = Set power management
15030 * @del_station = Delete station
15031 * @add_station = Add station
15032 * @set_pmksa = Set pmksa
15033 * @del_pmksa = Delete pmksa
15034 * @flush_pmksa = Flush pmksa
15035 * @update_ft_ies = Update FT IEs
15036 * @tdls_mgmt = Tdls management
15037 * @tdls_oper = Tdls operation
15038 * @set_rekey_data = Set rekey data
15039 * @sched_scan_start = Scheduled scan start
15040 * @sched_scan_stop = Scheduled scan stop
15041 * @resume = Resume wlan
15042 * @suspend = Suspend wlan
15043 * @set_mac_acl = Set mac acl
15044 * @testmode_cmd = Test mode command
15045 * @set_ap_chanwidth = Set AP channel bandwidth
15046 * @dump_survey = Dump survey
15047 * @key_mgmt_set_pmk = Set pmk key management
15048 */
15049static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
15050 .add_virtual_intf = wlan_hdd_add_virtual_intf,
15051 .del_virtual_intf = wlan_hdd_del_virtual_intf,
15052 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
15053 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015054 .start_ap = wlan_hdd_cfg80211_start_ap,
15055 .change_beacon = wlan_hdd_cfg80211_change_beacon,
15056 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015057 .change_bss = wlan_hdd_cfg80211_change_bss,
15058 .add_key = wlan_hdd_cfg80211_add_key,
15059 .get_key = wlan_hdd_cfg80211_get_key,
15060 .del_key = wlan_hdd_cfg80211_del_key,
15061 .set_default_key = wlan_hdd_cfg80211_set_default_key,
15062 .scan = wlan_hdd_cfg80211_scan,
15063 .connect = wlan_hdd_cfg80211_connect,
15064 .disconnect = wlan_hdd_cfg80211_disconnect,
15065 .join_ibss = wlan_hdd_cfg80211_join_ibss,
15066 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
15067 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
15068 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
15069 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
15070 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
15071 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
15072 .mgmt_tx = wlan_hdd_mgmt_tx,
15073 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
15074 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
15075 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053015076 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015077 .get_station = wlan_hdd_cfg80211_get_station,
15078 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
15079 .del_station = wlan_hdd_cfg80211_del_station,
15080 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015081 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
15082 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
15083 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015084#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015085 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
15086#endif
15087#ifdef FEATURE_WLAN_TDLS
15088 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
15089 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
15090#endif
15091#ifdef WLAN_FEATURE_GTK_OFFLOAD
15092 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
15093#endif /* WLAN_FEATURE_GTK_OFFLOAD */
15094#ifdef FEATURE_WLAN_SCAN_PNO
15095 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
15096 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
15097#endif /*FEATURE_WLAN_SCAN_PNO */
15098 .resume = wlan_hdd_cfg80211_resume_wlan,
15099 .suspend = wlan_hdd_cfg80211_suspend_wlan,
15100 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
15101#ifdef WLAN_NL80211_TESTMODE
15102 .testmode_cmd = wlan_hdd_cfg80211_testmode,
15103#endif
15104#ifdef QCA_HT_2040_COEX
15105 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
15106#endif
15107 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015108#ifdef CHANNEL_SWITCH_SUPPORTED
15109 .channel_switch = wlan_hdd_cfg80211_channel_switch,
15110#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015111 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053015112#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
15113 defined(CFG80211_ABORT_SCAN)
15114 .abort_scan = wlan_hdd_cfg80211_abort_scan,
15115#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015116};