blob: d592cf9008923491e00f6df283ad05f5eaebc0fe [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhang3a210c52016-12-08 10:18:12 +08002 * Copyright (c) 2012-2017 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
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053069#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070#include "wlan_hdd_misc.h"
71#include "wlan_hdd_nan.h"
72#include <wlan_hdd_ipa.h>
73#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053074#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053075#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053076#include "pld_common.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053077
Paul Zhang3a210c52016-12-08 10:18:12 +080078#ifdef WLAN_UMAC_CONVERGENCE
79#include "wlan_cfg80211.h"
80#endif
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"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095
Ravi Joshideb5a8d2015-11-09 19:11:43 -080096#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053097#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070098#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070099#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530100#include "wlan_hdd_disa.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800101
Leo Changfdb45c32016-10-28 11:09:23 -0700102#include <cdp_txrx_cmn.h>
103#include <cdp_txrx_misc.h>
104
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105#define g_mode_rates_size (12)
106#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
108 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
109
110/*
111 * Android CTS verifier needs atleast this much wait time (in msec)
112 */
113#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
114
115/*
116 * Refer @tCfgProtection structure for definition of the bit map.
117 * below value is obtained by setting the following bit-fields.
118 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
119 */
120#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
121
122#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700123 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800124 .center_freq = (freq), \
125 .hw_value = (chan), \
126 .flags = (flag), \
127 .max_antenna_gain = 0, \
128 .max_power = 30, \
129}
130
131#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700132 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800133 .center_freq = (freq), \
134 .hw_value = (chan), \
135 .flags = (flag), \
136 .max_antenna_gain = 0, \
137 .max_power = 30, \
138}
139
140#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
141 { \
142 .bitrate = rate, \
143 .hw_value = rate_id, \
144 .flags = flag, \
145 }
146
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
148#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149
150#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800151
Agrawal Ashish65634612016-08-18 13:24:32 +0530152#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
153 mode <= DFS_MODE_DEPRIORITIZE))
154#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
155 || (channel >= 36 && channel <= 184))
156
Peng Xu4d67c8f2015-10-16 16:02:26 -0700157#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530158#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700159
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160static const u32 hdd_cipher_suites[] = {
161 WLAN_CIPHER_SUITE_WEP40,
162 WLAN_CIPHER_SUITE_WEP104,
163 WLAN_CIPHER_SUITE_TKIP,
164#ifdef FEATURE_WLAN_ESE
165#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
166#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
167 WLAN_CIPHER_SUITE_BTK,
168 WLAN_CIPHER_SUITE_KRK,
169 WLAN_CIPHER_SUITE_CCMP,
170#else
171 WLAN_CIPHER_SUITE_CCMP,
172#endif
173#ifdef FEATURE_WLAN_WAPI
174 WLAN_CIPHER_SUITE_SMS4,
175#endif
176#ifdef WLAN_FEATURE_11W
177 WLAN_CIPHER_SUITE_AES_CMAC,
178#endif
179};
180
Abhishek Singhf512bf32016-05-04 16:47:46 +0530181static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800182 HDD2GHZCHAN(2412, 1, 0),
183 HDD2GHZCHAN(2417, 2, 0),
184 HDD2GHZCHAN(2422, 3, 0),
185 HDD2GHZCHAN(2427, 4, 0),
186 HDD2GHZCHAN(2432, 5, 0),
187 HDD2GHZCHAN(2437, 6, 0),
188 HDD2GHZCHAN(2442, 7, 0),
189 HDD2GHZCHAN(2447, 8, 0),
190 HDD2GHZCHAN(2452, 9, 0),
191 HDD2GHZCHAN(2457, 10, 0),
192 HDD2GHZCHAN(2462, 11, 0),
193 HDD2GHZCHAN(2467, 12, 0),
194 HDD2GHZCHAN(2472, 13, 0),
195 HDD2GHZCHAN(2484, 14, 0),
196};
197
Abhishek Singhf512bf32016-05-04 16:47:46 +0530198static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199 HDD5GHZCHAN(5180, 36, 0),
200 HDD5GHZCHAN(5200, 40, 0),
201 HDD5GHZCHAN(5220, 44, 0),
202 HDD5GHZCHAN(5240, 48, 0),
203 HDD5GHZCHAN(5260, 52, 0),
204 HDD5GHZCHAN(5280, 56, 0),
205 HDD5GHZCHAN(5300, 60, 0),
206 HDD5GHZCHAN(5320, 64, 0),
207 HDD5GHZCHAN(5500, 100, 0),
208 HDD5GHZCHAN(5520, 104, 0),
209 HDD5GHZCHAN(5540, 108, 0),
210 HDD5GHZCHAN(5560, 112, 0),
211 HDD5GHZCHAN(5580, 116, 0),
212 HDD5GHZCHAN(5600, 120, 0),
213 HDD5GHZCHAN(5620, 124, 0),
214 HDD5GHZCHAN(5640, 128, 0),
215 HDD5GHZCHAN(5660, 132, 0),
216 HDD5GHZCHAN(5680, 136, 0),
217 HDD5GHZCHAN(5700, 140, 0),
218 HDD5GHZCHAN(5720, 144, 0),
219 HDD5GHZCHAN(5745, 149, 0),
220 HDD5GHZCHAN(5765, 153, 0),
221 HDD5GHZCHAN(5785, 157, 0),
222 HDD5GHZCHAN(5805, 161, 0),
223 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224 HDD5GHZCHAN(5852, 170, 0),
225 HDD5GHZCHAN(5855, 171, 0),
226 HDD5GHZCHAN(5860, 172, 0),
227 HDD5GHZCHAN(5865, 173, 0),
228 HDD5GHZCHAN(5870, 174, 0),
229 HDD5GHZCHAN(5875, 175, 0),
230 HDD5GHZCHAN(5880, 176, 0),
231 HDD5GHZCHAN(5885, 177, 0),
232 HDD5GHZCHAN(5890, 178, 0),
233 HDD5GHZCHAN(5895, 179, 0),
234 HDD5GHZCHAN(5900, 180, 0),
235 HDD5GHZCHAN(5905, 181, 0),
236 HDD5GHZCHAN(5910, 182, 0),
237 HDD5GHZCHAN(5915, 183, 0),
238 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800239};
240
241static struct ieee80211_rate g_mode_rates[] = {
242 HDD_G_MODE_RATETAB(10, 0x1, 0),
243 HDD_G_MODE_RATETAB(20, 0x2, 0),
244 HDD_G_MODE_RATETAB(55, 0x4, 0),
245 HDD_G_MODE_RATETAB(110, 0x8, 0),
246 HDD_G_MODE_RATETAB(60, 0x10, 0),
247 HDD_G_MODE_RATETAB(90, 0x20, 0),
248 HDD_G_MODE_RATETAB(120, 0x40, 0),
249 HDD_G_MODE_RATETAB(180, 0x80, 0),
250 HDD_G_MODE_RATETAB(240, 0x100, 0),
251 HDD_G_MODE_RATETAB(360, 0x200, 0),
252 HDD_G_MODE_RATETAB(480, 0x400, 0),
253 HDD_G_MODE_RATETAB(540, 0x800, 0),
254};
255
256static struct ieee80211_rate a_mode_rates[] = {
257 HDD_G_MODE_RATETAB(60, 0x10, 0),
258 HDD_G_MODE_RATETAB(90, 0x20, 0),
259 HDD_G_MODE_RATETAB(120, 0x40, 0),
260 HDD_G_MODE_RATETAB(180, 0x80, 0),
261 HDD_G_MODE_RATETAB(240, 0x100, 0),
262 HDD_G_MODE_RATETAB(360, 0x200, 0),
263 HDD_G_MODE_RATETAB(480, 0x400, 0),
264 HDD_G_MODE_RATETAB(540, 0x800, 0),
265};
266
267static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530268 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800269 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700270 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800271 .bitrates = g_mode_rates,
272 .n_bitrates = g_mode_rates_size,
273 .ht_cap.ht_supported = 1,
274 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
275 | IEEE80211_HT_CAP_GRN_FLD
276 | IEEE80211_HT_CAP_DSSSCCK40
277 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
278 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
279 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
280 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
281 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
282 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
283 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
284};
285
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530287 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700289 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800290 .bitrates = a_mode_rates,
291 .n_bitrates = a_mode_rates_size,
292 .ht_cap.ht_supported = 1,
293 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
294 | IEEE80211_HT_CAP_GRN_FLD
295 | IEEE80211_HT_CAP_DSSSCCK40
296 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
297 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
298 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
299 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
300 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
301 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
302 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
303 .vht_cap.vht_supported = 1,
304};
305
306/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800307 * TX/RX direction for each kind of interface
308 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800309static const struct ieee80211_txrx_stypes
310 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
311 [NL80211_IFTYPE_STATION] = {
312 .tx = 0xffff,
313 .rx = BIT(SIR_MAC_MGMT_ACTION) |
314 BIT(SIR_MAC_MGMT_PROBE_REQ),
315 },
316 [NL80211_IFTYPE_AP] = {
317 .tx = 0xffff,
318 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
319 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
320 BIT(SIR_MAC_MGMT_PROBE_REQ) |
321 BIT(SIR_MAC_MGMT_DISASSOC) |
322 BIT(SIR_MAC_MGMT_AUTH) |
323 BIT(SIR_MAC_MGMT_DEAUTH) |
324 BIT(SIR_MAC_MGMT_ACTION),
325 },
326 [NL80211_IFTYPE_ADHOC] = {
327 .tx = 0xffff,
328 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
330 BIT(SIR_MAC_MGMT_PROBE_REQ) |
331 BIT(SIR_MAC_MGMT_DISASSOC) |
332 BIT(SIR_MAC_MGMT_AUTH) |
333 BIT(SIR_MAC_MGMT_DEAUTH) |
334 BIT(SIR_MAC_MGMT_ACTION),
335 },
336 [NL80211_IFTYPE_P2P_CLIENT] = {
337 .tx = 0xffff,
338 .rx = BIT(SIR_MAC_MGMT_ACTION) |
339 BIT(SIR_MAC_MGMT_PROBE_REQ),
340 },
341 [NL80211_IFTYPE_P2P_GO] = {
342 /* This is also same as for SoftAP */
343 .tx = 0xffff,
344 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
345 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
346 BIT(SIR_MAC_MGMT_PROBE_REQ) |
347 BIT(SIR_MAC_MGMT_DISASSOC) |
348 BIT(SIR_MAC_MGMT_AUTH) |
349 BIT(SIR_MAC_MGMT_DEAUTH) |
350 BIT(SIR_MAC_MGMT_ACTION),
351 },
352};
353
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800354/* Interface limits and combinations registered by the driver */
355
356/* STA ( + STA ) combination */
357static const struct ieee80211_iface_limit
358 wlan_hdd_sta_iface_limit[] = {
359 {
360 .max = 3, /* p2p0 is a STA as well */
361 .types = BIT(NL80211_IFTYPE_STATION),
362 },
363};
364
365/* ADHOC (IBSS) limit */
366static const struct ieee80211_iface_limit
367 wlan_hdd_adhoc_iface_limit[] = {
368 {
369 .max = 1,
370 .types = BIT(NL80211_IFTYPE_STATION),
371 },
372 {
373 .max = 1,
374 .types = BIT(NL80211_IFTYPE_ADHOC),
375 },
376};
377
378/* AP ( + AP ) combination */
379static const struct ieee80211_iface_limit
380 wlan_hdd_ap_iface_limit[] = {
381 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530382 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800383 .types = BIT(NL80211_IFTYPE_AP),
384 },
385};
386
387/* P2P limit */
388static const struct ieee80211_iface_limit
389 wlan_hdd_p2p_iface_limit[] = {
390 {
391 .max = 1,
392 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
393 },
394 {
395 .max = 1,
396 .types = BIT(NL80211_IFTYPE_P2P_GO),
397 },
398};
399
400static const struct ieee80211_iface_limit
401 wlan_hdd_sta_ap_iface_limit[] = {
402 {
403 /* We need 1 extra STA interface for OBSS scan when SAP starts
404 * with HT40 in STA+SAP concurrency mode
405 */
406 .max = (1 + SAP_MAX_OBSS_STA_CNT),
407 .types = BIT(NL80211_IFTYPE_STATION),
408 },
409 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530410 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800411 .types = BIT(NL80211_IFTYPE_AP),
412 },
413};
414
415/* STA + P2P combination */
416static const struct ieee80211_iface_limit
417 wlan_hdd_sta_p2p_iface_limit[] = {
418 {
419 /* One reserved for dedicated P2PDEV usage */
420 .max = 2,
421 .types = BIT(NL80211_IFTYPE_STATION)
422 },
423 {
424 /* Support for two identical (GO + GO or CLI + CLI)
425 * or dissimilar (GO + CLI) P2P interfaces
426 */
427 .max = 2,
428 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
429 },
430};
431
432/* STA + AP + P2PGO combination */
433static const struct ieee80211_iface_limit
434wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
435 /* Support for AP+P2PGO interfaces */
436 {
437 .max = 2,
438 .types = BIT(NL80211_IFTYPE_STATION)
439 },
440 {
441 .max = 1,
442 .types = BIT(NL80211_IFTYPE_P2P_GO)
443 },
444 {
445 .max = 1,
446 .types = BIT(NL80211_IFTYPE_AP)
447 }
448};
449
450/* SAP + P2P combination */
451static const struct ieee80211_iface_limit
452wlan_hdd_sap_p2p_iface_limit[] = {
453 {
454 /* 1 dedicated for p2p0 which is a STA type */
455 .max = 1,
456 .types = BIT(NL80211_IFTYPE_STATION)
457 },
458 {
459 /* The p2p interface in SAP+P2P can be GO/CLI.
460 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
461 */
462 .max = 1,
463 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
464 },
465 {
466 /* SAP+GO to support only one SAP interface */
467 .max = 1,
468 .types = BIT(NL80211_IFTYPE_AP)
469 }
470};
471
472/* P2P + P2P combination */
473static const struct ieee80211_iface_limit
474wlan_hdd_p2p_p2p_iface_limit[] = {
475 {
476 /* 1 dedicated for p2p0 which is a STA type */
477 .max = 1,
478 .types = BIT(NL80211_IFTYPE_STATION)
479 },
480 {
481 /* The p2p interface in P2P+P2P can be GO/CLI.
482 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
483 */
484 .max = 2,
485 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
486 },
487};
488
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700489static const struct ieee80211_iface_limit
490 wlan_hdd_mon_iface_limit[] = {
491 {
492 .max = 3, /* Monitor interface */
493 .types = BIT(NL80211_IFTYPE_MONITOR),
494 },
495};
496
497static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800498 wlan_hdd_iface_combination[] = {
499 /* STA */
500 {
501 .limits = wlan_hdd_sta_iface_limit,
502 .num_different_channels = 2,
503 .max_interfaces = 3,
504 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
505 },
506 /* ADHOC */
507 {
508 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700509 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510 .max_interfaces = 2,
511 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
512 },
513 /* AP */
514 {
515 .limits = wlan_hdd_ap_iface_limit,
516 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530517 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
519 },
520 /* P2P */
521 {
522 .limits = wlan_hdd_p2p_iface_limit,
523 .num_different_channels = 2,
524 .max_interfaces = 2,
525 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
526 },
527 /* STA + AP */
528 {
529 .limits = wlan_hdd_sta_ap_iface_limit,
530 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530531 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800532 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
533 .beacon_int_infra_match = true,
534 },
535 /* STA + P2P */
536 {
537 .limits = wlan_hdd_sta_p2p_iface_limit,
538 .num_different_channels = 2,
539 /* one interface reserved for P2PDEV dedicated usage */
540 .max_interfaces = 4,
541 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
542 .beacon_int_infra_match = true,
543 },
544 /* STA + P2P GO + SAP */
545 {
546 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
547 /* we can allow 3 channels for three different persona
548 * but due to firmware limitation, allow max 2 concrnt channels.
549 */
550 .num_different_channels = 2,
551 /* one interface reserved for P2PDEV dedicated usage */
552 .max_interfaces = 4,
553 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
554 .beacon_int_infra_match = true,
555 },
556 /* SAP + P2P */
557 {
558 .limits = wlan_hdd_sap_p2p_iface_limit,
559 .num_different_channels = 2,
560 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
561 .max_interfaces = 3,
562 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
563 .beacon_int_infra_match = true,
564 },
565 /* P2P + P2P */
566 {
567 .limits = wlan_hdd_p2p_p2p_iface_limit,
568 .num_different_channels = 2,
569 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
570 .max_interfaces = 3,
571 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
572 .beacon_int_infra_match = true,
573 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530574 /* Monitor */
575 {
576 .limits = wlan_hdd_mon_iface_limit,
577 .max_interfaces = 3,
578 .num_different_channels = 2,
579 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
580 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582
583static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530584struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585
586#ifdef WLAN_NL80211_TESTMODE
587enum wlan_hdd_tm_attr {
588 WLAN_HDD_TM_ATTR_INVALID = 0,
589 WLAN_HDD_TM_ATTR_CMD = 1,
590 WLAN_HDD_TM_ATTR_DATA = 2,
591 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
592 WLAN_HDD_TM_ATTR_TYPE = 4,
593 /* keep last */
594 WLAN_HDD_TM_ATTR_AFTER_LAST,
595 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
596};
597
598enum wlan_hdd_tm_cmd {
599 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
600 WLAN_HDD_TM_CMD_WLAN_HB = 1,
601};
602
603#define WLAN_HDD_TM_DATA_MAX_LEN 5000
604
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530605enum wlan_hdd_vendor_ie_access_policy {
606 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
607 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
608};
609
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800610static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
611 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
612 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
613 .len = WLAN_HDD_TM_DATA_MAX_LEN},
614};
615#endif /* WLAN_NL80211_TESTMODE */
616
617#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
618static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
619 .flags = WIPHY_WOWLAN_MAGIC_PKT,
620 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
621 .pattern_min_len = 1,
622 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
623};
624#endif
625
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530627 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
628 * @flags: Pointer to the flags to Add channel switch flag.
629 *
630 * This Function adds Channel Switch support flag, if channel switch is
631 * supported by kernel.
632 * Return: void.
633 */
634#ifdef CHANNEL_SWITCH_SUPPORTED
635static inline void hdd_add_channel_switch_support(uint32_t *flags)
636{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800637 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530638 return;
639}
640#else
641static inline void hdd_add_channel_switch_support(uint32_t *flags)
642{
643 return;
644}
645#endif
646
Manikandan Mohan22b83722015-12-15 15:03:23 -0800647#ifdef FEATURE_WLAN_TDLS
648
649/* TDLS capabilities params */
650#define PARAM_MAX_TDLS_SESSION \
651 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
652#define PARAM_TDLS_FEATURE_SUPPORT \
653 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
654
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530655/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
657 * @wiphy: WIPHY structure pointer
658 * @wdev: Wireless device structure pointer
659 * @data: Pointer to the data received
660 * @data_len: Length of the data received
661 *
662 * This function provides TDLS capabilities
663 *
664 * Return: 0 on success and errno on failure
665 */
666static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
667 struct wireless_dev *wdev,
668 const void *data,
669 int data_len)
670{
671 int status;
672 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
673 struct sk_buff *skb;
674 uint32_t set = 0;
675
Jeff Johnson1f61b612016-02-12 16:28:33 -0800676 ENTER_DEV(wdev->netdev);
677
Anurag Chouhan6d760662016-02-20 16:05:43 +0530678 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679 hdd_err("Command not allowed in FTM mode");
680 return -EPERM;
681 }
682
683 status = wlan_hdd_validate_context(hdd_ctx);
684 if (status)
685 return status;
686
687 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
688 NLMSG_HDRLEN);
689 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700690 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691 goto fail;
692 }
693
694 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700695 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
697 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700698 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 goto fail;
700 }
701 } else {
702 set = set | WIFI_TDLS_SUPPORT;
703 set = set | (hdd_ctx->config->fTDLSExternalControl ?
704 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
705 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
706 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700707 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
709 hdd_ctx->max_num_tdls_sta) ||
710 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
711 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700712 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800713 goto fail;
714 }
715 }
716 return cfg80211_vendor_cmd_reply(skb);
717fail:
718 if (skb)
719 kfree_skb(skb);
720 return -EINVAL;
721}
722
723/**
724 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
725 * @wiphy: WIPHY structure pointer
726 * @wdev: Wireless device structure pointer
727 * @data: Pointer to the data received
728 * @data_len: Length of the data received
729 *
730 * This function provides TDLS capabilities
731 *
732 * Return: 0 on success and errno on failure
733 */
734static int
735wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
736 struct wireless_dev *wdev,
737 const void *data,
738 int data_len)
739{
740 int ret;
741
742 cds_ssr_protect(__func__);
743 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
744 data, data_len);
745 cds_ssr_unprotect(__func__);
746
747 return ret;
748}
749#endif
750
751#ifdef QCA_HT_2040_COEX
752static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
753#endif
754
755#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
756/*
757 * FUNCTION: wlan_hdd_send_avoid_freq_event
758 * This is called when wlan driver needs to send vendor specific
759 * avoid frequency range event to userspace
760 */
761int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
762 tHddAvoidFreqList *pAvoidFreqList)
763{
764 struct sk_buff *vendor_event;
765
766 ENTER();
767
768 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700769 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800770 return -EINVAL;
771 }
772
773 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700774 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 return -EINVAL;
776 }
777
778 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
779 NULL,
780 sizeof(tHddAvoidFreqList),
781 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
782 GFP_KERNEL);
783 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700784 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785 return -EINVAL;
786 }
787
788 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
789 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
790
791 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
792
793 EXIT();
794 return 0;
795}
796#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
797
798/* vendor specific events */
799static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
800#ifdef FEATURE_WLAN_CH_AVOID
801 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
802 .vendor_id =
803 QCA_NL80211_VENDOR_ID,
804 .subcmd =
805 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
806 },
807#endif /* FEATURE_WLAN_CH_AVOID */
808
809#ifdef WLAN_FEATURE_NAN
810 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
811 .vendor_id =
812 QCA_NL80211_VENDOR_ID,
813 .subcmd =
814 QCA_NL80211_VENDOR_SUBCMD_NAN
815 },
816#endif
817
818#ifdef WLAN_FEATURE_STATS_EXT
819 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
820 .vendor_id =
821 QCA_NL80211_VENDOR_ID,
822 .subcmd =
823 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
824 },
825#endif /* WLAN_FEATURE_STATS_EXT */
826#ifdef FEATURE_WLAN_EXTSCAN
827 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
828 .vendor_id =
829 QCA_NL80211_VENDOR_ID,
830 .subcmd =
831 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
832 },
833 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
834 .vendor_id =
835 QCA_NL80211_VENDOR_ID,
836 .subcmd =
837 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
838 },
839 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
840 .
841 vendor_id
842 =
843 QCA_NL80211_VENDOR_ID,
844 .subcmd =
845 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
846 },
847 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
848 .
849 vendor_id
850 =
851 QCA_NL80211_VENDOR_ID,
852 .
853 subcmd =
854 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
855 },
856 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
857 .
858 vendor_id
859 =
860 QCA_NL80211_VENDOR_ID,
861 .
862 subcmd
863 =
864 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
865 },
866 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
867 .
868 vendor_id
869 =
870 QCA_NL80211_VENDOR_ID,
871 .subcmd =
872 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
873 },
874 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
875 .vendor_id =
876 QCA_NL80211_VENDOR_ID,
877 .subcmd =
878 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
879 },
880 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
881 .
882 vendor_id
883 =
884 QCA_NL80211_VENDOR_ID,
885 .subcmd =
886 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
887 },
888 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
889 .
890 vendor_id
891 =
892 QCA_NL80211_VENDOR_ID,
893 .subcmd =
894 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
895 },
896 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
897 .
898 vendor_id
899 =
900 QCA_NL80211_VENDOR_ID,
901 .
902 subcmd
903 =
904 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
905 },
906 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
907 .
908 vendor_id
909 =
910 QCA_NL80211_VENDOR_ID,
911 .
912 subcmd =
913 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
914 },
915 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
916 .
917 vendor_id
918 =
919 QCA_NL80211_VENDOR_ID,
920 .
921 subcmd
922 =
923 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
924 },
925 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
926 .
927 vendor_id
928 =
929 QCA_NL80211_VENDOR_ID,
930 .
931 subcmd
932 =
933 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
934 },
935 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
936 .vendor_id = QCA_NL80211_VENDOR_ID,
937 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
938 },
939 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
940 .vendor_id = QCA_NL80211_VENDOR_ID,
941 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
942 },
943#endif /* FEATURE_WLAN_EXTSCAN */
944
945#ifdef WLAN_FEATURE_LINK_LAYER_STATS
946 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
947 .vendor_id =
948 QCA_NL80211_VENDOR_ID,
949 .subcmd =
950 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
951 },
952 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
953 .vendor_id =
954 QCA_NL80211_VENDOR_ID,
955 .subcmd =
956 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
957 },
958 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
959 .vendor_id =
960 QCA_NL80211_VENDOR_ID,
961 .subcmd =
962 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
963 },
964 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
965 .vendor_id =
966 QCA_NL80211_VENDOR_ID,
967 .subcmd =
968 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
969 },
970 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
971 .vendor_id =
972 QCA_NL80211_VENDOR_ID,
973 .subcmd =
974 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
975 },
976 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
981 },
982#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
983 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
984 .vendor_id =
985 QCA_NL80211_VENDOR_ID,
986 .subcmd =
987 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
988 },
989 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
990 .vendor_id = QCA_NL80211_VENDOR_ID,
991 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
992 },
993#ifdef WLAN_FEATURE_ROAM_OFFLOAD
994 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
995 .vendor_id =
996 QCA_NL80211_VENDOR_ID,
997 .subcmd =
998 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
999 },
1000#endif
1001 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1002 .vendor_id =
1003 QCA_NL80211_VENDOR_ID,
1004 .subcmd =
1005 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1006 },
1007 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1020 .vendor_id =
1021 QCA_NL80211_VENDOR_ID,
1022 .subcmd =
1023 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1024 },
1025 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1026 .vendor_id =
1027 QCA_NL80211_VENDOR_ID,
1028 .subcmd =
1029 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1030 },
1031#ifdef FEATURE_WLAN_EXTSCAN
1032 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1033 .vendor_id = QCA_NL80211_VENDOR_ID,
1034 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1035 },
1036 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1037 .vendor_id = QCA_NL80211_VENDOR_ID,
1038 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1039 },
1040 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1041 .vendor_id = QCA_NL80211_VENDOR_ID,
1042 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1043 },
1044 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1045 .vendor_id = QCA_NL80211_VENDOR_ID,
1046 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1047 },
1048 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1049 .vendor_id = QCA_NL80211_VENDOR_ID,
1050 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1051 },
1052#endif /* FEATURE_WLAN_EXTSCAN */
1053 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1054 .vendor_id = QCA_NL80211_VENDOR_ID,
1055 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1056 },
1057#ifdef WLAN_FEATURE_MEMDUMP
1058 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1059 .vendor_id = QCA_NL80211_VENDOR_ID,
1060 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1061 },
1062#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001063#ifdef WLAN_FEATURE_TSF
1064 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1067 },
1068#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001069 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1070 .vendor_id = QCA_NL80211_VENDOR_ID,
1071 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1072 },
1073 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1074 .vendor_id = QCA_NL80211_VENDOR_ID,
1075 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1076 },
1077 /* OCB events */
1078 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1079 .vendor_id = QCA_NL80211_VENDOR_ID,
1080 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1081 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001082#ifdef FEATURE_LFR_SUBNET_DETECTION
1083 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1084 .vendor_id = QCA_NL80211_VENDOR_ID,
1085 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1086 },
1087#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001088
1089#ifdef WLAN_FEATURE_NAN_DATAPATH
1090 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1091 .vendor_id = QCA_NL80211_VENDOR_ID,
1092 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1093 },
1094#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001095
1096 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1097 .vendor_id = QCA_NL80211_VENDOR_ID,
1098 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1099 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301100 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1101 .vendor_id = QCA_NL80211_VENDOR_ID,
1102 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1103 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301104 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1105 .vendor_id = QCA_NL80211_VENDOR_ID,
1106 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1107 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001108#ifdef WLAN_UMAC_CONVERGENCE
1109 COMMON_VENDOR_EVENTS
1110#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111};
1112
1113/**
1114 * __is_driver_dfs_capable() - get driver DFS capability
1115 * @wiphy: pointer to wireless wiphy structure.
1116 * @wdev: pointer to wireless_dev structure.
1117 * @data: Pointer to the data to be passed via vendor interface
1118 * @data_len:Length of the data to be passed
1119 *
1120 * This function is called by userspace to indicate whether or not
1121 * the driver supports DFS offload.
1122 *
1123 * Return: 0 on success, negative errno on failure
1124 */
1125static int __is_driver_dfs_capable(struct wiphy *wiphy,
1126 struct wireless_dev *wdev,
1127 const void *data,
1128 int data_len)
1129{
1130 u32 dfs_capability = 0;
1131 struct sk_buff *temp_skbuff;
1132 int ret_val;
1133 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1134
Jeff Johnson1f61b612016-02-12 16:28:33 -08001135 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136
1137 ret_val = wlan_hdd_validate_context(hdd_ctx);
1138 if (ret_val)
1139 return ret_val;
1140
Anurag Chouhan6d760662016-02-20 16:05:43 +05301141 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142 hdd_err("Command not allowed in FTM mode");
1143 return -EPERM;
1144 }
1145
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001147
1148 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1149 NLMSG_HDRLEN);
1150
1151 if (temp_skbuff != NULL) {
1152 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1153 dfs_capability);
1154 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001155 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001156 kfree_skb(temp_skbuff);
1157
1158 return ret_val;
1159 }
1160
1161 return cfg80211_vendor_cmd_reply(temp_skbuff);
1162 }
1163
Jeff Johnson020db452016-06-29 14:37:26 -07001164 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001165 return -ENOMEM;
1166}
1167
1168/**
1169 * is_driver_dfs_capable() - get driver DFS capability
1170 * @wiphy: pointer to wireless wiphy structure.
1171 * @wdev: pointer to wireless_dev structure.
1172 * @data: Pointer to the data to be passed via vendor interface
1173 * @data_len:Length of the data to be passed
1174 *
1175 * This function is called by userspace to indicate whether or not
1176 * the driver supports DFS offload. This is an SSR-protected
1177 * wrapper function.
1178 *
1179 * Return: 0 on success, negative errno on failure
1180 */
1181static int is_driver_dfs_capable(struct wiphy *wiphy,
1182 struct wireless_dev *wdev,
1183 const void *data,
1184 int data_len)
1185{
1186 int ret;
1187
1188 cds_ssr_protect(__func__);
1189 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1190 cds_ssr_unprotect(__func__);
1191
1192 return ret;
1193}
1194
1195/**
1196 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1197 *
1198 * @adapter: SAP adapter pointer
1199 *
1200 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1201 * radio. So in case of DFS MCC scenario override current SAP given config
1202 * to follow concurrent SAP DFS config
1203 *
1204 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1205 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1207{
1208 hdd_adapter_t *con_sap_adapter;
1209 tsap_Config_t *sap_config, *con_sap_config;
1210 int con_ch;
1211
1212 /*
1213 * Check if AP+AP case, once primary AP chooses a DFS
1214 * channel secondary AP should always follow primary APs channel
1215 */
1216 if (!cds_concurrent_beaconing_sessions_running())
1217 return 0;
1218
1219 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1220 if (!con_sap_adapter)
1221 return 0;
1222
1223 sap_config = &adapter->sessionCtx.ap.sapConfig;
1224 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1225 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1226
1227 if (!CDS_IS_DFS_CH(con_ch))
1228 return 0;
1229
Jeff Johnson020db452016-06-29 14:37:26 -07001230 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001232 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001233 sap_config->channel = con_ch;
1234
1235 if (con_sap_config->acs_cfg.acs_mode == true) {
1236 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1237 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001238 hdd_err("Primary AP channel config error");
1239 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240 con_ch, con_sap_config->acs_cfg.pri_ch,
1241 con_sap_config->acs_cfg.ht_sec_ch);
1242 return -EINVAL;
1243 }
1244 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1245 * MCC restriction. So free ch list allocated in do_acs
1246 * func for Sec AP and realloc for Pri AP ch list size
1247 */
1248 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301249 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001250
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301251 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001252 &con_sap_config->acs_cfg,
1253 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301254 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 sizeof(uint8_t) *
1256 con_sap_config->acs_cfg.ch_list_count);
1257 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001258 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001259 return -ENOMEM;
1260 }
1261
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301262 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001263 con_sap_config->acs_cfg.ch_list,
1264 con_sap_config->acs_cfg.ch_list_count);
1265
1266 } else {
1267 sap_config->acs_cfg.pri_ch = con_ch;
1268 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1269 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1270 }
1271
1272 return con_ch;
1273}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001274
1275/**
1276 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1277 * @sap_cfg: pointer to SAP config struct
1278 *
1279 * This function sets the default ACS start and end channel for the given band
1280 * and also parses the given ACS channel list.
1281 *
1282 * Return: None
1283 */
1284
1285static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1286 bool vht_enabled)
1287{
1288 int i;
1289 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1290 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001291 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1292 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001293 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1294 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001295 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1296 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001299 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1300 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1302 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001303 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1304 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305 }
1306
1307 if (ht_enabled)
1308 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1309
1310 if (vht_enabled)
1311 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1312
1313
1314 /* Parse ACS Chan list from hostapd */
1315 if (!sap_cfg->acs_cfg.ch_list)
1316 return;
1317
1318 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1319 sap_cfg->acs_cfg.end_ch =
1320 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1321 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301322 /* avoid channel as start channel */
1323 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1324 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001325 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1326 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1327 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1328 }
1329}
1330
1331
1332static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1333
1334/**
1335 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1336 * @adapter: pointer to SAP adapter struct
1337 *
1338 * This function starts the ACS procedure if there are no
1339 * constraints like MBSSID DFS restrictions.
1340 *
1341 * Return: Status of ACS Start procedure
1342 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301343int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001344{
1345
1346 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1347 tsap_Config_t *sap_config;
1348 tpWLAN_SAPEventCB acs_event_callback;
1349 int status;
1350
1351 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301352 if (hdd_ctx->acs_policy.acs_channel)
1353 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1354 else
1355 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001356
1357 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1358 if (status < 0) {
1359 return status;
1360 } else {
1361 if (status > 0) {
1362 /*notify hostapd about channel override */
1363 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1364 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1365 return 0;
1366 }
1367 }
1368 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1369 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001370 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 return -EINVAL;
1372 }
1373
1374 acs_event_callback = hdd_hostapd_sap_event_cb;
1375
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301376 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301377 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301378 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001380 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001381 acs_event_callback, sap_config, adapter->dev);
1382
1383
1384 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001385 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386 return -EINVAL;
1387 }
bings394afdd2017-01-09 11:22:38 +08001388 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1389 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001390 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1391
1392 return 0;
1393}
1394
1395/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301396 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1397 * @ap_adapter: AP adapter
1398 * @nol: Non-occupancy list
1399 * @nol_len: Length of NOL
1400 *
1401 * Get the NOL for SAP
1402 *
1403 * Return: Zero on success, non-zero on failure
1404 */
1405static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1406 uint32_t *nol_len)
1407{
1408 QDF_STATUS ret;
1409
1410 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1411 nol, nol_len);
1412 if (QDF_IS_STATUS_ERROR(ret))
1413 return -EINVAL;
1414
1415 return 0;
1416}
1417
1418/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301419 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1420 * @hdd_ctx: hdd context
1421 * @acs_chan_params: external acs channel params
1422 * @sap_config: SAP config
1423 *
1424 * This API provides unsorted pcl list.
1425 * this list is a subset of the valid channel list given by hostapd.
1426 * if channel is not present in pcl, weightage will be given as zero
1427 *
1428 * Return: Zero on success, non-zero on failure
1429 */
1430static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1431 struct hdd_vendor_acs_chan_params *acs_chan_params,
1432 tsap_Config_t *sap_config)
1433{
1434 int i, j;
1435
1436 for (i = 0; i < acs_chan_params->channel_count; i++) {
1437 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1438 if (acs_chan_params->channel_list[i] ==
1439 sap_config->acs_cfg.pcl_channels[j]) {
1440 acs_chan_params->vendor_pcl_list[i] =
1441 sap_config->acs_cfg.pcl_channels[j];
1442 acs_chan_params->vendor_weight_list[i] =
1443 sap_config->acs_cfg.
1444 pcl_channels_weight_list[j];
1445 break;
1446 } else {
1447 acs_chan_params->vendor_pcl_list[i] =
1448 acs_chan_params->channel_list[i];
1449 acs_chan_params->vendor_weight_list[i] = 0;
1450 }
1451 }
1452 }
1453 if (hdd_ctx->unsafe_channel_count == 0)
1454 return;
1455 /* Update unsafe channel weight as zero */
1456 for (i = 0; i < acs_chan_params->channel_count; i++) {
1457 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1458 if (acs_chan_params->channel_list[i] ==
1459 hdd_ctx->unsafe_channel_list[j]) {
1460 acs_chan_params->vendor_weight_list[i] = 0;
1461 }
1462 }
1463 }
1464}
1465
1466/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301467 * hdd_update_reg_chan_info : This API contructs channel info
1468 * for all the given channel
1469 * @adapter: pointer to SAP adapter struct
1470 * @channel_count: channel count
1471 * @channel_list: channel list
1472 *
1473 * Return: Status of of channel information updation
1474 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301475static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301476 uint32_t channel_count,
1477 uint8_t *channel_list)
1478{
1479 int i;
1480 struct hdd_channel_info *icv;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301481 struct ch_params_s ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301482 uint8_t bw_offset = 0, chan = 0;
1483 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1484 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1485
1486 /* memory allocation */
1487 sap_config->channel_info = qdf_mem_malloc(
1488 sizeof(struct hdd_channel_info) *
1489 channel_count);
1490 if (!sap_config->channel_info) {
1491 hdd_err("memory allocation failed");
1492 return -ENOMEM;
1493
1494 }
1495 for (i = 0; i < channel_count; i++) {
1496 icv = &sap_config->channel_info[i];
1497 chan = channel_list[i];
1498
1499 if (chan == 0)
1500 continue;
1501
1502 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1503 bw_offset = 1 << BW_40_OFFSET_BIT;
1504 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1505 bw_offset = 1 << BW_20_OFFSET_BIT;
1506 icv->freq = cds_get_channel_freq(chan);
1507 icv->ieee_chan_number = chan;
1508 icv->max_reg_power = cds_get_channel_reg_power(chan);
1509
1510 /* filling demo values */
1511 icv->max_radio_power = HDD_MAX_TX_POWER;
1512 icv->min_radio_power = HDD_MIN_TX_POWER;
1513 /* not supported in current driver */
1514 icv->max_antenna_gain = 0;
1515
1516 icv->reg_class_id = wlan_hdd_find_opclass(
1517 WLAN_HDD_GET_HAL_CTX(adapter),
1518 chan, bw_offset);
1519
1520 if (CDS_IS_CHANNEL_5GHZ(chan)) {
1521 ch_params.ch_width = sap_config->acs_cfg.ch_width;
1522 cds_set_channel_params(chan, 0, &ch_params);
1523 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1524 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1525 }
1526 icv->flags = 0;
1527 icv->flags = cds_get_vendor_reg_flags(chan,
1528 sap_config->acs_cfg.ch_width,
1529 sap_config->acs_cfg.is_ht_enabled,
1530 sap_config->acs_cfg.is_vht_enabled,
1531 hdd_ctx->config->enable_sub_20_channel_width);
1532
1533 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1534 icv->freq, icv->flags,
1535 icv->flagext, icv->ieee_chan_number,
1536 icv->max_reg_power, icv->max_radio_power,
1537 icv->min_radio_power, icv->reg_class_id,
1538 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1539 icv->vht_center_freq_seg1);
1540 }
1541 return 0;
1542}
1543
1544/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1545#define CHAN_INFO_ATTR_FLAGS \
1546 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1547#define CHAN_INFO_ATTR_FLAG_EXT \
1548 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1549#define CHAN_INFO_ATTR_FREQ \
1550 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1551#define CHAN_INFO_ATTR_MAX_REG_POWER \
1552 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1553#define CHAN_INFO_ATTR_MAX_POWER \
1554 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1555#define CHAN_INFO_ATTR_MIN_POWER \
1556 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1557#define CHAN_INFO_ATTR_REG_CLASS_ID \
1558 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1559#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1560 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1561#define CHAN_INFO_ATTR_VHT_SEG_0 \
1562 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1563#define CHAN_INFO_ATTR_VHT_SEG_1 \
1564 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1565
1566/**
1567 * hdd_cfg80211_update_channel_info() - add channel info attributes
1568 * @skb: pointer to sk buff
1569 * @hdd_ctx: pointer to hdd station context
1570 * @idx: attribute index
1571 *
1572 * Return: Success(0) or reason code for failure
1573 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301574static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301575hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1576 tsap_Config_t *sap_config, int idx)
1577{
1578 struct nlattr *nla_attr, *channel;
1579 struct hdd_channel_info *icv;
1580 int i;
1581
1582 nla_attr = nla_nest_start(skb, idx);
1583 if (!nla_attr)
1584 goto fail;
1585
1586 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1587 channel = nla_nest_start(skb, i);
1588 if (!channel)
1589 goto fail;
1590
1591 icv = &sap_config->channel_info[i];
1592 if (!icv) {
1593 hdd_err("channel info not found");
1594 goto fail;
1595 }
1596 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1597 icv->freq) ||
1598 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1599 icv->flags) ||
1600 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1601 icv->flagext) ||
1602 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1603 icv->max_reg_power) ||
1604 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1605 icv->max_radio_power) ||
1606 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1607 icv->min_radio_power) ||
1608 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1609 icv->reg_class_id) ||
1610 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1611 icv->max_antenna_gain) ||
1612 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1613 icv->vht_center_freq_seg0) ||
1614 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1615 icv->vht_center_freq_seg1)) {
1616 hdd_err("put fail");
1617 goto fail;
1618 }
1619 nla_nest_end(skb, channel);
1620 }
1621 nla_nest_end(skb, nla_attr);
1622 return 0;
1623fail:
1624 hdd_err("nl channel update failed");
1625 return -EINVAL;
1626}
1627#undef CHAN_INFO_ATTR_FLAGS
1628#undef CHAN_INFO_ATTR_FLAG_EXT
1629#undef CHAN_INFO_ATTR_FREQ
1630#undef CHAN_INFO_ATTR_MAX_REG_POWER
1631#undef CHAN_INFO_ATTR_MAX_POWER
1632#undef CHAN_INFO_ATTR_MIN_POWER
1633#undef CHAN_INFO_ATTR_REG_CLASS_ID
1634#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1635#undef CHAN_INFO_ATTR_VHT_SEG_0
1636#undef CHAN_INFO_ATTR_VHT_SEG_1
1637
1638/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301639 * hdd_cfg80211_update_pcl() - add pcl info attributes
1640 * @skb: pointer to sk buff
1641 * @hdd_ctx: pointer to hdd station context
1642 * @idx: attribute index
1643 * @vendor_pcl_list: PCL list
1644 * @vendor_weight_list: PCL weights
1645 *
1646 * Return: Success(0) or reason code for failure
1647 */
1648static int32_t
1649hdd_cfg80211_update_pcl(struct sk_buff *skb,
1650 uint8_t ch_list_count, int idx,
1651 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1652{
1653 struct nlattr *nla_attr, *channel;
1654 int i;
1655
1656 nla_attr = nla_nest_start(skb, idx);
1657
1658 if (!nla_attr)
1659 goto fail;
1660
1661 for (i = 0; i < ch_list_count; i++) {
1662 channel = nla_nest_start(skb, i);
1663 if (!channel)
1664 goto fail;
1665 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1666 vendor_pcl_list[i]) ||
1667 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1668 vendor_weight_list[i])) {
1669 hdd_err("put fail");
1670 goto fail;
1671 }
1672 nla_nest_end(skb, channel);
1673 }
1674 nla_nest_end(skb, nla_attr);
1675
1676 return 0;
1677fail:
1678 hdd_err("updating pcl list failed");
1679 return -EINVAL;
1680}
1681
1682static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1683{
1684 /* Get scan band */
1685 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1686 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1687 *band = eCSR_BAND_24;
1688 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1689 *band = eCSR_BAND_5G;
1690 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1691 *band = eCSR_BAND_ALL;
1692 }
1693 /* Auto is not supported currently */
1694 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1695 hdd_err("invalid band");
1696 *band = eCSR_BAND_24;
1697 }
1698}
1699
1700void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1701 uint8_t reason)
1702{
1703 struct sk_buff *skb;
1704 tsap_Config_t *sap_config;
1705 uint32_t channel_count = 0, status;
1706 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1707 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1708 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1709 struct hdd_vendor_acs_chan_params acs_chan_params;
1710 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1711 eCsrBand band = eCSR_BAND_24;
1712 eCsrPhyMode phy_mode;
1713
1714 if (!hdd_ctx) {
1715 hdd_err("HDD context is NULL");
1716 return;
1717 }
1718
1719 ENTER();
1720 sap_config = &adapter->sessionCtx.ap.sapConfig;
1721
1722 /* Get valid channels for SAP */
1723 wlan_hdd_sap_get_valid_channellist(adapter,
1724 &channel_count, channel_list);
1725
1726 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1727 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1728 /* Get phymode */
1729 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1730
1731 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1732 &(adapter->wdev),
1733 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1734 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1735 GFP_KERNEL);
1736
1737 if (!skb) {
1738 hdd_err("cfg80211_vendor_event_alloc failed");
1739 return;
1740 }
1741 /*
1742 * Application expects pcl to be a subset of channel list
1743 * Remove all channels which are not in channel list from pcl
1744 * and add weight as zero
1745 */
1746 acs_chan_params.channel_count = channel_count;
1747 acs_chan_params.channel_list = channel_list;
1748 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1749 acs_chan_params.vendor_weight_list = vendor_weight_list;
1750
1751 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1752 sap_config);
1753 /* Update values in NL buffer */
1754 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1755 reason) ||
1756 nla_put_u8(skb,
1757 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1758 false) ||
1759 nla_put_u8(skb,
1760 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1761 true) ||
1762 nla_put_u8(skb,
1763 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1764 true) ||
1765 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1766 sap_config->acs_cfg.ch_width) ||
1767 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1768 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1769 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1770 band) ||
1771 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1772 phy_mode) ||
1773 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1774 channel_count, channel_list)) {
1775 hdd_err("nla put fail");
1776 goto fail;
1777 }
1778 status = hdd_cfg80211_update_pcl(skb, channel_count,
1779 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1780 vendor_pcl_list, vendor_weight_list);
1781
1782 if (status != 0)
1783 goto fail;
1784
1785 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1786 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1787
1788 if (status != 0)
1789 goto fail;
1790
1791 cfg80211_vendor_event(skb, GFP_KERNEL);
1792 return;
1793fail:
1794 if (skb)
1795 kfree_skb(skb);
1796}
1797
1798static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1799{
1800 struct hdd_external_acs_timer_context *timer_context;
1801
1802 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1803 return 0;
1804
1805 hdd_notice("Starting vendor app based ACS");
1806 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1807 timer_context->adapter = adapter;
1808
1809 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1810 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1811 QDF_TIMER_TYPE_SW,
1812 hdd_acs_response_timeout_handler, timer_context);
1813 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1814 return 0;
1815}
1816
1817/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001818 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1819 * @wiphy: Linux wiphy struct pointer
1820 * @wdev: Linux wireless device struct pointer
1821 * @data: ACS information from hostapd
1822 * @data_len: ACS information length
1823 *
1824 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1825 * and starts ACS procedure.
1826 *
1827 * Return: ACS procedure start status
1828 */
1829
1830static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1831 struct wireless_dev *wdev,
1832 const void *data, int data_len)
1833{
1834 struct net_device *ndev = wdev->netdev;
1835 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1836 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1837 tsap_Config_t *sap_config;
1838 struct sk_buff *temp_skbuff;
1839 int status = -EINVAL, i = 0;
1840 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1841 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301842 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001843
1844 /* ***Note*** Donot set SME config related to ACS operation here because
1845 * ACS operation is not synchronouse and ACS for Second AP may come when
1846 * ACS operation for first AP is going on. So only do_acs is split to
1847 * seperate start_acs routine. Also SME-PMAC struct that is used to
1848 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1849 * config shall be set only from start_acs.
1850 */
1851
1852 /* nla_policy Policy template. Policy not applied as some attributes are
1853 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1854 *
1855 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1856 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1857 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1858 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1859 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1860 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1861 */
1862
Jeff Johnson1f61b612016-02-12 16:28:33 -08001863 ENTER_DEV(ndev);
1864
Anurag Chouhan6d760662016-02-20 16:05:43 +05301865 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001866 hdd_err("Command not allowed in FTM mode");
1867 return -EPERM;
1868 }
1869
Kapil Gupta8878ad92017-02-13 11:56:04 +05301870 if (hdd_ctx->config->force_sap_acs &&
1871 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001872 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001873 return -EPERM;
1874 }
1875
1876 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301877 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001878 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301879
Naveen Rawat64e477e2016-05-20 10:34:56 -07001880 if (cds_is_sub_20_mhz_enabled()) {
1881 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1882 status = -EINVAL;
1883 goto out;
1884 }
1885
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301887 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888
1889 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1890 NULL);
1891 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001892 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001893 goto out;
1894 }
1895
1896 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001897 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001898 goto out;
1899 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301900 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1901 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001902
1903 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1904 ht_enabled =
1905 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1906 else
1907 ht_enabled = 0;
1908
1909 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1910 ht40_enabled =
1911 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1912 else
1913 ht40_enabled = 0;
1914
1915 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1916 vht_enabled =
1917 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1918 else
1919 vht_enabled = 0;
1920
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301921 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1922 vht_enabled = 0;
1923 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1924 }
1925
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001926 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1927 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1928 } else {
1929 if (ht_enabled && ht40_enabled)
1930 ch_width = 40;
1931 else
1932 ch_width = 20;
1933 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301934
1935 /* this may be possible, when sap_force_11n_for_11ac is set */
1936 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1937 if (ht_enabled && ht40_enabled)
1938 ch_width = 40;
1939 else
1940 ch_width = 20;
1941 }
1942
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943 if (ch_width == 80)
1944 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1945 else if (ch_width == 40)
1946 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1947 else
1948 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1949
1950 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1951 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1952 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1953 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1954 * since it contains the frequency values of the channels in
1955 * the channel list.
1956 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1957 * is present
1958 */
1959 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1960 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1961 sap_config->acs_cfg.ch_list_count = nla_len(
1962 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1963 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301964 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 sizeof(uint8_t) *
1966 sap_config->acs_cfg.ch_list_count);
1967 if (sap_config->acs_cfg.ch_list == NULL)
1968 goto out;
1969
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301970 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001971 sap_config->acs_cfg.ch_list_count);
1972 }
1973 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1974 uint32_t *freq =
1975 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1976 sap_config->acs_cfg.ch_list_count = nla_len(
1977 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1978 sizeof(uint32_t);
1979 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301980 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981 sap_config->acs_cfg.ch_list_count);
1982 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001983 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 status = -ENOMEM;
1985 goto out;
1986 }
1987
1988 /* convert frequency to channel */
1989 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1990 sap_config->acs_cfg.ch_list[i] =
1991 ieee80211_frequency_to_channel(freq[i]);
1992 }
1993 }
1994
1995 hdd_debug("get pcl for DO_ACS vendor command");
1996
1997 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001998 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301999 sap_config->acs_cfg.pcl_channels,
2000 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302001 sap_config->acs_cfg.pcl_channels_weight_list,
2002 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302003 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002004 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002006 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302007 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2008 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07002009 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010 vht_enabled = 1;
2011 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2012 sap_config->acs_cfg.ch_width =
2013 hdd_ctx->config->vhtChannelWidth;
2014 /* No VHT80 in 2.4G so perform ACS accordingly */
2015 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302016 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002017 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302018 ch_width = 40;
2019 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020 }
2021
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302022 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2023
Jeff Johnson020db452016-06-29 14:37:26 -07002024 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 -08002025 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2026 ch_width, ht_enabled, vht_enabled,
2027 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2028
Kapil Gupta8878ad92017-02-13 11:56:04 +05302029 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2030 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2031
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002032 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07002033 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002034 sap_config->acs_cfg.ch_list_count);
2035 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07002036 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 }
2038 sap_config->acs_cfg.acs_mode = true;
2039 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002040 /* ***Note*** Completion variable usage is not allowed
2041 * here since ACS scan operation may take max 2.2 sec
2042 * for 5G band:
2043 * 9 Active channel X 40 ms active scan time +
2044 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2046 * for this long. So we split up the scanning part.
2047 */
2048 set_bit(ACS_PENDING, &adapter->event_flags);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302049 hdd_notice("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002050 status = 0;
2051 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302052 /* Check if vendor specific acs is enabled */
2053 if (hdd_ctx->config->vendor_acs_support) {
2054 sap_config->acs_cfg.hw_mode = hw_mode;
2055 hdd_create_acs_timer(adapter);
2056 hdd_update_acs_timer_reason(adapter,
2057 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2058 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2059 wlan_sap_set_vendor_acs(
2060 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2061 true);
2062 else
2063 wlan_sap_set_vendor_acs(
2064 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2065 false);
2066
2067 } else
2068 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002069 }
2070
2071out:
2072 if (0 == status) {
2073 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2074 NLMSG_HDRLEN);
2075 if (temp_skbuff != NULL)
2076 return cfg80211_vendor_cmd_reply(temp_skbuff);
2077 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002078 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2080
2081 return status;
2082}
2083
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002084/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002085 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2086 * @wiphy: Linux wiphy struct pointer
2087 * @wdev: Linux wireless device struct pointer
2088 * @data: ACS information from hostapd
2089 * @data_len: ACS information len
2090 *
2091 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2092 * and starts ACS procedure.
2093 *
2094 * Return: ACS procedure start status
2095 */
2096
2097static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2098 struct wireless_dev *wdev,
2099 const void *data, int data_len)
2100{
2101 int ret;
2102
2103 cds_ssr_protect(__func__);
2104 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2105 cds_ssr_unprotect(__func__);
2106
2107 return ret;
2108}
2109
2110/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002111 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2112 * @adapter: Pointer to adapter struct
2113 *
2114 * This function handle cleanup of what was done in DO_ACS, including free
2115 * memory.
2116 *
2117 * Return: void
2118 */
2119
2120void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2121{
2122 if (adapter == NULL)
2123 return;
2124 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2125 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2126 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2127 }
2128}
2129
2130/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002131 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2132 * @work: Linux workqueue struct pointer for ACS work
2133 *
2134 * This function starts the ACS procedure which was marked pending when an ACS
2135 * procedure was in progress for a concurrent SAP interface.
2136 *
2137 * Return: None
2138 */
2139
2140static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2141{
2142 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2143 acs_pending_work.work);
2144 wlan_hdd_cfg80211_start_acs(adapter);
2145}
2146
2147/**
2148 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2149 * @adapter: Pointer to SAP adapter struct
2150 * @pri_channel: SAP ACS procedure selected Primary channel
2151 * @sec_channel: SAP ACS procedure selected secondary channel
2152 *
2153 * This is a callback function from SAP module on ACS procedure is completed.
2154 * This function send the ACS selected channel information to hostapd
2155 *
2156 * Return: None
2157 */
2158
2159void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2160{
2161 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2162 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2163 struct sk_buff *vendor_event;
2164 int ret_val;
2165 hdd_adapter_t *con_sap_adapter;
2166 uint16_t ch_width;
2167
2168 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002169 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002170 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2171 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2172 GFP_KERNEL);
2173
2174 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002175 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176 return;
2177 }
2178
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002179 ret_val = nla_put_u8(vendor_event,
2180 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2181 sap_cfg->acs_cfg.pri_ch);
2182 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002183 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184 kfree_skb(vendor_event);
2185 return;
2186 }
2187
2188 ret_val = nla_put_u8(vendor_event,
2189 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2190 sap_cfg->acs_cfg.ht_sec_ch);
2191 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002192 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002193 kfree_skb(vendor_event);
2194 return;
2195 }
2196
2197 ret_val = nla_put_u8(vendor_event,
2198 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2199 sap_cfg->acs_cfg.vht_seg0_center_ch);
2200 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002201 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002202 kfree_skb(vendor_event);
2203 return;
2204 }
2205
2206 ret_val = nla_put_u8(vendor_event,
2207 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2208 sap_cfg->acs_cfg.vht_seg1_center_ch);
2209 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002210 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002211 kfree_skb(vendor_event);
2212 return;
2213 }
2214
2215 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2216 ch_width = 80;
2217 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2218 ch_width = 40;
2219 else
2220 ch_width = 20;
2221
2222 ret_val = nla_put_u16(vendor_event,
2223 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2224 ch_width);
2225 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002226 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002227 kfree_skb(vendor_event);
2228 return;
2229 }
2230 if (sap_cfg->acs_cfg.pri_ch > 14)
2231 ret_val = nla_put_u8(vendor_event,
2232 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2233 QCA_ACS_MODE_IEEE80211A);
2234 else
2235 ret_val = nla_put_u8(vendor_event,
2236 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2237 QCA_ACS_MODE_IEEE80211G);
2238
2239 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002240 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002241 kfree_skb(vendor_event);
2242 return;
2243 }
2244
Jeff Johnson46b40792016-06-29 14:03:14 -07002245 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 -08002246 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2247 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2248 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2249
2250 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2251 /* ***Note*** As already mentioned Completion variable usage is not
2252 * allowed here since ACS scan operation may take max 2.2 sec.
2253 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2254 * operation.
2255 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2256 * when Primary AP ACS is complete and secondary AP ACS is started here
2257 * immediately, Primary AP start_bss may come inbetween ACS operation
2258 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2259 * delay. This path and below constraint will be removed on sessionizing
2260 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2261 * As per design constraint user space control application must take
2262 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2263 * this code path. Sec AP hostapd should be started after Primary AP
2264 * start beaconing which can be confirmed by getchannel iwpriv command
2265 */
2266
2267 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2268 if (con_sap_adapter &&
2269 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002270 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2271 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002272 /* Lets give 500ms for OBSS + START_BSS to complete */
2273 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2274 msecs_to_jiffies(500));
2275 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2276 }
2277
2278 return;
2279}
2280
2281static int
2282__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2283 struct wireless_dev *wdev,
2284 const void *data,
2285 int data_len)
2286{
2287 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2288 struct sk_buff *skb = NULL;
2289 uint32_t fset = 0;
2290 int ret;
2291
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002292 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302293
Anurag Chouhan6d760662016-02-20 16:05:43 +05302294 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002295 hdd_err("Command not allowed in FTM mode");
2296 return -EPERM;
2297 }
2298
2299 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302300 if (ret)
2301 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302
2303 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002304 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002305 fset |= WIFI_FEATURE_INFRA;
2306 }
2307 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002308 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002309 fset |= WIFI_FEATURE_INFRA_5G;
2310 }
2311#ifdef WLAN_FEATURE_P2P
2312 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2313 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002314 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002315 fset |= WIFI_FEATURE_P2P;
2316 }
2317#endif
2318 fset |= WIFI_FEATURE_SOFT_AP;
2319
2320 /* HOTSPOT is a supplicant feature, enable it by default */
2321 fset |= WIFI_FEATURE_HOTSPOT;
2322
2323#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302324 if (pHddCtx->config->extscan_enabled &&
2325 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002326 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002327 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2328 }
2329#endif
2330 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07002331 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002332 fset |= WIFI_FEATURE_NAN;
2333 }
2334 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002335 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002336 fset |= WIFI_FEATURE_D2D_RTT;
2337 fset |= WIFI_FEATURE_D2AP_RTT;
2338 }
2339#ifdef FEATURE_WLAN_SCAN_PNO
2340 if (pHddCtx->config->configPNOScanSupport &&
2341 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002342 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343 fset |= WIFI_FEATURE_PNO;
2344 }
2345#endif
2346 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2347#ifdef FEATURE_WLAN_TDLS
2348 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2349 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002350 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 fset |= WIFI_FEATURE_TDLS;
2352 }
2353 if (sme_is_feature_supported_by_fw(TDLS) &&
2354 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2355 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002356 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002357 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2358 }
2359#endif
2360#ifdef WLAN_AP_STA_CONCURRENCY
2361 fset |= WIFI_FEATURE_AP_STA;
2362#endif
2363 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002364 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002365
2366 if (hdd_link_layer_stats_supported())
2367 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2368
2369 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2370 NLMSG_HDRLEN);
2371 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002372 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002373 return -EINVAL;
2374 }
Jeff Johnson020db452016-06-29 14:37:26 -07002375 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002377 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 goto nla_put_failure;
2379 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302380 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302381 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382nla_put_failure:
2383 kfree_skb(skb);
2384 return -EINVAL;
2385}
2386
2387/**
2388 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2389 * @wiphy: pointer to wireless wiphy structure.
2390 * @wdev: pointer to wireless_dev structure.
2391 * @data: Pointer to the data to be passed via vendor interface
2392 * @data_len:Length of the data to be passed
2393 *
2394 * Return: Return the Success or Failure code.
2395 */
2396static int
2397wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2398 struct wireless_dev *wdev,
2399 const void *data, int data_len)
2400{
2401 int ret = 0;
2402
2403 cds_ssr_protect(__func__);
2404 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2405 data, data_len);
2406 cds_ssr_unprotect(__func__);
2407
2408 return ret;
2409}
2410
2411/**
2412 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2413 * @wiphy: pointer to wireless wiphy structure.
2414 * @wdev: pointer to wireless_dev structure.
2415 * @data: Pointer to the data to be passed via vendor interface
2416 * @data_len:Length of the data to be passed
2417 *
2418 * Set the MAC address that is to be used for scanning.
2419 *
2420 * Return: Return the Success or Failure code.
2421 */
2422static int
2423__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2424 struct wireless_dev *wdev,
2425 const void *data,
2426 int data_len)
2427{
2428 tpSirScanMacOui pReqMsg = NULL;
2429 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2430 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302431 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002432 int ret;
2433
Jeff Johnson1f61b612016-02-12 16:28:33 -08002434 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435
Anurag Chouhan6d760662016-02-20 16:05:43 +05302436 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 hdd_err("Command not allowed in FTM mode");
2438 return -EPERM;
2439 }
2440
2441 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302442 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002444
2445 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002446 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002447 return -ENOTSUPP;
2448 }
2449
2450 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2451 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002452 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453 return -EINVAL;
2454 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302455 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002456 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002457 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458 return -ENOMEM;
2459 }
2460 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002461 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002462 goto fail;
2463 }
2464 nla_memcpy(&pReqMsg->oui[0],
2465 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2466 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002467 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002468 pReqMsg->oui[1], pReqMsg->oui[2]);
2469 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302470 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002471 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 goto fail;
2473 }
2474 return 0;
2475fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302476 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002477 return -EINVAL;
2478}
2479
2480/**
2481 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2482 * @wiphy: pointer to wireless wiphy structure.
2483 * @wdev: pointer to wireless_dev structure.
2484 * @data: Pointer to the data to be passed via vendor interface
2485 * @data_len:Length of the data to be passed
2486 *
2487 * Set the MAC address that is to be used for scanning. This is an
2488 * SSR-protecting wrapper function.
2489 *
2490 * Return: Return the Success or Failure code.
2491 */
2492static int
2493wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2494 struct wireless_dev *wdev,
2495 const void *data,
2496 int data_len)
2497{
2498 int ret;
2499
2500 cds_ssr_protect(__func__);
2501 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2502 data, data_len);
2503 cds_ssr_unprotect(__func__);
2504
2505 return ret;
2506}
2507
2508/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302509 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2510 * @wiphy: pointer phy adapter
2511 * @wdev: pointer to wireless device structure
2512 * @data: pointer to data buffer
2513 * @data_len: length of data
2514 *
2515 * This routine will give concurrency matrix
2516 *
2517 * Return: int status code
2518 */
2519static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2520 struct wireless_dev *wdev,
2521 const void *data,
2522 int data_len)
2523{
2524 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2525 uint8_t i, feature_sets, max_feature_sets;
2526 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2527 struct sk_buff *reply_skb;
2528 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2529 int ret;
2530
2531 ENTER_DEV(wdev->netdev);
2532
2533 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2534 hdd_err("Command not allowed in FTM mode");
2535 return -EPERM;
2536 }
2537
2538 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302539 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302540 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302541
2542 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2543 data, data_len, NULL)) {
2544 hdd_err("Invalid ATTR");
2545 return -EINVAL;
2546 }
2547
2548 /* Parse and fetch max feature set */
2549 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2550 hdd_err("Attr max feature set size failed");
2551 return -EINVAL;
2552 }
2553 max_feature_sets = nla_get_u32(tb[
2554 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2555 hdd_info("Max feature set size: %d", max_feature_sets);
2556
2557 /* Fill feature combination matrix */
2558 feature_sets = 0;
2559 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002560 WIFI_FEATURE_P2P;
2561 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2562 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302563 /* Add more feature combinations here */
2564
2565 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002566 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302567 hdd_info("Feature set matrix");
2568 for (i = 0; i < feature_sets; i++)
2569 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2570
2571 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2572 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2573 if (!reply_skb) {
2574 hdd_err("Feature set matrix: buffer alloc fail");
2575 return -ENOMEM;
2576 }
2577
2578 if (nla_put_u32(reply_skb,
2579 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2580 feature_sets) ||
2581 nla_put(reply_skb,
2582 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2583 sizeof(u32) * feature_sets,
2584 feature_set_matrix)) {
2585 hdd_err("nla put fail");
2586 kfree_skb(reply_skb);
2587 return -EINVAL;
2588 }
2589 return cfg80211_vendor_cmd_reply(reply_skb);
2590}
2591
2592/**
2593 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2594 * @wiphy: pointer to wireless wiphy structure.
2595 * @wdev: pointer to wireless_dev structure.
2596 * @data: Pointer to the data to be passed via vendor interface
2597 * @data_len:Length of the data to be passed
2598 *
2599 * Retrieves the concurrency feature set matrix
2600 *
2601 * Return: 0 on success, negative errno on failure
2602 */
2603static int
2604wlan_hdd_cfg80211_get_concurrency_matrix(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_get_concurrency_matrix(wiphy, wdev,
2613 data, data_len);
2614 cds_ssr_unprotect(__func__);
2615
2616 return ret;
2617}
2618
2619/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2621 * @feature_flags: pointer to the byte array of features.
2622 * @feature: Feature to be turned ON in the byte array.
2623 *
2624 * Return: None
2625 *
2626 * This is called to turn ON or SET the feature flag for the requested feature.
2627 **/
2628#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002629static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2630 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002631{
2632 uint32_t index;
2633 uint8_t bit_mask;
2634
2635 index = feature / NUM_BITS_IN_BYTE;
2636 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2637 feature_flags[index] |= bit_mask;
2638}
2639
2640/**
2641 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2642 * @wiphy: pointer to wireless wiphy structure.
2643 * @wdev: pointer to wireless_dev structure.
2644 * @data: Pointer to the data to be passed via vendor interface
2645 * @data_len:Length of the data to be passed
2646 *
2647 * This is called when wlan driver needs to send supported feature set to
2648 * supplicant upon a request/query from the supplicant.
2649 *
2650 * Return: Return the Success or Failure code.
2651 **/
2652#define MAX_CONCURRENT_CHAN_ON_24G 2
2653#define MAX_CONCURRENT_CHAN_ON_5G 2
2654static int
2655__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2656 struct wireless_dev *wdev,
2657 const void *data, int data_len)
2658{
2659 struct sk_buff *skb = NULL;
2660 uint32_t dbs_capability = 0;
2661 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302662 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002663 int ret_val;
2664
2665 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2666 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2667
Jeff Johnson1f61b612016-02-12 16:28:33 -08002668 ENTER_DEV(wdev->netdev);
2669
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002670 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2671 if (ret_val)
2672 return ret_val;
2673
Anurag Chouhan6d760662016-02-20 16:05:43 +05302674 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002675 hdd_err("Command not allowed in FTM mode");
2676 return -EPERM;
2677 }
2678
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002679 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002680 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002681 wlan_hdd_cfg80211_set_feature(feature_flags,
2682 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2683 }
2684
2685 wlan_hdd_cfg80211_set_feature(feature_flags,
2686 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2687 if (wma_is_scan_simultaneous_capable())
2688 wlan_hdd_cfg80211_set_feature(feature_flags,
2689 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002690
2691 if (wma_is_p2p_lo_capable())
2692 wlan_hdd_cfg80211_set_feature(feature_flags,
2693 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2694
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002695 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2696 NLMSG_HDRLEN);
2697
2698 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002699 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002700 return -ENOMEM;
2701 }
2702
2703 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2704 sizeof(feature_flags), feature_flags))
2705 goto nla_put_failure;
2706
2707 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302708 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002709 if (one_by_one_dbs)
2710 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2711
2712 if (two_by_two_dbs)
2713 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2714
2715 if (!one_by_one_dbs && !two_by_two_dbs)
2716 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2717 } else {
2718 hdd_err("wma_get_dbs_hw_mode failed");
2719 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2720 }
2721
2722 hdd_info("dbs_capability is %d", dbs_capability);
2723
2724 if (nla_put_u32(skb,
2725 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2726 MAX_CONCURRENT_CHAN_ON_24G))
2727 goto nla_put_failure;
2728
2729 if (nla_put_u32(skb,
2730 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2731 MAX_CONCURRENT_CHAN_ON_5G))
2732 goto nla_put_failure;
2733
2734 return cfg80211_vendor_cmd_reply(skb);
2735
2736nla_put_failure:
2737 kfree_skb(skb);
2738 return -EINVAL;
2739}
2740
2741/**
2742 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2743 * @wiphy: pointer to wireless wiphy structure.
2744 * @wdev: pointer to wireless_dev structure.
2745 * @data: Pointer to the data to be passed via vendor interface
2746 * @data_len:Length of the data to be passed
2747 *
2748 * This is called when wlan driver needs to send supported feature set to
2749 * supplicant upon a request/query from the supplicant.
2750 *
2751 * Return: Return the Success or Failure code.
2752 */
2753static int
2754wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2755 struct wireless_dev *wdev,
2756 const void *data, int data_len)
2757{
2758 int ret;
2759
2760 cds_ssr_protect(__func__);
2761 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2762 data, data_len);
2763 cds_ssr_unprotect(__func__);
2764
2765 return ret;
2766}
2767
2768
2769/**
2770 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2771 * @wiphy: The wiphy structure
2772 * @wdev: The wireless device
2773 * @data: Data passed by framework
2774 * @data_len: Parameters to be configured passed as data
2775 *
2776 * The roaming related parameters are configured by the framework
2777 * using this interface.
2778 *
2779 * Return: Return either success or failure code.
2780 */
2781static int
2782__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2783 struct wireless_dev *wdev, const void *data, int data_len)
2784{
2785 struct net_device *dev = wdev->netdev;
2786 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2787 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2788 uint8_t session_id;
2789 struct roam_ext_params roam_params;
2790 uint32_t cmd_type, req_id;
2791 struct nlattr *curr_attr;
2792 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2793 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2794 int rem, i;
2795 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002796 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002797 int ret;
2798
Jeff Johnson1f61b612016-02-12 16:28:33 -08002799 ENTER_DEV(dev);
2800
Anurag Chouhan6d760662016-02-20 16:05:43 +05302801 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002802 hdd_err("Command not allowed in FTM mode");
2803 return -EPERM;
2804 }
2805
2806 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302807 if (ret)
2808 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002809
2810 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2811 data, data_len,
2812 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002813 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002814 return -EINVAL;
2815 }
2816 /* Parse and fetch Command Type*/
2817 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002818 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002819 goto fail;
2820 }
2821 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302822 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2824 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002825 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002826 goto fail;
2827 }
2828 req_id = nla_get_u32(
2829 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002830 hdd_debug("Req Id (%d)", req_id);
2831 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002832 switch (cmd_type) {
2833 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2834 i = 0;
2835 nla_for_each_nested(curr_attr,
2836 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2837 rem) {
2838 if (nla_parse(tb2,
2839 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2840 nla_data(curr_attr), nla_len(curr_attr),
2841 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002842 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002843 goto fail;
2844 }
2845 /* Parse and Fetch allowed SSID list*/
2846 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002847 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002848 goto fail;
2849 }
2850 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2851 /*
2852 * Upper Layers include a null termination character.
2853 * Check for the actual permissible length of SSID and
2854 * also ensure not to copy the NULL termination
2855 * character to the driver buffer.
2856 */
2857 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2858 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2859 nla_memcpy(
2860 roam_params.ssid_allowed_list[i].ssId,
2861 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2862 buf_len - 1);
2863 roam_params.ssid_allowed_list[i].length =
2864 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002865 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002866 roam_params.ssid_allowed_list[i].length,
2867 roam_params.ssid_allowed_list[i].ssId,
2868 roam_params.ssid_allowed_list[i].length);
2869 i++;
2870 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002871 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002872 }
2873 }
2874 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002875 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002876 roam_params.num_ssid_allowed_list);
2877 sme_update_roam_params(pHddCtx->hHal, session_id,
2878 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2879 break;
2880 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2881 /* Parse and fetch 5G Boost Threshold */
2882 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002883 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002884 goto fail;
2885 }
2886 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2887 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002888 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002889 roam_params.raise_rssi_thresh_5g);
2890 /* Parse and fetch 5G Penalty Threshold */
2891 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002892 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002893 goto fail;
2894 }
2895 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2896 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002897 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002898 roam_params.drop_rssi_thresh_5g);
2899 /* Parse and fetch 5G Boost Factor */
2900 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002901 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002902 goto fail;
2903 }
2904 roam_params.raise_factor_5g = nla_get_u32(
2905 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002906 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 roam_params.raise_factor_5g);
2908 /* Parse and fetch 5G Penalty factor */
2909 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002910 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002911 goto fail;
2912 }
2913 roam_params.drop_factor_5g = nla_get_u32(
2914 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002915 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002916 roam_params.drop_factor_5g);
2917 /* Parse and fetch 5G Max Boost */
2918 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002919 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002920 goto fail;
2921 }
2922 roam_params.max_raise_rssi_5g = nla_get_u32(
2923 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002924 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002925 roam_params.max_raise_rssi_5g);
2926 /* Parse and fetch Rssi Diff */
2927 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002928 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002929 goto fail;
2930 }
2931 roam_params.rssi_diff = nla_get_s32(
2932 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002933 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002934 roam_params.rssi_diff);
2935 /* Parse and fetch Alert Rssi Threshold */
2936 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002937 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002938 goto fail;
2939 }
2940 roam_params.alert_rssi_threshold = nla_get_u32(
2941 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002942 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002943 roam_params.alert_rssi_threshold);
2944 sme_update_roam_params(pHddCtx->hHal, session_id,
2945 roam_params,
2946 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2947 break;
2948 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2949 /* Parse and fetch Activate Good Rssi Roam */
2950 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002951 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952 goto fail;
2953 }
2954 roam_params.good_rssi_roam = nla_get_s32(
2955 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002956 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 roam_params.good_rssi_roam);
2958 sme_update_roam_params(pHddCtx->hHal, session_id,
2959 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2960 break;
2961 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2962 /* Parse and fetch number of preferred BSSID */
2963 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002964 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002965 goto fail;
2966 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002967 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002968 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002969 if (count > MAX_BSSID_FAVORED) {
2970 hdd_err("Preferred BSSID count %u exceeds max %u",
2971 count, MAX_BSSID_FAVORED);
2972 goto fail;
2973 }
2974 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002975 i = 0;
2976 nla_for_each_nested(curr_attr,
2977 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2978 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002979
2980 if (i == count) {
2981 hdd_warn("Ignoring excess Preferred BSSID");
2982 break;
2983 }
2984
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985 if (nla_parse(tb2,
2986 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2987 nla_data(curr_attr), nla_len(curr_attr),
2988 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002989 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002990 goto fail;
2991 }
2992 /* Parse and fetch MAC address */
2993 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002994 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995 goto fail;
2996 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002997 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002998 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302999 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003000 hdd_debug(MAC_ADDRESS_STR,
3001 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003002 /* Parse and fetch preference factor*/
3003 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003004 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003005 goto fail;
3006 }
3007 roam_params.bssid_favored_factor[i] = nla_get_u32(
3008 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003009 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003010 roam_params.bssid_favored_factor[i]);
3011 i++;
3012 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003013 if (i < count)
3014 hdd_warn("Num Preferred BSSID %u less than expected %u",
3015 i, count);
3016 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003017 sme_update_roam_params(pHddCtx->hHal, session_id,
3018 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3019 break;
3020 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3021 /* Parse and fetch number of blacklist BSSID */
3022 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003023 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003024 goto fail;
3025 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003026 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003028 if (count > MAX_BSSID_AVOID_LIST) {
3029 hdd_err("Blacklist BSSID count %u exceeds max %u",
3030 count, MAX_BSSID_AVOID_LIST);
3031 goto fail;
3032 }
3033 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003034 i = 0;
3035 nla_for_each_nested(curr_attr,
3036 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3037 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003038
3039 if (i == count) {
3040 hdd_warn("Ignoring excess Blacklist BSSID");
3041 break;
3042 }
3043
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003044 if (nla_parse(tb2,
3045 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3046 nla_data(curr_attr), nla_len(curr_attr),
3047 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003048 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003049 goto fail;
3050 }
3051 /* Parse and fetch MAC address */
3052 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003053 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003054 goto fail;
3055 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003056 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003057 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303058 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003059 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003060 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003061 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003062 i++;
3063 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003064 if (i < count)
3065 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3066 i, count);
3067 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003068 sme_update_roam_params(pHddCtx->hHal, session_id,
3069 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3070 break;
3071 }
3072 return 0;
3073fail:
3074 return -EINVAL;
3075}
3076
3077/**
3078 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3079 * @wiphy: pointer to wireless wiphy structure.
3080 * @wdev: pointer to wireless_dev structure.
3081 * @data: Pointer to the data to be passed via vendor interface
3082 * @data_len:Length of the data to be passed
3083 *
3084 * Return: Return the Success or Failure code.
3085 */
3086static int
3087wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3088 struct wireless_dev *wdev,
3089 const void *data,
3090 int data_len)
3091{
3092 int ret;
3093
3094 cds_ssr_protect(__func__);
3095 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3096 data, data_len);
3097 cds_ssr_unprotect(__func__);
3098
3099 return ret;
3100}
3101
3102static const struct nla_policy
3103wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3104 +1] = {
3105 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3106};
3107
3108/**
3109 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3110 * @hdd_ctx: HDD context
3111 * @device_mode: device mode
3112 * Return: bool
3113 */
3114static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003115 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003116{
3117 hdd_adapter_t *adapter;
3118 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3119 hdd_ap_ctx_t *ap_ctx;
3120 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303121 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003122
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303123 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003124 &adapter_node);
3125
3126 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303127 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003128 adapter = adapter_node->pAdapter;
3129
3130 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003131 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003132 ap_ctx =
3133 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3134
3135 /*
3136 * if there is SAP already running on DFS channel,
3137 * do not disable scan on dfs channels. Note that
3138 * with SAP on DFS, there cannot be conurrency on
3139 * single radio. But then we can have multiple
3140 * radios !!
3141 */
3142 if (CHANNEL_STATE_DFS ==
3143 cds_get_channel_state(
3144 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003145 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146 return true;
3147 }
3148 }
3149
3150 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003151 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003152 sta_ctx =
3153 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3154
3155 /*
3156 * if STA is already connected on DFS channel,
3157 * do not disable scan on dfs channels
3158 */
3159 if (hdd_conn_is_connected(sta_ctx) &&
3160 (CHANNEL_STATE_DFS ==
3161 cds_get_channel_state(
3162 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003163 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164 return true;
3165 }
3166 }
3167
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303168 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003169 adapter_node,
3170 &next);
3171 adapter_node = next;
3172 }
3173
3174 return false;
3175}
3176
3177/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003178 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3179 * @hdd_ctx: HDD context within host driver
3180 * @adapter: Adapter pointer
3181 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3182 *
3183 * Loops through devices to see who is operating on DFS channels
3184 * and then disables/enables DFS channels by calling SME API.
3185 * Fails the disable request if any device is active on a DFS channel.
3186 *
3187 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003188 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003189
3190int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3191 hdd_adapter_t *adapter,
3192 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003193{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303195 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003196 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197
3198 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3199 if (no_dfs_flag) {
3200 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003201 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003202
3203 if (true == status)
3204 return -EOPNOTSUPP;
3205
3206 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003207 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003208
3209 if (true == status)
3210 return -EOPNOTSUPP;
3211 }
3212
3213 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3214
3215 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3216
3217 /*
3218 * call the SME API to tunnel down the new channel list
3219 * to the firmware
3220 */
3221 status = sme_handle_dfs_chan_scan(
3222 h_hal, hdd_ctx->config->enableDFSChnlScan);
3223
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303224 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 ret_val = 0;
3226
3227 /*
3228 * Clear the SME scan cache also. Note that the
3229 * clearing of scan results is independent of session;
3230 * so no need to iterate over
3231 * all sessions
3232 */
3233 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303234 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 ret_val = -EPERM;
3236 }
3237
3238 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003239 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003240 ret_val = 0;
3241 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003242 return ret_val;
3243}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003244
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003245/**
3246 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3247 * @wiphy: corestack handler
3248 * @wdev: wireless device
3249 * @data: data
3250 * @data_len: data length
3251 * Return: success(0) or reason code for failure
3252 */
3253static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3254 struct wireless_dev *wdev,
3255 const void *data,
3256 int data_len)
3257{
3258 struct net_device *dev = wdev->netdev;
3259 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3260 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3261 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3262 int ret_val;
3263 uint32_t no_dfs_flag = 0;
3264
Jeff Johnson1f61b612016-02-12 16:28:33 -08003265 ENTER_DEV(dev);
3266
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003267 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303268 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003269 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003270
3271 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3272 data, data_len,
3273 wlan_hdd_set_no_dfs_flag_config_policy)) {
3274 hdd_err("invalid attr");
3275 return -EINVAL;
3276 }
3277
3278 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3279 hdd_err("attr dfs flag failed");
3280 return -EINVAL;
3281 }
3282
3283 no_dfs_flag = nla_get_u32(
3284 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3285
Jeff Johnson020db452016-06-29 14:37:26 -07003286 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003287
3288 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003289 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003290 return -EINVAL;
3291 }
3292
3293 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3294 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003295 return ret_val;
3296}
3297
3298/**
3299 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3300 *
3301 * @wiphy: wiphy device pointer
3302 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003303 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003304 * @data_len: Buffer length
3305 *
3306 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3307 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3308 *
3309 * Return: EOK or other error codes.
3310 */
3311
3312static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3313 struct wireless_dev *wdev,
3314 const void *data,
3315 int data_len)
3316{
3317 int ret;
3318
3319 cds_ssr_protect(__func__);
3320 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3321 data, data_len);
3322 cds_ssr_unprotect(__func__);
3323
3324 return ret;
3325}
3326
Manikandan Mohan80dea792016-04-28 16:36:48 -07003327static const struct nla_policy
3328wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3329 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3330};
3331
3332/**
3333 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3334 * @wiphy: wiphy device pointer
3335 * @wdev: wireless device pointer
3336 * @data: Vendor command data buffer
3337 * @data_len: Buffer length
3338 *
3339 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3340 * setup WISA Mode features.
3341 *
3342 * Return: Success(0) or reason code for failure
3343 */
3344static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3345 struct wireless_dev *wdev, const void *data, int data_len)
3346{
3347 struct net_device *dev = wdev->netdev;
3348 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3349 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3350 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3351 struct sir_wisa_params wisa;
3352 int ret_val;
3353 QDF_STATUS status;
3354 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003355 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3356 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003357
3358 ENTER_DEV(dev);
3359 ret_val = wlan_hdd_validate_context(hdd_ctx);
3360 if (ret_val)
3361 goto err;
3362
3363 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3364 hdd_err("Command not allowed in FTM mode");
3365 return -EPERM;
3366 }
3367
3368 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3369 wlan_hdd_wisa_cmd_policy)) {
3370 hdd_err("Invalid WISA cmd attributes");
3371 ret_val = -EINVAL;
3372 goto err;
3373 }
3374 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3375 hdd_err("Invalid WISA mode");
3376 ret_val = -EINVAL;
3377 goto err;
3378 }
3379
3380 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
3381 hdd_info("WISA Mode: %d", wisa_mode);
3382 wisa.mode = wisa_mode;
3383 wisa.vdev_id = adapter->sessionId;
3384 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003385 if (!QDF_IS_STATUS_SUCCESS(status)) {
3386 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003387 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003388 }
3389 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003390 cdp_set_wisa_mode(soc,
3391 cdp_get_vdev_from_vdev_id(soc, pdev,
3392 adapter->sessionId),
3393 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003394err:
3395 EXIT();
3396 return ret_val;
3397}
3398
3399/**
3400 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3401 * @wiphy: corestack handler
3402 * @wdev: wireless device
3403 * @data: data
3404 * @data_len: data length
3405 *
3406 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3407 * setup WISA mode features.
3408 *
3409 * Return: Success(0) or reason code for failure
3410 */
3411static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3412 struct wireless_dev *wdev,
3413 const void *data,
3414 int data_len)
3415{
3416 int ret;
3417
3418 cds_ssr_protect(__func__);
3419 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3420 cds_ssr_unprotect(__func__);
3421
3422 return ret;
3423}
3424
Anurag Chouhan96919482016-07-13 16:36:57 +05303425/*
3426 * define short names for the global vendor params
3427 * used by __wlan_hdd_cfg80211_get_station_cmd()
3428 */
3429#define STATION_INVALID \
3430 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3431#define STATION_INFO \
3432 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3433#define STATION_ASSOC_FAIL_REASON \
3434 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3435#define STATION_MAX \
3436 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3437
3438static const struct nla_policy
3439hdd_get_station_policy[STATION_MAX + 1] = {
3440 [STATION_INFO] = {.type = NLA_FLAG},
3441 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3442};
3443
3444/**
3445 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3446 * @hdd_ctx: HDD context within host driver
3447 * @wdev: wireless device
3448 *
3449 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3450 * Validate cmd attributes and send the station info to upper layers.
3451 *
3452 * Return: Success(0) or reason code for failure
3453 */
3454static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3455 hdd_adapter_t *adapter)
3456{
3457 struct sk_buff *skb = NULL;
3458 uint32_t nl_buf_len;
3459 hdd_station_ctx_t *hdd_sta_ctx;
3460
3461 nl_buf_len = NLMSG_HDRLEN;
3462 nl_buf_len += sizeof(uint32_t);
3463 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3464
3465 if (!skb) {
3466 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3467 return -ENOMEM;
3468 }
3469
3470 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3471
3472 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3473 hdd_sta_ctx->conn_info.assoc_status_code)) {
3474 hdd_err("put fail");
3475 goto fail;
3476 }
3477 return cfg80211_vendor_cmd_reply(skb);
3478fail:
3479 if (skb)
3480 kfree_skb(skb);
3481 return -EINVAL;
3482}
3483
3484/**
3485 * hdd_map_auth_type() - transform auth type specific to
3486 * vendor command
3487 * @auth_type: csr auth type
3488 *
3489 * Return: Success(0) or reason code for failure
3490 */
3491static int hdd_convert_auth_type(uint32_t auth_type)
3492{
3493 uint32_t ret_val;
3494
3495 switch (auth_type) {
3496 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3497 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3498 break;
3499 case eCSR_AUTH_TYPE_SHARED_KEY:
3500 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3501 break;
3502 case eCSR_AUTH_TYPE_WPA:
3503 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3504 break;
3505 case eCSR_AUTH_TYPE_WPA_PSK:
3506 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3507 break;
3508 case eCSR_AUTH_TYPE_AUTOSWITCH:
3509 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3510 break;
3511 case eCSR_AUTH_TYPE_WPA_NONE:
3512 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3513 break;
3514 case eCSR_AUTH_TYPE_RSN:
3515 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3516 break;
3517 case eCSR_AUTH_TYPE_RSN_PSK:
3518 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3519 break;
3520 case eCSR_AUTH_TYPE_FT_RSN:
3521 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3522 break;
3523 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3524 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3525 break;
3526 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3527 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3528 break;
3529 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3530 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3531 break;
3532 case eCSR_AUTH_TYPE_CCKM_WPA:
3533 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3534 break;
3535 case eCSR_AUTH_TYPE_CCKM_RSN:
3536 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3537 break;
3538 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3539 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3540 break;
3541 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3542 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3543 break;
3544 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3545 case eCSR_AUTH_TYPE_FAILED:
3546 case eCSR_AUTH_TYPE_NONE:
3547 default:
3548 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3549 break;
3550 }
3551 return ret_val;
3552}
3553
3554/**
3555 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3556 * vendor command
3557 * @dot11mode: dot11mode
3558 *
3559 * Return: Success(0) or reason code for failure
3560 */
3561static int hdd_convert_dot11mode(uint32_t dot11mode)
3562{
3563 uint32_t ret_val;
3564
3565 switch (dot11mode) {
3566 case eCSR_CFG_DOT11_MODE_11A:
3567 ret_val = QCA_WLAN_802_11_MODE_11A;
3568 break;
3569 case eCSR_CFG_DOT11_MODE_11B:
3570 ret_val = QCA_WLAN_802_11_MODE_11B;
3571 break;
3572 case eCSR_CFG_DOT11_MODE_11G:
3573 ret_val = QCA_WLAN_802_11_MODE_11G;
3574 break;
3575 case eCSR_CFG_DOT11_MODE_11N:
3576 ret_val = QCA_WLAN_802_11_MODE_11N;
3577 break;
3578 case eCSR_CFG_DOT11_MODE_11AC:
3579 ret_val = QCA_WLAN_802_11_MODE_11AC;
3580 break;
3581 case eCSR_CFG_DOT11_MODE_AUTO:
3582 case eCSR_CFG_DOT11_MODE_ABG:
3583 default:
3584 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3585 }
3586 return ret_val;
3587}
3588
3589/**
3590 * hdd_add_tx_bitrate() - add tx bitrate attribute
3591 * @skb: pointer to sk buff
3592 * @hdd_sta_ctx: pointer to hdd station context
3593 * @idx: attribute index
3594 *
3595 * Return: Success(0) or reason code for failure
3596 */
3597static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3598 hdd_station_ctx_t *hdd_sta_ctx,
3599 int idx)
3600{
3601 struct nlattr *nla_attr;
3602 uint32_t bitrate, bitrate_compat;
3603
3604 nla_attr = nla_nest_start(skb, idx);
3605 if (!nla_attr)
3606 goto fail;
3607 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3608 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3609
3610 /* report 16-bit bitrate only if we can */
3611 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3612 if (bitrate > 0 &&
3613 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3614 hdd_err("put fail");
3615 goto fail;
3616 }
3617 if (bitrate_compat > 0 &&
3618 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3619 hdd_err("put fail");
3620 goto fail;
3621 }
3622 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3623 hdd_sta_ctx->conn_info.txrate.nss)) {
3624 hdd_err("put fail");
3625 goto fail;
3626 }
3627 nla_nest_end(skb, nla_attr);
3628 return 0;
3629fail:
3630 return -EINVAL;
3631}
3632
3633/**
3634 * hdd_add_sta_info() - add station info attribute
3635 * @skb: pointer to sk buff
3636 * @hdd_sta_ctx: pointer to hdd station context
3637 * @idx: attribute index
3638 *
3639 * Return: Success(0) or reason code for failure
3640 */
3641static int32_t hdd_add_sta_info(struct sk_buff *skb,
3642 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3643{
3644 struct nlattr *nla_attr;
3645
3646 nla_attr = nla_nest_start(skb, idx);
3647 if (!nla_attr)
3648 goto fail;
3649 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3650 (hdd_sta_ctx->conn_info.signal + 100))) {
3651 hdd_err("put fail");
3652 goto fail;
3653 }
3654 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3655 goto fail;
3656 nla_nest_end(skb, nla_attr);
3657 return 0;
3658fail:
3659 return -EINVAL;
3660}
3661
3662/**
3663 * hdd_add_survey_info() - add survey info attribute
3664 * @skb: pointer to sk buff
3665 * @hdd_sta_ctx: pointer to hdd station context
3666 * @idx: attribute index
3667 *
3668 * Return: Success(0) or reason code for failure
3669 */
3670static int32_t hdd_add_survey_info(struct sk_buff *skb,
3671 hdd_station_ctx_t *hdd_sta_ctx,
3672 int idx)
3673{
3674 struct nlattr *nla_attr;
3675
3676 nla_attr = nla_nest_start(skb, idx);
3677 if (!nla_attr)
3678 goto fail;
3679 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3680 hdd_sta_ctx->conn_info.freq) ||
3681 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3682 (hdd_sta_ctx->conn_info.noise + 100))) {
3683 hdd_err("put fail");
3684 goto fail;
3685 }
3686 nla_nest_end(skb, nla_attr);
3687 return 0;
3688fail:
3689 return -EINVAL;
3690}
3691
3692/**
3693 * hdd_add_link_standard_info() - add link info attribute
3694 * @skb: pointer to sk buff
3695 * @hdd_sta_ctx: pointer to hdd station context
3696 * @idx: attribute index
3697 *
3698 * Return: Success(0) or reason code for failure
3699 */
3700static int32_t
3701hdd_add_link_standard_info(struct sk_buff *skb,
3702 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3703{
3704 struct nlattr *nla_attr;
3705
3706 nla_attr = nla_nest_start(skb, idx);
3707 if (!nla_attr)
3708 goto fail;
3709 if (nla_put(skb,
3710 NL80211_ATTR_SSID,
3711 hdd_sta_ctx->conn_info.SSID.SSID.length,
3712 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3713 hdd_err("put fail");
3714 goto fail;
3715 }
3716 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3717 goto fail;
3718 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3719 goto fail;
3720 nla_nest_end(skb, nla_attr);
3721 return 0;
3722fail:
3723 return -EINVAL;
3724}
3725
3726/**
3727 * hdd_add_ap_standard_info() - add ap info attribute
3728 * @skb: pointer to sk buff
3729 * @hdd_sta_ctx: pointer to hdd station context
3730 * @idx: attribute index
3731 *
3732 * Return: Success(0) or reason code for failure
3733 */
3734static int32_t
3735hdd_add_ap_standard_info(struct sk_buff *skb,
3736 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3737{
3738 struct nlattr *nla_attr;
3739
3740 nla_attr = nla_nest_start(skb, idx);
3741 if (!nla_attr)
3742 goto fail;
3743 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3744 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3745 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3746 &hdd_sta_ctx->conn_info.vht_caps)) {
3747 hdd_err("put fail");
3748 goto fail;
3749 }
3750 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3751 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3752 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3753 &hdd_sta_ctx->conn_info.ht_caps)) {
3754 hdd_err("put fail");
3755 goto fail;
3756 }
3757 nla_nest_end(skb, nla_attr);
3758 return 0;
3759fail:
3760 return -EINVAL;
3761}
3762
3763/**
3764 * hdd_get_station_info() - send BSS information to supplicant
3765 * @hdd_ctx: pointer to hdd context
3766 * @adapter: pointer to adapter
3767 *
3768 * Return: 0 if success else error status
3769 */
3770static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3771 hdd_adapter_t *adapter)
3772{
3773 struct sk_buff *skb = NULL;
3774 uint8_t *tmp_hs20 = NULL;
3775 uint32_t nl_buf_len;
3776 hdd_station_ctx_t *hdd_sta_ctx;
3777
3778 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3779
3780 nl_buf_len = NLMSG_HDRLEN;
3781 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3782 sizeof(hdd_sta_ctx->conn_info.freq) +
3783 sizeof(hdd_sta_ctx->conn_info.noise) +
3784 sizeof(hdd_sta_ctx->conn_info.signal) +
3785 (sizeof(uint32_t) * 2) +
3786 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3787 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3788 sizeof(hdd_sta_ctx->conn_info.authType) +
3789 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3790 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3791 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3792 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3793 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3794 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3795 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3796 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3797 1);
3798 }
3799 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3800 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3801 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3802 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3803
3804
3805 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3806 if (!skb) {
3807 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3808 return -ENOMEM;
3809 }
3810
3811 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3812 LINK_INFO_STANDARD_NL80211_ATTR)) {
3813 hdd_err("put fail");
3814 goto fail;
3815 }
3816 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3817 AP_INFO_STANDARD_NL80211_ATTR)) {
3818 hdd_err("put fail");
3819 goto fail;
3820 }
3821 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3822 hdd_sta_ctx->conn_info.roam_count) ||
3823 nla_put_u32(skb, INFO_AKM,
3824 hdd_convert_auth_type(
3825 hdd_sta_ctx->conn_info.authType)) ||
3826 nla_put_u32(skb, WLAN802_11_MODE,
3827 hdd_convert_dot11mode(
3828 hdd_sta_ctx->conn_info.dot11Mode))) {
3829 hdd_err("put fail");
3830 goto fail;
3831 }
3832 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3833 if (nla_put(skb, HT_OPERATION,
3834 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3835 &hdd_sta_ctx->conn_info.ht_operation)) {
3836 hdd_err("put fail");
3837 goto fail;
3838 }
3839 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3840 if (nla_put(skb, VHT_OPERATION,
3841 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3842 &hdd_sta_ctx->conn_info.vht_operation)) {
3843 hdd_err("put fail");
3844 goto fail;
3845 }
3846 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3847 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3848 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3849 tmp_hs20 + 1)) {
3850 hdd_err("put fail");
3851 goto fail;
3852 }
3853
3854 return cfg80211_vendor_cmd_reply(skb);
3855fail:
3856 if (skb)
3857 kfree_skb(skb);
3858 return -EINVAL;
3859}
3860
3861/**
3862 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3863 * @wiphy: corestack handler
3864 * @wdev: wireless device
3865 * @data: data
3866 * @data_len: data length
3867 *
3868 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3869 * Validate cmd attributes and send the station info to upper layers.
3870 *
3871 * Return: Success(0) or reason code for failure
3872 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303873static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303874__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3875 struct wireless_dev *wdev,
3876 const void *data,
3877 int data_len)
3878{
3879 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3880 struct net_device *dev = wdev->netdev;
3881 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3882 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3883 int32_t status;
3884
3885 ENTER_DEV(dev);
3886 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3887 hdd_err("Command not allowed in FTM mode");
3888 status = -EPERM;
3889 goto out;
3890 }
3891
3892 status = wlan_hdd_validate_context(hdd_ctx);
3893 if (0 != status)
3894 goto out;
3895
3896
3897 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3898 data, data_len, NULL);
3899 if (status) {
3900 hdd_err("Invalid ATTR");
3901 goto out;
3902 }
3903
3904 /* Parse and fetch Command Type*/
3905 if (tb[STATION_INFO]) {
3906 status = hdd_get_station_info(hdd_ctx, adapter);
3907 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3908 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3909 } else {
3910 hdd_err("get station info cmd type failed");
3911 status = -EINVAL;
3912 goto out;
3913 }
3914 EXIT();
3915out:
3916 return status;
3917}
3918
3919/**
3920 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3921 * @wiphy: corestack handler
3922 * @wdev: wireless device
3923 * @data: data
3924 * @data_len: data length
3925 *
3926 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3927 * Validate cmd attributes and send the station info to upper layers.
3928 *
3929 * Return: Success(0) or reason code for failure
3930 */
3931static int32_t
3932hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3933 struct wireless_dev *wdev,
3934 const void *data,
3935 int data_len)
3936{
3937 int ret;
3938
3939 cds_ssr_protect(__func__);
3940 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3941 cds_ssr_unprotect(__func__);
3942
3943 return ret;
3944}
3945
3946/*
3947 * undef short names defined for get station command
3948 * used by __wlan_hdd_cfg80211_get_station_cmd()
3949 */
3950#undef STATION_INVALID
3951#undef STATION_INFO
3952#undef STATION_ASSOC_FAIL_REASON
3953#undef STATION_MAX
3954
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003955#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3956/**
3957 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3958 * @wiphy: pointer to wireless wiphy structure.
3959 * @wdev: pointer to wireless_dev structure.
3960 * @data: Pointer to the Key data
3961 * @data_len:Length of the data passed
3962 *
3963 * This is called when wlan driver needs to save the keys received via
3964 * vendor specific command.
3965 *
3966 * Return: Return the Success or Failure code.
3967 */
3968static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3969 struct wireless_dev *wdev,
3970 const void *data, int data_len)
3971{
3972 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3973 struct net_device *dev = wdev->netdev;
3974 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3975 hdd_context_t *hdd_ctx_ptr;
3976 int status;
3977
Jeff Johnson1f61b612016-02-12 16:28:33 -08003978 ENTER_DEV(dev);
3979
Anurag Chouhan6d760662016-02-20 16:05:43 +05303980 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003981 hdd_err("Command not allowed in FTM mode");
3982 return -EPERM;
3983 }
3984
3985 if ((data == NULL) || (data_len == 0) ||
3986 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003987 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003988 return -EINVAL;
3989 }
3990
3991 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3992 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003993 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003994 return -EINVAL;
3995 }
3996
3997 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303998 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003999 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004000 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4001 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004002 true,
4003 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304004 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4005 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004006 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4007 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4008 return 0;
4009}
4010
4011/**
4012 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4013 * @wiphy: pointer to wireless wiphy structure.
4014 * @wdev: pointer to wireless_dev structure.
4015 * @data: Pointer to the Key data
4016 * @data_len:Length of the data passed
4017 *
4018 * This is called when wlan driver needs to save the keys received via
4019 * vendor specific command.
4020 *
4021 * Return: Return the Success or Failure code.
4022 */
4023static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4024 struct wireless_dev *wdev,
4025 const void *data, int data_len)
4026{
4027 int ret;
4028
4029 cds_ssr_protect(__func__);
4030 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4031 cds_ssr_unprotect(__func__);
4032
4033 return ret;
4034}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004035#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036
4037static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4038 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4039 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4040 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004041 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042};
4043
4044/**
4045 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4046 * @wiphy: pointer to wireless wiphy structure.
4047 * @wdev: pointer to wireless_dev structure.
4048 * @data: Pointer to the data to be passed via vendor interface
4049 * @data_len:Length of the data to be passed
4050 *
4051 * This is called when wlan driver needs to send wifi driver related info
4052 * (driver/fw version) to the user space application upon request.
4053 *
4054 * Return: Return the Success or Failure code.
4055 */
4056static int
4057__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4058 struct wireless_dev *wdev,
4059 const void *data, int data_len)
4060{
4061 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4062 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004063 tSirVersionString driver_version;
4064 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004065 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004066 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004067 struct sk_buff *reply_skb;
4068 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004069
Jeff Johnson1f61b612016-02-12 16:28:33 -08004070 ENTER_DEV(wdev->netdev);
4071
Anurag Chouhan6d760662016-02-20 16:05:43 +05304072 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073 hdd_err("Command not allowed in FTM mode");
4074 return -EPERM;
4075 }
4076
4077 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304078 if (status)
4079 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004080
4081 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4082 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004083 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004084 return -EINVAL;
4085 }
4086
4087 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004088 hdd_err("Rcvd req for Driver version");
4089 strlcpy(driver_version, QWLAN_VERSIONSTR,
4090 sizeof(driver_version));
4091 skb_len += strlen(driver_version) + 1;
4092 count++;
4093 }
4094
4095 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
4096 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004097 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4098 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004099 snprintf(firmware_version, sizeof(firmware_version),
4100 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4101 skb_len += strlen(firmware_version) + 1;
4102 count++;
4103 }
4104
4105 if (count == 0) {
4106 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004107 return -EINVAL;
4108 }
4109
Ryan Hsu7ac88852016-04-28 10:20:34 -07004110 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4111 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4112
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004113 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004114 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115 return -ENOMEM;
4116 }
4117
Ryan Hsu7ac88852016-04-28 10:20:34 -07004118 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4119 if (nla_put_string(reply_skb,
4120 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4121 driver_version))
4122 goto error_nla_fail;
4123 }
4124
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304125 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004126 if (nla_put_string(reply_skb,
4127 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4128 firmware_version))
4129 goto error_nla_fail;
4130 }
4131
4132 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4133 if (nla_put_u32(reply_skb,
4134 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4135 hdd_ctx->radio_index))
4136 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004137 }
4138
4139 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004140
4141error_nla_fail:
4142 hdd_err("nla put fail");
4143 kfree_skb(reply_skb);
4144 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004145}
4146
4147/**
4148 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4149 * @wiphy: pointer to wireless wiphy structure.
4150 * @wdev: pointer to wireless_dev structure.
4151 * @data: Pointer to the data to be passed via vendor interface
4152 * @data_len:Length of the data to be passed
4153 *
4154 * This is called when wlan driver needs to send wifi driver related info
4155 * (driver/fw version) to the user space application upon request.
4156 *
4157 * Return: Return the Success or Failure code.
4158 */
4159static int
4160wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4161 struct wireless_dev *wdev,
4162 const void *data, int data_len)
4163{
4164 int ret;
4165
4166 cds_ssr_protect(__func__);
4167 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4168 cds_ssr_unprotect(__func__);
4169
4170 return ret;
4171}
4172
4173/**
4174 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4175 * @wiphy: pointer to wireless wiphy structure.
4176 * @wdev: pointer to wireless_dev structure.
4177 * @data: Pointer to the data to be passed via vendor interface
4178 * @data_len:Length of the data to be passed
4179 *
4180 * This is called by userspace to know the supported logger features
4181 *
4182 * Return: Return the Success or Failure code.
4183 */
4184static int
4185__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4186 struct wireless_dev *wdev,
4187 const void *data, int data_len)
4188{
4189 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4190 int status;
4191 uint32_t features;
4192 struct sk_buff *reply_skb = NULL;
4193
Jeff Johnson1f61b612016-02-12 16:28:33 -08004194 ENTER_DEV(wdev->netdev);
4195
Anurag Chouhan6d760662016-02-20 16:05:43 +05304196 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004197 hdd_err("Command not allowed in FTM mode");
4198 return -EPERM;
4199 }
4200
4201 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304202 if (status)
4203 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004204
4205 features = 0;
4206
4207 if (hdd_is_memdump_supported())
4208 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4209 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4210 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4211 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4212
4213 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4214 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4215 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004216 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004217 return -ENOMEM;
4218 }
4219
Jeff Johnson020db452016-06-29 14:37:26 -07004220 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004221 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4222 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004223 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004224 kfree_skb(reply_skb);
4225 return -EINVAL;
4226 }
4227
4228 return cfg80211_vendor_cmd_reply(reply_skb);
4229}
4230
4231/**
4232 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4233 * @wiphy: pointer to wireless wiphy structure.
4234 * @wdev: pointer to wireless_dev structure.
4235 * @data: Pointer to the data to be passed via vendor interface
4236 * @data_len:Length of the data to be passed
4237 *
4238 * This is called by userspace to know the supported logger features
4239 *
4240 * Return: Return the Success or Failure code.
4241 */
4242static int
4243wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4244 struct wireless_dev *wdev,
4245 const void *data, int data_len)
4246{
4247 int ret;
4248
4249 cds_ssr_protect(__func__);
4250 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4251 data, data_len);
4252 cds_ssr_unprotect(__func__);
4253
4254 return ret;
4255}
4256
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004257#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004258/**
4259 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304260 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004261 * @bssid: pointer to bssid of roamed AP.
4262 * @req_rsn_ie: Pointer to request RSN IE
4263 * @req_rsn_len: Length of the request RSN IE
4264 * @rsp_rsn_ie: Pointer to response RSN IE
4265 * @rsp_rsn_len: Length of the response RSN IE
4266 * @roam_info_ptr: Pointer to the roaming related information
4267 *
4268 * This is called when wlan driver needs to send the roaming and
4269 * authorization information after roaming.
4270 *
4271 * The information that would be sent is the request RSN IE, response
4272 * RSN IE and BSSID of the newly roamed AP.
4273 *
4274 * If the Authorized status is authenticated, then additional parameters
4275 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4276 * supplicant.
4277 *
4278 * The supplicant upon receiving this event would ignore the legacy
4279 * cfg80211_roamed call and use the entire information from this event.
4280 * The cfg80211_roamed should still co-exist since the kernel will
4281 * make use of the parameters even if the supplicant ignores it.
4282 *
4283 * Return: Return the Success or Failure code.
4284 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304285int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004286 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4287 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4288{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304289 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004290 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004291 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004292 ENTER();
4293
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304294 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004295 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004296
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004297 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004298 !roam_info_ptr->roamSynchInProgress)
4299 return 0;
4300
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304302 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004303 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4304 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4305 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004306 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004307 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4308 GFP_KERNEL);
4309
4310 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004311 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004312 return -EINVAL;
4313 }
4314
4315 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4316 ETH_ALEN, bssid) ||
4317 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4318 req_rsn_len, req_rsn_ie) ||
4319 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4320 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004321 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004322 goto nla_put_failure;
4323 }
Jeff Johnson020db452016-06-29 14:37:26 -07004324 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004325 if (roam_info_ptr->synchAuthStatus ==
4326 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004327 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004328 if (nla_put_u8(skb,
4329 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4330 hdd_err("nla put fail");
4331 goto nla_put_failure;
4332 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004333 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4334 /* if FT or CCKM connection: dont send replay counter */
4335 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4336 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4337 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4338 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4339 nla_put(skb,
4340 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4341 SIR_REPLAY_CTR_LEN,
4342 roam_info_ptr->replay_ctr)) {
4343 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08004344 hdd_err("failed to send replay counter.");
4345 goto nla_put_failure;
4346 }
4347 if (nla_put(skb,
4348 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4349 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4350 nla_put(skb,
4351 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4352 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4353 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004354 goto nla_put_failure;
4355 }
4356 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004357 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004358 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4359 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004360 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004361 goto nla_put_failure;
4362 }
4363 }
4364
Jeff Johnson020db452016-06-29 14:37:26 -07004365 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004366 roam_info_ptr->subnet_change_status);
4367
4368 /*
4369 * Add subnet change status if subnet has changed
4370 * 0 = unchanged
4371 * 1 = changed
4372 * 2 = unknown
4373 */
4374 if (roam_info_ptr->subnet_change_status) {
4375 if (nla_put_u8(skb,
4376 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4377 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004378 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004379 goto nla_put_failure;
4380 }
4381 }
4382
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004383 cfg80211_vendor_event(skb, GFP_KERNEL);
4384 return 0;
4385
4386nla_put_failure:
4387 kfree_skb(skb);
4388 return -EINVAL;
4389}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004390#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004391
4392static const struct nla_policy
4393wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4394
4395 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4396 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4397 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304398 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304399 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4400 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004401 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4402 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4403 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4404 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4405 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304406 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004407};
4408
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004409/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304410 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4411 *
4412 * @adapter: Pointer to HDD adapter
4413 * @ie_data: Pointer to Scan IEs buffer
4414 * @ie_len: Length of Scan IEs
4415 *
4416 * Return: 0 on success; error number otherwise
4417 */
4418static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4419 uint8_t *ie_data, uint8_t ie_len)
4420{
4421 hdd_scaninfo_t *scan_info = NULL;
4422 scan_info = &adapter->scan_info;
4423
4424 if (scan_info->default_scan_ies) {
4425 qdf_mem_free(scan_info->default_scan_ies);
4426 scan_info->default_scan_ies = NULL;
4427 }
4428
4429 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4430 if (!scan_info->default_scan_ies)
4431 return -ENOMEM;
4432
4433 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4434 scan_info->default_scan_ies_len = ie_len;
4435 return 0;
4436}
4437
4438/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004439 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4440 * vendor command
4441 *
4442 * @wiphy: wiphy device pointer
4443 * @wdev: wireless device pointer
4444 * @data: Vendor command data buffer
4445 * @data_len: Buffer length
4446 *
4447 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4448 *
4449 * Return: Error code.
4450 */
4451static int
4452__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4453 struct wireless_dev *wdev,
4454 const void *data,
4455 int data_len)
4456{
4457 struct net_device *dev = wdev->netdev;
4458 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4459 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4460 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4461 int ret_val = 0;
4462 u32 modulated_dtim;
4463 u16 stats_avg_factor;
4464 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304465 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004466 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004467 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304468 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304469 int attr_len;
4470 int access_policy = 0;
4471 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4472 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304473 uint16_t scan_ie_len = 0;
4474 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304475 struct sir_set_tx_rx_aggregation_size request;
4476 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004477 uint8_t retry, delay;
4478 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304479 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304480
Jeff Johnson1f61b612016-02-12 16:28:33 -08004481 ENTER_DEV(dev);
4482
Anurag Chouhan6d760662016-02-20 16:05:43 +05304483 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004484 hdd_err("Command not allowed in FTM mode");
4485 return -EPERM;
4486 }
4487
4488 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304489 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491
4492 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4493 data, data_len,
4494 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004495 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004496 return -EINVAL;
4497 }
4498
Krunal Sonie3531942016-04-12 17:43:53 -07004499 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4500 ftm_capab = nla_get_u32(tb[
4501 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4502 hdd_ctx->config->fine_time_meas_cap =
4503 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4504 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304505 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004506 hdd_ctx->config->fine_time_meas_cap);
4507 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4508 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4509 hdd_ctx->config->fine_time_meas_cap);
4510 }
4511
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004512 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4513 modulated_dtim = nla_get_u32(
4514 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4515
4516 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4517 adapter->sessionId,
4518 modulated_dtim);
4519
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304520 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 ret_val = -EPERM;
4522 }
4523
Kapil Gupta6213c012016-09-02 19:39:09 +05304524 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4525 qpower = nla_get_u8(
4526 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4527 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4528 ret_val = -EINVAL;
4529 }
4530
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004531 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4532 stats_avg_factor = nla_get_u16(
4533 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4534 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4535 adapter->sessionId,
4536 stats_avg_factor);
4537
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304538 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004539 ret_val = -EPERM;
4540 }
4541
4542
4543 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4544 guard_time = nla_get_u32(
4545 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4546 status = sme_configure_guard_time(hdd_ctx->hHal,
4547 adapter->sessionId,
4548 guard_time);
4549
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304550 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004551 ret_val = -EPERM;
4552 }
4553
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304554 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4555 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4556 attr_len = nla_len(
4557 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4558 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4559 hdd_info("Invalid value. attr_len %d",
4560 attr_len);
4561 return -EINVAL;
4562 }
4563
4564 nla_memcpy(&vendor_ie,
4565 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4566 attr_len);
4567 vendor_ie_present = true;
4568 hdd_info("Access policy vendor ie present.attr_len %d",
4569 attr_len);
4570 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4571 &vendor_ie[0], attr_len);
4572 }
4573
4574 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4575 access_policy = (int) nla_get_u32(
4576 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4577 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4578 (access_policy >
4579 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4580 hdd_info("Invalid value. access_policy %d",
4581 access_policy);
4582 return -EINVAL;
4583 }
4584 access_policy_present = true;
4585 hdd_info("Access policy present. access_policy %d",
4586 access_policy);
4587 }
4588
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004589 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4590 retry = nla_get_u8(tb[
4591 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4592 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4593 CFG_NON_AGG_RETRY_MAX : retry;
4594 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4595 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4596 retry, PDEV_CMD);
4597 }
4598
4599 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4600 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4601 retry = retry > CFG_AGG_RETRY_MAX ?
4602 CFG_AGG_RETRY_MAX : retry;
4603
4604 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4605 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4606 CFG_AGG_RETRY_MIN : retry;
4607 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4608 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4609 retry, PDEV_CMD);
4610 }
4611
4612 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4613 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4614 retry = retry > CFG_MGMT_RETRY_MAX ?
4615 CFG_MGMT_RETRY_MAX : retry;
4616 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4617 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4618 retry, PDEV_CMD);
4619 }
4620
4621 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4622 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4623 retry = retry > CFG_CTRL_RETRY_MAX ?
4624 CFG_CTRL_RETRY_MAX : retry;
4625 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4626 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4627 retry, PDEV_CMD);
4628 }
4629
4630 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4631 delay = nla_get_u8(tb[
4632 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4633 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4634 CFG_PROPAGATION_DELAY_MAX : delay;
4635 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4636 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4637 delay, PDEV_CMD);
4638 }
4639
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304640 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4641 tx_fail_count = nla_get_u32(
4642 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4643 if (tx_fail_count) {
4644 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4645 adapter->sessionId, tx_fail_count);
4646 if (QDF_STATUS_SUCCESS != status) {
4647 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4648 status);
4649 return -EINVAL;
4650 }
4651 }
4652 }
4653
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304654 if (vendor_ie_present && access_policy_present) {
4655 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4656 access_policy =
4657 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304658 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304659 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304660 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304661
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304662 hdd_info("calling sme_update_access_policy_vendor_ie");
4663 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4664 adapter->sessionId, &vendor_ie[0],
4665 access_policy);
4666 if (QDF_STATUS_SUCCESS != status) {
4667 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304668 return -EINVAL;
4669 }
4670 }
4671
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304672 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4673 set_value = nla_get_u8(
4674 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4675 hdd_info("set_value: %d", set_value);
4676 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4677 }
4678
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304679 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4680 scan_ie_len = nla_len(
4681 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4682 hdd_info("Received default scan IE of len %d session %d device mode %d",
4683 scan_ie_len, adapter->sessionId,
4684 adapter->device_mode);
4685 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4686 scan_ie = (uint8_t *) nla_data(tb
4687 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304688
4689 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4690 scan_ie_len))
4691 hdd_err("Failed to save default scan IEs");
4692
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304693 if (adapter->device_mode == QDF_STA_MODE) {
4694 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4695 adapter->sessionId, scan_ie,
4696 scan_ie_len);
4697 if (QDF_STATUS_SUCCESS != status)
4698 ret_val = -EPERM;
4699 }
4700 } else
4701 ret_val = -EPERM;
4702 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304703
4704 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4705 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4706 /* if one is specified, both must be specified */
4707 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4708 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4709 hdd_err("Both TX and RX MPDU Aggregation required");
4710 return -EINVAL;
4711 }
4712
4713 request.tx_aggregation_size = nla_get_u8(
4714 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4715 request.rx_aggregation_size = nla_get_u8(
4716 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4717 request.vdev_id = adapter->sessionId;
4718
4719 if (request.tx_aggregation_size >=
4720 CFG_TX_AGGREGATION_SIZE_MIN &&
4721 request.tx_aggregation_size <=
4722 CFG_TX_AGGREGATION_SIZE_MAX &&
4723 request.rx_aggregation_size >=
4724 CFG_RX_AGGREGATION_SIZE_MIN &&
4725 request.rx_aggregation_size <=
4726 CFG_RX_AGGREGATION_SIZE_MAX) {
4727 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4728 if (qdf_status != QDF_STATUS_SUCCESS) {
4729 hdd_err("failed to set aggr sizes err %d",
4730 qdf_status);
4731 ret_val = -EPERM;
4732 }
4733 } else {
4734 hdd_err("TX %d RX %d MPDU aggr size not in range",
4735 request.tx_aggregation_size,
4736 request.rx_aggregation_size);
4737 ret_val = -EINVAL;
4738 }
4739 }
4740
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304741 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4742 uint8_t ignore_assoc_disallowed;
4743
4744 ignore_assoc_disallowed
4745 = nla_get_u8(tb[
4746 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4747 hdd_info("Set ignore_assoc_disallowed value - %d",
4748 ignore_assoc_disallowed);
4749 if ((ignore_assoc_disallowed <
4750 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4751 (ignore_assoc_disallowed >
4752 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4753 return -EPERM;
4754
4755 sme_update_session_param(hdd_ctx->hHal,
4756 adapter->sessionId,
4757 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4758 ignore_assoc_disallowed);
4759 }
4760
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004761 return ret_val;
4762}
4763
4764/**
4765 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4766 * vendor command
4767 *
4768 * @wiphy: wiphy device pointer
4769 * @wdev: wireless device pointer
4770 * @data: Vendor command data buffer
4771 * @data_len: Buffer length
4772 *
4773 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4774 *
4775 * Return: EOK or other error codes.
4776 */
4777static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4778 struct wireless_dev *wdev,
4779 const void *data,
4780 int data_len)
4781{
4782 int ret;
4783
4784 cds_ssr_protect(__func__);
4785 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4786 data, data_len);
4787 cds_ssr_unprotect(__func__);
4788
4789 return ret;
4790}
4791
4792static const struct
4793nla_policy
4794qca_wlan_vendor_wifi_logger_start_policy
4795[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4796 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4797 = {.type = NLA_U32 },
4798 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4799 = {.type = NLA_U32 },
4800 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4801 = {.type = NLA_U32 },
4802};
4803
4804/**
4805 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4806 * or disable the collection of packet statistics from the firmware
4807 * @wiphy: WIPHY structure pointer
4808 * @wdev: Wireless device structure pointer
4809 * @data: Pointer to the data received
4810 * @data_len: Length of the data received
4811 *
4812 * This function enables or disables the collection of packet statistics from
4813 * the firmware
4814 *
4815 * Return: 0 on success and errno on failure
4816 */
4817static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4818 struct wireless_dev *wdev,
4819 const void *data,
4820 int data_len)
4821{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304822 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004823 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4824 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4825 struct sir_wifi_start_log start_log;
4826
Jeff Johnson1f61b612016-02-12 16:28:33 -08004827 ENTER_DEV(wdev->netdev);
4828
Anurag Chouhan6d760662016-02-20 16:05:43 +05304829 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004830 hdd_err("Command not allowed in FTM mode");
4831 return -EPERM;
4832 }
4833
4834 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304835 if (status)
4836 return status;
4837
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004838
4839 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4840 data, data_len,
4841 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004842 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843 return -EINVAL;
4844 }
4845
4846 /* Parse and fetch ring id */
4847 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004848 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849 return -EINVAL;
4850 }
4851 start_log.ring_id = nla_get_u32(
4852 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004853 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854
4855 /* Parse and fetch verbose level */
4856 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004857 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004858 return -EINVAL;
4859 }
4860 start_log.verbose_level = nla_get_u32(
4861 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004862 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004863
4864 /* Parse and fetch flag */
4865 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004866 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004867 return -EINVAL;
4868 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304869 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304871 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004872
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304873 /* size is buff size which can be set using iwpriv command*/
4874 start_log.size = 0;
4875
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004876 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4877
4878 if (start_log.ring_id == RING_ID_WAKELOCK) {
4879 /* Start/stop wakelock events */
4880 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4881 cds_set_wakelock_logging(true);
4882 else
4883 cds_set_wakelock_logging(false);
4884 return 0;
4885 }
4886
4887 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304888 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004889 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004890 status);
4891 return -EINVAL;
4892 }
4893 return 0;
4894}
4895
4896/**
4897 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4898 * or disable the collection of packet statistics from the firmware
4899 * @wiphy: WIPHY structure pointer
4900 * @wdev: Wireless device structure pointer
4901 * @data: Pointer to the data received
4902 * @data_len: Length of the data received
4903 *
4904 * This function is used to enable or disable the collection of packet
4905 * statistics from the firmware
4906 *
4907 * Return: 0 on success and errno on failure
4908 */
4909static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4910 struct wireless_dev *wdev,
4911 const void *data,
4912 int data_len)
4913{
4914 int ret = 0;
4915
4916 cds_ssr_protect(__func__);
4917 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4918 wdev, data, data_len);
4919 cds_ssr_unprotect(__func__);
4920
4921 return ret;
4922}
4923
4924static const struct
4925nla_policy
4926qca_wlan_vendor_wifi_logger_get_ring_data_policy
4927[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4928 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4929 = {.type = NLA_U32 },
4930};
4931
4932/**
4933 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4934 * @wiphy: WIPHY structure pointer
4935 * @wdev: Wireless device structure pointer
4936 * @data: Pointer to the data received
4937 * @data_len: Length of the data received
4938 *
4939 * This function is used to flush or retrieve the per packet statistics from
4940 * the driver
4941 *
4942 * Return: 0 on success and errno on failure
4943 */
4944static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4945 struct wireless_dev *wdev,
4946 const void *data,
4947 int data_len)
4948{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304949 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004950 uint32_t ring_id;
4951 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4952 struct nlattr *tb
4953 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4954
Jeff Johnson1f61b612016-02-12 16:28:33 -08004955 ENTER_DEV(wdev->netdev);
4956
Anurag Chouhan6d760662016-02-20 16:05:43 +05304957 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004958 hdd_err("Command not allowed in FTM mode");
4959 return -EPERM;
4960 }
4961
4962 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304963 if (status)
4964 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004965
4966 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4967 data, data_len,
4968 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004969 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004970 return -EINVAL;
4971 }
4972
4973 /* Parse and fetch ring id */
4974 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004975 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004976 return -EINVAL;
4977 }
4978
4979 ring_id = nla_get_u32(
4980 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4981
4982 if (ring_id == RING_ID_PER_PACKET_STATS) {
4983 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004984 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304985 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4986 /*
4987 * As part of DRIVER ring ID, flush both driver and fw logs.
4988 * For other Ring ID's driver doesn't have any rings to flush
4989 */
4990 hdd_notice("Bug report triggered by framework");
4991
4992 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4993 WLAN_LOG_INDICATOR_FRAMEWORK,
4994 WLAN_LOG_REASON_CODE_UNUSED,
4995 true, false);
4996 if (QDF_STATUS_SUCCESS != status) {
4997 hdd_err("Failed to trigger bug report");
4998 return -EINVAL;
4999 }
5000 } else {
5001 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5002 WLAN_LOG_INDICATOR_FRAMEWORK,
5003 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005004 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 return 0;
5006}
5007
5008/**
5009 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5010 * @wiphy: WIPHY structure pointer
5011 * @wdev: Wireless device structure pointer
5012 * @data: Pointer to the data received
5013 * @data_len: Length of the data received
5014 *
5015 * This function is used to flush or retrieve the per packet statistics from
5016 * the driver
5017 *
5018 * Return: 0 on success and errno on failure
5019 */
5020static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5021 struct wireless_dev *wdev,
5022 const void *data,
5023 int data_len)
5024{
5025 int ret = 0;
5026
5027 cds_ssr_protect(__func__);
5028 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5029 wdev, data, data_len);
5030 cds_ssr_unprotect(__func__);
5031
5032 return ret;
5033}
5034
5035#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5036/**
5037 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5038 * @hdd_ctx: HDD context
5039 * @request_id: [input] request id
5040 * @pattern_id: [output] pattern id
5041 *
5042 * This function loops through request id to pattern id array
5043 * if the slot is available, store the request id and return pattern id
5044 * if entry exists, return the pattern id
5045 *
5046 * Return: 0 on success and errno on failure
5047 */
5048static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5049 uint32_t request_id,
5050 uint8_t *pattern_id)
5051{
5052 uint32_t i;
5053
5054 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5055 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5056 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5057 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5058 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5059 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5060 return 0;
5061 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5062 request_id) {
5063 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5064 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5065 return 0;
5066 }
5067 }
5068 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5069 return -EINVAL;
5070}
5071
5072/**
5073 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5074 * @hdd_ctx: HDD context
5075 * @request_id: [input] request id
5076 * @pattern_id: [output] pattern id
5077 *
5078 * This function loops through request id to pattern id array
5079 * reset request id to 0 (slot available again) and
5080 * return pattern id
5081 *
5082 * Return: 0 on success and errno on failure
5083 */
5084static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5085 uint32_t request_id,
5086 uint8_t *pattern_id)
5087{
5088 uint32_t i;
5089
5090 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5091 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5092 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5093 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5094 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5095 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5096 return 0;
5097 }
5098 }
5099 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5100 return -EINVAL;
5101}
5102
5103
5104/*
5105 * define short names for the global vendor params
5106 * used by __wlan_hdd_cfg80211_offloaded_packets()
5107 */
5108#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5109#define PARAM_REQUEST_ID \
5110 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5111#define PARAM_CONTROL \
5112 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5113#define PARAM_IP_PACKET \
5114 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5115#define PARAM_SRC_MAC_ADDR \
5116 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5117#define PARAM_DST_MAC_ADDR \
5118 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5119#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5120
5121/**
5122 * wlan_hdd_add_tx_ptrn() - add tx pattern
5123 * @adapter: adapter pointer
5124 * @hdd_ctx: hdd context
5125 * @tb: nl attributes
5126 *
5127 * This function reads the NL attributes and forms a AddTxPtrn message
5128 * posts it to SME.
5129 *
5130 */
5131static int
5132wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5133 struct nlattr **tb)
5134{
5135 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305136 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005137 uint32_t request_id, ret, len;
5138 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305139 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005140 uint16_t eth_type = htons(ETH_P_IP);
5141
5142 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005143 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005144 return -ENOTSUPP;
5145 }
5146
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305147 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005148 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005149 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005150 return -ENOMEM;
5151 }
5152
5153 /* Parse and fetch request Id */
5154 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005155 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005156 goto fail;
5157 }
5158
5159 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5160 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005161 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005162 return -EINVAL;
5163 }
Jeff Johnson77848112016-06-29 14:52:06 -07005164 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005165
5166 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005167 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005168 goto fail;
5169 }
5170 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07005171 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005172 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005173 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005174 goto fail;
5175 }
5176
5177 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005178 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005179 goto fail;
5180 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005181 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305182 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005183 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005184 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005185
Anurag Chouhanc5548422016-02-24 18:33:27 +05305186 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005187 &adapter->macAddressCurrent)) {
5188 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005189 goto fail;
5190 }
5191
5192 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005193 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005194 goto fail;
5195 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305196 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005197 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005198 MAC_ADDR_ARRAY(dst_addr.bytes));
5199
5200 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005201 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005202 goto fail;
5203 }
5204 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07005205 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005206
5207 if (add_req->ucPtrnSize < 0 ||
5208 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5209 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005210 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005211 add_req->ucPtrnSize);
5212 goto fail;
5213 }
5214
5215 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305216 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305217 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305218 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305219 QDF_MAC_ADDR_SIZE);
5220 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305221 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005222 len += 2;
5223
5224 /*
5225 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5226 * ------------------------------------------------------------
5227 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5228 * ------------------------------------------------------------
5229 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305230 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231 nla_data(tb[PARAM_IP_PACKET]),
5232 add_req->ucPtrnSize);
5233 add_req->ucPtrnSize += len;
5234
5235 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5236 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005237 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005238 goto fail;
5239 }
5240 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005241 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005242
5243 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305244 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005245 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005246 goto fail;
5247 }
5248
5249 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305250 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005251 return 0;
5252
5253fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305254 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005255 return -EINVAL;
5256}
5257
5258/**
5259 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5260 * @adapter: adapter pointer
5261 * @hdd_ctx: hdd context
5262 * @tb: nl attributes
5263 *
5264 * This function reads the NL attributes and forms a DelTxPtrn message
5265 * posts it to SME.
5266 *
5267 */
5268static int
5269wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5270 struct nlattr **tb)
5271{
5272 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305273 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005274 uint32_t request_id, ret;
5275 uint8_t pattern_id = 0;
5276
5277 /* Parse and fetch request Id */
5278 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005279 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005280 return -EINVAL;
5281 }
5282 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5283 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005284 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005285 return -EINVAL;
5286 }
5287
5288 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5289 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07005290 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005291 return -EINVAL;
5292 }
5293
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305294 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005295 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005296 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005297 return -ENOMEM;
5298 }
5299
Anurag Chouhanc5548422016-02-24 18:33:27 +05305300 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08005301 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005302 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07005303 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304 request_id, del_req->ucPtrnId);
5305
5306 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305307 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005308 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005309 goto fail;
5310 }
5311
5312 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305313 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005314 return 0;
5315
5316fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305317 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005318 return -EINVAL;
5319}
5320
5321
5322/**
5323 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5324 * @wiphy: Pointer to wireless phy
5325 * @wdev: Pointer to wireless device
5326 * @data: Pointer to data
5327 * @data_len: Data length
5328 *
5329 * Return: 0 on success, negative errno on failure
5330 */
5331static int
5332__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5333 struct wireless_dev *wdev,
5334 const void *data,
5335 int data_len)
5336{
5337 struct net_device *dev = wdev->netdev;
5338 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5339 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5340 struct nlattr *tb[PARAM_MAX + 1];
5341 uint8_t control;
5342 int ret;
5343 static const struct nla_policy policy[PARAM_MAX + 1] = {
5344 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5345 [PARAM_CONTROL] = { .type = NLA_U32 },
5346 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305347 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005348 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305349 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005350 [PARAM_PERIOD] = { .type = NLA_U32 },
5351 };
5352
Jeff Johnson1f61b612016-02-12 16:28:33 -08005353 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354
Anurag Chouhan6d760662016-02-20 16:05:43 +05305355 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005356 hdd_err("Command not allowed in FTM mode");
5357 return -EPERM;
5358 }
5359
5360 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305361 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005362 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005363
5364 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005365 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005366 return -ENOTSUPP;
5367 }
5368
5369 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005370 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005371 return -EINVAL;
5372 }
5373
5374 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005375 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376 return -EINVAL;
5377 }
5378 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07005379 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005380
5381 if (control == WLAN_START_OFFLOADED_PACKETS)
5382 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
5383 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
5384 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
5385 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005386 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005387 return -EINVAL;
5388 }
5389}
5390
5391/*
5392 * done with short names for the global vendor params
5393 * used by __wlan_hdd_cfg80211_offloaded_packets()
5394 */
5395#undef PARAM_MAX
5396#undef PARAM_REQUEST_ID
5397#undef PARAM_CONTROL
5398#undef PARAM_IP_PACKET
5399#undef PARAM_SRC_MAC_ADDR
5400#undef PARAM_DST_MAC_ADDR
5401#undef PARAM_PERIOD
5402
5403/**
5404 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5405 * @wiphy: wiphy structure pointer
5406 * @wdev: Wireless device structure pointer
5407 * @data: Pointer to the data received
5408 * @data_len: Length of @data
5409 *
5410 * Return: 0 on success; errno on failure
5411 */
5412static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5413 struct wireless_dev *wdev,
5414 const void *data,
5415 int data_len)
5416{
5417 int ret = 0;
5418
5419 cds_ssr_protect(__func__);
5420 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5421 wdev, data, data_len);
5422 cds_ssr_unprotect(__func__);
5423
5424 return ret;
5425}
5426#endif
5427
5428/*
5429 * define short names for the global vendor params
5430 * used by __wlan_hdd_cfg80211_monitor_rssi()
5431 */
5432#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5433#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5434#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5435#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5436#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5437
5438/**
5439 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5440 * @wiphy: Pointer to wireless phy
5441 * @wdev: Pointer to wireless device
5442 * @data: Pointer to data
5443 * @data_len: Data length
5444 *
5445 * Return: 0 on success, negative errno on failure
5446 */
5447static int
5448__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5449 struct wireless_dev *wdev,
5450 const void *data,
5451 int data_len)
5452{
5453 struct net_device *dev = wdev->netdev;
5454 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5455 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5456 struct nlattr *tb[PARAM_MAX + 1];
5457 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305458 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005459 int ret;
5460 uint32_t control;
5461 static const struct nla_policy policy[PARAM_MAX + 1] = {
5462 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5463 [PARAM_CONTROL] = { .type = NLA_U32 },
5464 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5465 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5466 };
5467
Jeff Johnson1f61b612016-02-12 16:28:33 -08005468 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005469
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305470 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5471 hdd_err("invalid session id: %d", adapter->sessionId);
5472 return -EINVAL;
5473 }
5474
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005475 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305476 if (ret)
5477 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005478
5479 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005480 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005481 return -ENOTSUPP;
5482 }
5483
5484 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005485 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005486 return -EINVAL;
5487 }
5488
5489 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005490 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005491 return -EINVAL;
5492 }
5493
5494 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005495 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005496 return -EINVAL;
5497 }
5498
5499 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5500 req.session_id = adapter->sessionId;
5501 control = nla_get_u32(tb[PARAM_CONTROL]);
5502
5503 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5504 req.control = true;
5505 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005506 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005507 return -EINVAL;
5508 }
5509
5510 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005511 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005512 return -EINVAL;
5513 }
5514
5515 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5516 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5517
5518 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005519 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005520 req.min_rssi, req.max_rssi);
5521 return -EINVAL;
5522 }
Jeff Johnson77848112016-06-29 14:52:06 -07005523 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005524 req.min_rssi, req.max_rssi);
5525
5526 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5527 req.control = false;
5528 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005529 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005530 return -EINVAL;
5531 }
Jeff Johnson77848112016-06-29 14:52:06 -07005532 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005533 req.request_id, req.session_id, req.control);
5534
5535 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305536 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005537 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005538 return -EINVAL;
5539 }
5540
5541 return 0;
5542}
5543
5544/*
5545 * done with short names for the global vendor params
5546 * used by __wlan_hdd_cfg80211_monitor_rssi()
5547 */
5548#undef PARAM_MAX
5549#undef PARAM_CONTROL
5550#undef PARAM_REQUEST_ID
5551#undef PARAM_MAX_RSSI
5552#undef PARAM_MIN_RSSI
5553
5554/**
5555 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5556 * @wiphy: wiphy structure pointer
5557 * @wdev: Wireless device structure pointer
5558 * @data: Pointer to the data received
5559 * @data_len: Length of @data
5560 *
5561 * Return: 0 on success; errno on failure
5562 */
5563static int
5564wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5565 const void *data, int data_len)
5566{
5567 int ret;
5568
5569 cds_ssr_protect(__func__);
5570 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5571 cds_ssr_unprotect(__func__);
5572
5573 return ret;
5574}
5575
5576/**
5577 * hdd_rssi_threshold_breached() - rssi breached NL event
5578 * @hddctx: HDD context
5579 * @data: rssi breached event data
5580 *
5581 * This function reads the rssi breached event %data and fill in the skb with
5582 * NL attributes and send up the NL event.
5583 *
5584 * Return: none
5585 */
5586void hdd_rssi_threshold_breached(void *hddctx,
5587 struct rssi_breach_event *data)
5588{
5589 hdd_context_t *hdd_ctx = hddctx;
5590 struct sk_buff *skb;
5591
5592 ENTER();
5593
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305594 if (wlan_hdd_validate_context(hdd_ctx))
5595 return;
5596 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005597 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005598 return;
5599 }
5600
5601 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5602 NULL,
5603 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5604 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5605 GFP_KERNEL);
5606
5607 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005608 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005609 return;
5610 }
5611
Jeff Johnson77848112016-06-29 14:52:06 -07005612 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005613 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005614 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005615 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5616
5617 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5618 data->request_id) ||
5619 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5620 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5621 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5622 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005623 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005624 goto fail;
5625 }
5626
5627 cfg80211_vendor_event(skb, GFP_KERNEL);
5628 return;
5629
5630fail:
5631 kfree_skb(skb);
5632 return;
5633}
5634
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305635static const struct nla_policy
5636ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5637 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5638};
5639
5640/**
5641 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5642 * @wiphy: Pointer to wireless phy
5643 * @wdev: Pointer to wireless device
5644 * @data: Pointer to data
5645 * @data_len: Length of @data
5646 *
5647 * Return: 0 on success, negative errno on failure
5648 */
5649static int
5650__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5651 struct wireless_dev *wdev,
5652 const void *data, int data_len)
5653{
5654 int status;
5655 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5656 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005657 struct net_device *dev = wdev->netdev;
5658 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305659
5660 ENTER_DEV(wdev->netdev);
5661
5662 status = wlan_hdd_validate_context(pHddCtx);
5663 if (0 != status)
5664 return status;
5665 if (!pHddCtx->config->fhostNSOffload) {
5666 hdd_err("ND Offload not supported");
5667 return -EINVAL;
5668 }
5669
5670 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5671 (struct nlattr *)data,
5672 data_len, ns_offload_set_policy)) {
5673 hdd_err("nla_parse failed");
5674 return -EINVAL;
5675 }
5676
5677 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5678 hdd_err("ND Offload flag attribute not present");
5679 return -EINVAL;
5680 }
5681
5682 pHddCtx->ns_offload_enable =
5683 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5684
Dustin Brownd8279d22016-09-07 14:52:57 -07005685 /* update ns offload in case it is already enabled/disabled */
5686 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5687
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305688 return 0;
5689}
5690
5691/**
5692 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5693 * @wiphy: pointer to wireless wiphy structure.
5694 * @wdev: pointer to wireless_dev structure.
5695 * @data: Pointer to the data to be passed via vendor interface
5696 * @data_len:Length of the data to be passed
5697 *
5698 * Return: Return the Success or Failure code.
5699 */
5700static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5701 struct wireless_dev *wdev,
5702 const void *data, int data_len)
5703{
5704 int ret;
5705
5706 cds_ssr_protect(__func__);
5707 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5708 cds_ssr_unprotect(__func__);
5709
5710 return ret;
5711}
5712
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005713/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5714 * @wiphy: Pointer to wireless phy
5715 * @wdev: Pointer to wireless device
5716 * @data: Pointer to data
5717 * @data_len: Data length
5718 *
5719 * This function return the preferred frequency list generated by the policy
5720 * manager.
5721 *
5722 * Return: success or failure code
5723 */
5724static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5725 struct wireless_dev
5726 *wdev, const void *data,
5727 int data_len)
5728{
5729 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5730 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305731 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305732 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005733 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305734 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005735 enum cds_con_mode intf_mode;
5736 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5737 struct sk_buff *reply_skb;
5738
Jeff Johnson1f61b612016-02-12 16:28:33 -08005739 ENTER_DEV(wdev->netdev);
5740
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005741 ret = wlan_hdd_validate_context(hdd_ctx);
5742 if (ret)
5743 return -EINVAL;
5744
5745 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5746 data, data_len, NULL)) {
5747 hdd_err("Invalid ATTR");
5748 return -EINVAL;
5749 }
5750
5751 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5752 hdd_err("attr interface type failed");
5753 return -EINVAL;
5754 }
5755
5756 intf_mode = nla_get_u32(tb
5757 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5758
5759 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5760 hdd_err("Invalid interface type");
5761 return -EINVAL;
5762 }
5763
5764 hdd_debug("Userspace requested pref freq list");
5765
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305766 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5767 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305768 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005769 hdd_err("Get pcl failed");
5770 return -EINVAL;
5771 }
5772
5773 /* convert channel number to frequency */
5774 for (i = 0; i < pcl_len; i++) {
5775 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5776 freq_list[i] =
5777 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005778 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005779 else
5780 freq_list[i] =
5781 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005782 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005783 }
5784
5785 /* send the freq_list back to supplicant */
5786 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5787 sizeof(u32) *
5788 pcl_len +
5789 NLMSG_HDRLEN);
5790
5791 if (!reply_skb) {
5792 hdd_err("Allocate reply_skb failed");
5793 return -EINVAL;
5794 }
5795
5796 if (nla_put_u32(reply_skb,
5797 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5798 intf_mode) ||
5799 nla_put(reply_skb,
5800 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5801 sizeof(uint32_t) * pcl_len,
5802 freq_list)) {
5803 hdd_err("nla put fail");
5804 kfree_skb(reply_skb);
5805 return -EINVAL;
5806 }
5807
5808 return cfg80211_vendor_cmd_reply(reply_skb);
5809}
5810
5811/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5812 * @wiphy: Pointer to wireless phy
5813 * @wdev: Pointer to wireless device
5814 * @data: Pointer to data
5815 * @data_len: Data length
5816 *
5817 * This function return the preferred frequency list generated by the policy
5818 * manager.
5819 *
5820 * Return: success or failure code
5821 */
5822static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5823 struct wireless_dev
5824 *wdev, const void *data,
5825 int data_len)
5826{
5827 int ret = 0;
5828
5829 cds_ssr_protect(__func__);
5830 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5831 data, data_len);
5832 cds_ssr_unprotect(__func__);
5833
5834 return ret;
5835}
5836
5837/**
5838 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5839 * @wiphy: Pointer to wireless phy
5840 * @wdev: Pointer to wireless device
5841 * @data: Pointer to data
5842 * @data_len: Data length
5843 *
5844 * Return: 0 on success, negative errno on failure
5845 */
5846static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5847 struct wireless_dev *wdev,
5848 const void *data,
5849 int data_len)
5850{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305851 struct net_device *ndev = wdev->netdev;
5852 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005853 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5854 int ret = 0;
5855 enum cds_con_mode intf_mode;
5856 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5857 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005858
Jeff Johnson1f61b612016-02-12 16:28:33 -08005859 ENTER_DEV(ndev);
5860
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005861 ret = wlan_hdd_validate_context(hdd_ctx);
5862 if (ret)
5863 return ret;
5864
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005865 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5866 data, data_len, NULL)) {
5867 hdd_err("Invalid ATTR");
5868 return -EINVAL;
5869 }
5870
5871 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5872 hdd_err("attr interface type failed");
5873 return -EINVAL;
5874 }
5875
5876 intf_mode = nla_get_u32(tb
5877 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5878
5879 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5880 hdd_err("Invalid interface type");
5881 return -EINVAL;
5882 }
5883
5884 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5885 hdd_err("attr probable freq failed");
5886 return -EINVAL;
5887 }
5888
5889 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5890 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5891
5892 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005893 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005894 channel_hint, HW_MODE_20_MHZ)) {
5895 hdd_err("Set channel hint failed due to concurrency check");
5896 return -EINVAL;
5897 }
5898
Krunal Soni09e55032016-06-07 10:06:55 -07005899 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5900 hdd_warn("Remain On Channel Pending");
5901
Krunal Soni3091bcc2016-06-23 12:28:21 -07005902 ret = qdf_reset_connection_update();
5903 if (!QDF_IS_STATUS_SUCCESS(ret))
5904 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005905
Krunal Soni3091bcc2016-06-23 12:28:21 -07005906 ret = cds_current_connections_update(adapter->sessionId,
5907 channel_hint,
5908 SIR_UPDATE_REASON_SET_OPER_CHAN);
5909 if (QDF_STATUS_E_FAILURE == ret) {
5910 /* return in the failure case */
5911 hdd_err("ERROR: connections update failed!!");
5912 return -EINVAL;
5913 }
5914
5915 if (QDF_STATUS_SUCCESS == ret) {
5916 /*
5917 * Success is the only case for which we expect hw mode
5918 * change to take place, hence we need to wait.
5919 * For any other return value it should be a pass
5920 * through
5921 */
5922 ret = qdf_wait_for_connection_update();
5923 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5924 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005925 return -EINVAL;
5926 }
5927
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005928 }
5929
5930 return 0;
5931}
5932
5933/**
5934 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5935 * @wiphy: Pointer to wireless phy
5936 * @wdev: Pointer to wireless device
5937 * @data: Pointer to data
5938 * @data_len: Data length
5939 *
5940 * Return: 0 on success, negative errno on failure
5941 */
5942static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5943 struct wireless_dev *wdev,
5944 const void *data,
5945 int data_len)
5946{
5947 int ret = 0;
5948
5949 cds_ssr_protect(__func__);
5950 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5951 data, data_len);
5952 cds_ssr_unprotect(__func__);
5953
5954 return ret;
5955}
5956
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305957static const struct
5958nla_policy
5959qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5960 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5961};
5962
5963/**
5964 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5965 * @wiphy: WIPHY structure pointer
5966 * @wdev: Wireless device structure pointer
5967 * @data: Pointer to the data received
5968 * @data_len: Length of the data received
5969 *
5970 * This function is used to get link properties like nss, rate flags and
5971 * operating frequency for the active connection with the given peer.
5972 *
5973 * Return: 0 on success and errno on failure
5974 */
5975static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5976 struct wireless_dev *wdev,
5977 const void *data,
5978 int data_len)
5979{
5980 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5981 struct net_device *dev = wdev->netdev;
5982 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5983 hdd_station_ctx_t *hdd_sta_ctx;
5984 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305985 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305986 uint32_t sta_id;
5987 struct sk_buff *reply_skb;
5988 uint32_t rate_flags = 0;
5989 uint8_t nss;
5990 uint8_t final_rate_flags = 0;
5991 uint32_t freq;
5992
Jeff Johnson1f61b612016-02-12 16:28:33 -08005993 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305994
Anurag Chouhan6d760662016-02-20 16:05:43 +05305995 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305996 hdd_err("Command not allowed in FTM mode");
5997 return -EPERM;
5998 }
5999
6000 if (0 != wlan_hdd_validate_context(hdd_ctx))
6001 return -EINVAL;
6002
6003 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6004 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006005 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306006 return -EINVAL;
6007 }
6008
6009 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006010 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306011 adapter->device_mode);
6012 return -EINVAL;
6013 }
6014
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306015 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306016 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07006017 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306018 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6019
Krunal Sonib4326f22016-03-10 13:05:51 -08006020 if (adapter->device_mode == QDF_STA_MODE ||
6021 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306022 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6023 if ((hdd_sta_ctx->conn_info.connState !=
6024 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306025 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306026 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006027 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306028 MAC_ADDR_ARRAY(peer_mac));
6029 return -EINVAL;
6030 }
6031
6032 nss = hdd_sta_ctx->conn_info.nss;
6033 freq = cds_chan_to_freq(
6034 hdd_sta_ctx->conn_info.operationChannel);
6035 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006036 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6037 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306038
6039 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6040 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306041 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306042 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306043 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306044 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306045 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306046 break;
6047 }
6048
6049 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006050 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306051 MAC_ADDR_ARRAY(peer_mac));
6052 return -EINVAL;
6053 }
6054
6055 nss = adapter->aStaInfo[sta_id].nss;
6056 freq = cds_chan_to_freq(
6057 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6058 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6059 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006060 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306061 MAC_ADDR_ARRAY(peer_mac));
6062 return -EINVAL;
6063 }
6064
6065 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6066 if (rate_flags & eHAL_TX_RATE_VHT80) {
6067 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006068#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306069 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006070#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306071 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6072 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006073#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306074 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006075#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306076 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6077 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6078 } else if (rate_flags &
6079 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6080 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006081#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306082 if (rate_flags & eHAL_TX_RATE_HT40)
6083 final_rate_flags |=
6084 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006085#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306086 }
6087
6088 if (rate_flags & eHAL_TX_RATE_SGI) {
6089 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6090 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6091 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6092 }
6093 }
6094
6095 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6096 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6097
6098 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006099 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306100 return -EINVAL;
6101 }
6102
6103 if (nla_put_u8(reply_skb,
6104 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6105 nss) ||
6106 nla_put_u8(reply_skb,
6107 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6108 final_rate_flags) ||
6109 nla_put_u32(reply_skb,
6110 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6111 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006112 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306113 kfree_skb(reply_skb);
6114 return -EINVAL;
6115 }
6116
6117 return cfg80211_vendor_cmd_reply(reply_skb);
6118}
6119
6120/**
6121 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6122 * properties.
6123 * @wiphy: WIPHY structure pointer
6124 * @wdev: Wireless device structure pointer
6125 * @data: Pointer to the data received
6126 * @data_len: Length of the data received
6127 *
6128 * This function is used to get link properties like nss, rate flags and
6129 * operating frequency for the active connection with the given peer.
6130 *
6131 * Return: 0 on success and errno on failure
6132 */
6133static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6134 struct wireless_dev *wdev,
6135 const void *data,
6136 int data_len)
6137{
6138 int ret = 0;
6139
6140 cds_ssr_protect(__func__);
6141 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6142 wdev, data, data_len);
6143 cds_ssr_unprotect(__func__);
6144
6145 return ret;
6146}
6147
Peng Xu278d0122015-09-24 16:34:17 -07006148static const struct
6149nla_policy
6150qca_wlan_vendor_ota_test_policy
6151[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6152 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6153};
6154
6155/**
6156 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6157 * @wiphy: Pointer to wireless phy
6158 * @wdev: Pointer to wireless device
6159 * @data: Pointer to data
6160 * @data_len: Data length
6161 *
6162 * Return: 0 on success, negative errno on failure
6163 */
6164static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6165 struct wireless_dev *wdev,
6166 const void *data,
6167 int data_len)
6168{
6169 struct net_device *dev = wdev->netdev;
6170 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6171 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6172 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6173 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6174 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306175 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006176 uint32_t current_roam_state;
6177
Jeff Johnson1f61b612016-02-12 16:28:33 -08006178 ENTER_DEV(dev);
6179
Anurag Chouhan6d760662016-02-20 16:05:43 +05306180 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006181 hdd_err("Command not allowed in FTM mode");
6182 return -EPERM;
6183 }
6184
6185 if (0 != wlan_hdd_validate_context(hdd_ctx))
6186 return -EINVAL;
6187
6188 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6189 data, data_len,
6190 qca_wlan_vendor_ota_test_policy)) {
6191 hdd_err("invalid attr");
6192 return -EINVAL;
6193 }
6194
6195 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6196 hdd_err("attr ota test failed");
6197 return -EINVAL;
6198 }
6199
6200 ota_enable = nla_get_u8(
6201 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6202
6203 hdd_info(" OTA test enable = %d", ota_enable);
6204 if (ota_enable != 1) {
6205 hdd_err("Invalid value, only enable test mode is supported!");
6206 return -EINVAL;
6207 }
6208
6209 current_roam_state =
6210 sme_get_current_roam_state(hal, adapter->sessionId);
6211 status = sme_stop_roaming(hal, adapter->sessionId,
6212 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306213 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006214 hdd_err("Enable/Disable roaming failed");
6215 return -EINVAL;
6216 }
6217
6218 status = sme_ps_enable_disable(hal, adapter->sessionId,
6219 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306220 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006221 hdd_err("Enable/Disable power save failed");
6222 /* restore previous roaming setting */
6223 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6224 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6225 status = sme_start_roaming(hal, adapter->sessionId,
6226 eCsrHddIssued);
6227 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6228 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6229 status = sme_stop_roaming(hal, adapter->sessionId,
6230 eCsrHddIssued);
6231
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306232 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006233 hdd_err("Restoring roaming state failed");
6234
6235 return -EINVAL;
6236 }
6237
6238
6239 return 0;
6240}
6241
6242/**
6243 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6244 * @wiphy: Pointer to wireless phy
6245 * @wdev: Pointer to wireless device
6246 * @data: Pointer to data
6247 * @data_len: Data length
6248 *
6249 * Return: 0 on success, negative errno on failure
6250 */
6251static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6252 struct wireless_dev *wdev,
6253 const void *data,
6254 int data_len)
6255{
6256 int ret = 0;
6257
6258 cds_ssr_protect(__func__);
6259 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6260 cds_ssr_unprotect(__func__);
6261
6262 return ret;
6263}
6264
Peng Xu4d67c8f2015-10-16 16:02:26 -07006265/**
6266 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6267 * @wiphy: Pointer to wireless phy
6268 * @wdev: Pointer to wireless device
6269 * @data: Pointer to data
6270 * @data_len: Data length
6271 *
6272 * Return: 0 on success, negative errno on failure
6273 */
6274static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6275 struct wireless_dev *wdev,
6276 const void *data,
6277 int data_len)
6278{
6279 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6280 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006281 hdd_adapter_t *adapter;
6282 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006283 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6284 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006285 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006286
Jeff Johnson1f61b612016-02-12 16:28:33 -08006287 ENTER_DEV(dev);
6288
Peng Xu4d67c8f2015-10-16 16:02:26 -07006289 ret = wlan_hdd_validate_context(hdd_ctx);
6290 if (ret)
6291 return ret;
6292
6293 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6294
6295 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6296 data, data_len, NULL)) {
6297 hdd_err("Invalid ATTR");
6298 return -EINVAL;
6299 }
6300
6301 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6302 hdd_err("attr tx power scale failed");
6303 return -EINVAL;
6304 }
6305
6306 scale_value = nla_get_u8(tb
6307 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6308
6309 if (scale_value > MAX_TXPOWER_SCALE) {
6310 hdd_err("Invalid tx power scale level");
6311 return -EINVAL;
6312 }
6313
Peng Xu62c8c432016-05-09 15:23:02 -07006314 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006315
Peng Xu62c8c432016-05-09 15:23:02 -07006316 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006317 hdd_err("Set tx power scale failed");
6318 return -EINVAL;
6319 }
6320
6321 return 0;
6322}
6323
6324/**
6325 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6326 * @wiphy: Pointer to wireless phy
6327 * @wdev: Pointer to wireless device
6328 * @data: Pointer to data
6329 * @data_len: Data length
6330 *
6331 * Return: 0 on success, negative errno on failure
6332 */
6333static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6334 struct wireless_dev *wdev,
6335 const void *data,
6336 int data_len)
6337{
Peng Xu62c8c432016-05-09 15:23:02 -07006338 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006339
6340 cds_ssr_protect(__func__);
6341 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6342 data, data_len);
6343 cds_ssr_unprotect(__func__);
6344
6345 return ret;
6346}
6347
6348/**
6349 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6350 * @wiphy: Pointer to wireless phy
6351 * @wdev: Pointer to wireless device
6352 * @data: Pointer to data
6353 * @data_len: Data length
6354 *
6355 * Return: 0 on success, negative errno on failure
6356 */
6357static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6358 struct wireless_dev *wdev,
6359 const void *data,
6360 int data_len)
6361{
6362 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6363 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006364 hdd_adapter_t *adapter;
6365 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006366 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6367 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006368 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006369
Jeff Johnson1f61b612016-02-12 16:28:33 -08006370 ENTER_DEV(dev);
6371
Peng Xu4d67c8f2015-10-16 16:02:26 -07006372 ret = wlan_hdd_validate_context(hdd_ctx);
6373 if (ret)
6374 return ret;
6375
6376 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6377
6378 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6379 data, data_len, NULL)) {
6380 hdd_err("Invalid ATTR");
6381 return -EINVAL;
6382 }
6383
6384 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6385 hdd_err("attr tx power decrease db value failed");
6386 return -EINVAL;
6387 }
6388
6389 scale_value = nla_get_u8(tb
6390 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6391
Peng Xu62c8c432016-05-09 15:23:02 -07006392 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6393 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006394
Peng Xu62c8c432016-05-09 15:23:02 -07006395 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006396 hdd_err("Set tx power decrease db failed");
6397 return -EINVAL;
6398 }
6399
6400 return 0;
6401}
6402
6403/**
6404 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6405 * @wiphy: Pointer to wireless phy
6406 * @wdev: Pointer to wireless device
6407 * @data: Pointer to data
6408 * @data_len: Data length
6409 *
6410 * Return: 0 on success, negative errno on failure
6411 */
6412static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6413 struct wireless_dev *wdev,
6414 const void *data,
6415 int data_len)
6416{
Peng Xu62c8c432016-05-09 15:23:02 -07006417 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006418
6419 cds_ssr_protect(__func__);
6420 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6421 data, data_len);
6422 cds_ssr_unprotect(__func__);
6423
6424 return ret;
6425}
Peng Xu8fdaa492016-06-22 10:20:47 -07006426
6427/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306428 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6429 * @wiphy: Pointer to wireless phy
6430 * @wdev: Pointer to wireless device
6431 * @data: Pointer to data
6432 * @data_len: Data length
6433 *
6434 * Processes the conditional channel switch request and invokes the helper
6435 * APIs to process the channel switch request.
6436 *
6437 * Return: 0 on success, negative errno on failure
6438 */
6439static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6440 struct wireless_dev *wdev,
6441 const void *data,
6442 int data_len)
6443{
6444 int ret;
6445 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6446 struct net_device *dev = wdev->netdev;
6447 hdd_adapter_t *adapter;
6448 struct nlattr
6449 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6450 uint32_t freq_len, i;
6451 uint32_t *freq;
6452 uint8_t chans[QDF_MAX_NUM_CHAN];
6453
6454 ENTER_DEV(dev);
6455
6456 ret = wlan_hdd_validate_context(hdd_ctx);
6457 if (ret)
6458 return ret;
6459
6460 if (!hdd_ctx->config->enableDFSMasterCap) {
6461 hdd_err("DFS master capability is not present in the driver");
6462 return -EINVAL;
6463 }
6464
6465 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6466 hdd_err("Command not allowed in FTM mode");
6467 return -EPERM;
6468 }
6469
6470 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6471 if (adapter->device_mode != QDF_SAP_MODE) {
6472 hdd_err("Invalid device mode %d", adapter->device_mode);
6473 return -EINVAL;
6474 }
6475
6476 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6477 data, data_len, NULL)) {
6478 hdd_err("Invalid ATTR");
6479 return -EINVAL;
6480 }
6481
6482 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6483 hdd_err("Frequency list is missing");
6484 return -EINVAL;
6485 }
6486
6487 freq_len = nla_len(
6488 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6489 sizeof(uint32_t);
6490
6491 if (freq_len > QDF_MAX_NUM_CHAN) {
6492 hdd_err("insufficient space to hold channels");
6493 return -ENOMEM;
6494 }
6495
6496 hdd_debug("freq_len=%d", freq_len);
6497
6498 freq = nla_data(
6499 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6500
6501
6502 for (i = 0; i < freq_len; i++) {
6503 if (freq[i] == 0)
6504 chans[i] = 0;
6505 else
6506 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6507
6508 hdd_debug("freq[%d]=%d", i, freq[i]);
6509 }
6510
6511 /*
6512 * The input frequency list from user space is designed to be a
6513 * priority based frequency list. This is only to accommodate any
6514 * future request. But, current requirement is only to perform CAC
6515 * on a single channel. So, the first entry from the list is picked.
6516 *
6517 * If channel is zero, any channel in the available outdoor regulatory
6518 * domain will be selected.
6519 */
6520 ret = wlan_hdd_request_pre_cac(chans[0]);
6521 if (ret) {
6522 hdd_err("pre cac request failed with reason:%d", ret);
6523 return ret;
6524 }
6525
6526 return 0;
6527}
6528
6529/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006530 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6531 * @wiphy: Pointer to wireless phy
6532 * @wdev: Pointer to wireless device
6533 * @data: Pointer to data
6534 * @data_len: Data length
6535 *
6536 * This function is to process the p2p listen offload start vendor
6537 * command. It parses the input parameters and invoke WMA API to
6538 * send the command to firmware.
6539 *
6540 * Return: 0 on success, negative errno on failure
6541 */
6542static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6543 struct wireless_dev *wdev,
6544 const void *data,
6545 int data_len)
6546{
6547 int ret;
6548 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6549 struct net_device *dev = wdev->netdev;
6550 hdd_adapter_t *adapter;
6551 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6552 struct sir_p2p_lo_start params;
6553 QDF_STATUS status;
6554
6555 ENTER_DEV(dev);
6556
6557 ret = wlan_hdd_validate_context(hdd_ctx);
6558 if (ret)
6559 return ret;
6560
6561 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6562 hdd_err("Command not allowed in FTM mode");
6563 return -EPERM;
6564 }
6565
6566 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6567 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6568 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6569 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6570 hdd_err("Invalid device mode %d", adapter->device_mode);
6571 return -EINVAL;
6572 }
6573
6574 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6575 data, data_len, NULL)) {
6576 hdd_err("Invalid ATTR");
6577 return -EINVAL;
6578 }
6579
6580 memset(&params, 0, sizeof(params));
6581
6582 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6583 params.ctl_flags = 1; /* set to default value */
6584 else
6585 params.ctl_flags = nla_get_u32(tb
6586 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6587
6588 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6589 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6590 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6591 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6592 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6593 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6594 hdd_err("Attribute parsing failed");
6595 return -EINVAL;
6596 }
6597
6598 params.vdev_id = adapter->sessionId;
6599 params.freq = nla_get_u32(tb
6600 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6601 if ((params.freq != 2412) && (params.freq != 2437) &&
6602 (params.freq != 2462)) {
6603 hdd_err("Invalid listening channel: %d", params.freq);
6604 return -EINVAL;
6605 }
6606
6607 params.period = nla_get_u32(tb
6608 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6609 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6610 hdd_err("Invalid period: %d", params.period);
6611 return -EINVAL;
6612 }
6613
6614 params.interval = nla_get_u32(tb
6615 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6616 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6617 hdd_err("Invalid interval: %d", params.interval);
6618 return -EINVAL;
6619 }
6620
6621 params.count = nla_get_u32(tb
6622 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006623 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006624 hdd_err("Invalid count: %d", params.count);
6625 return -EINVAL;
6626 }
6627
6628 params.device_types = nla_data(tb
6629 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6630 if (params.device_types == NULL) {
6631 hdd_err("Invalid device types");
6632 return -EINVAL;
6633 }
6634
6635 params.dev_types_len = nla_len(tb
6636 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6637 if (params.dev_types_len < 8) {
6638 hdd_err("Invalid device type length: %d", params.dev_types_len);
6639 return -EINVAL;
6640 }
6641
6642 params.probe_resp_tmplt = nla_data(tb
6643 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6644 if (params.probe_resp_tmplt == NULL) {
6645 hdd_err("Invalid probe response template");
6646 return -EINVAL;
6647 }
6648
6649 params.probe_resp_len = nla_len(tb
6650 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6651 if (params.probe_resp_len == 0) {
6652 hdd_err("Invalid probe resp template length: %d",
6653 params.probe_resp_len);
6654 return -EINVAL;
6655 }
6656
6657 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6658 params.freq, params.period, params.interval, params.count);
6659
6660 status = wma_p2p_lo_start(&params);
6661
6662 if (!QDF_IS_STATUS_SUCCESS(status)) {
6663 hdd_err("P2P LO start failed");
6664 return -EINVAL;
6665 }
6666
6667 return 0;
6668}
6669
6670
6671/**
6672 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6673 * @wiphy: Pointer to wireless phy
6674 * @wdev: Pointer to wireless device
6675 * @data: Pointer to data
6676 * @data_len: Data length
6677 *
6678 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6679 * to process p2p listen offload start vendor command.
6680 *
6681 * Return: 0 on success, negative errno on failure
6682 */
6683static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6684 struct wireless_dev *wdev,
6685 const void *data,
6686 int data_len)
6687{
6688 int ret = 0;
6689
6690 cds_ssr_protect(__func__);
6691 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6692 data, data_len);
6693 cds_ssr_unprotect(__func__);
6694
6695 return ret;
6696}
6697
6698/**
6699 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6700 * @wiphy: Pointer to wireless phy
6701 * @wdev: Pointer to wireless device
6702 * @data: Pointer to data
6703 * @data_len: Data length
6704 *
6705 * This function is to process the p2p listen offload stop vendor
6706 * command. It invokes WMA API to send command to firmware.
6707 *
6708 * Return: 0 on success, negative errno on failure
6709 */
6710static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6711 struct wireless_dev *wdev,
6712 const void *data,
6713 int data_len)
6714{
6715 QDF_STATUS status;
6716 hdd_adapter_t *adapter;
6717 struct net_device *dev = wdev->netdev;
6718
6719 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6720 hdd_err("Command not allowed in FTM mode");
6721 return -EPERM;
6722 }
6723
6724 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6725 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6726 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6727 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6728 hdd_err("Invalid device mode");
6729 return -EINVAL;
6730 }
6731
6732 status = wma_p2p_lo_stop(adapter->sessionId);
6733
6734 if (!QDF_IS_STATUS_SUCCESS(status)) {
6735 hdd_err("P2P LO stop failed");
6736 return -EINVAL;
6737 }
6738
6739 return 0;
6740}
6741
6742/**
6743 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6744 * @wiphy: Pointer to wireless phy
6745 * @wdev: Pointer to wireless device
6746 * @data: Pointer to data
6747 * @data_len: Data length
6748 *
6749 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6750 * to process p2p listen offload stop vendor command.
6751 *
6752 * Return: 0 on success, negative errno on failure
6753 */
6754static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6755 struct wireless_dev *wdev,
6756 const void *data,
6757 int data_len)
6758{
6759 int ret = 0;
6760
6761 cds_ssr_protect(__func__);
6762 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6763 data, data_len);
6764 cds_ssr_unprotect(__func__);
6765
6766 return ret;
6767}
6768
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306769/**
6770 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6771 * @wiphy: Pointer to wireless phy
6772 * @wdev: Pointer to wireless device
6773 * @data: Pointer to data
6774 * @data_len: Data length
6775 *
6776 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6777 * to process the conditional channel switch request.
6778 *
6779 * Return: 0 on success, negative errno on failure
6780 */
6781static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6782 struct wireless_dev *wdev,
6783 const void *data,
6784 int data_len)
6785{
6786 int ret;
6787
6788 cds_ssr_protect(__func__);
6789 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6790 data, data_len);
6791 cds_ssr_unprotect(__func__);
6792
6793 return ret;
6794}
6795
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306796/*
6797 * define short names for the global vendor params
6798 * used by __wlan_hdd_cfg80211_bpf_offload()
6799 */
6800#define BPF_INVALID \
6801 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6802#define BPF_SET_RESET \
6803 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6804#define BPF_VERSION \
6805 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6806#define BPF_FILTER_ID \
6807 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6808#define BPF_PACKET_SIZE \
6809 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6810#define BPF_CURRENT_OFFSET \
6811 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6812#define BPF_PROGRAM \
6813 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6814#define BPF_MAX \
6815 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006816
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306817static const struct nla_policy
6818wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6819 [BPF_SET_RESET] = {.type = NLA_U32},
6820 [BPF_VERSION] = {.type = NLA_U32},
6821 [BPF_FILTER_ID] = {.type = NLA_U32},
6822 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6823 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6824 [BPF_PROGRAM] = {.type = NLA_U8},
6825};
6826
6827/**
6828 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6829 * @hdd_context: hdd_context
6830 * @bpf_get_offload: struct for get offload
6831 *
6832 * This function receives the response/data from the lower layer and
6833 * checks to see if the thread is still waiting then post the results to
6834 * upper layer, if the request has timed out then ignore.
6835 *
6836 * Return: None
6837 */
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006838static void hdd_get_bpf_offload_cb(void *hdd_context,
6839 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306840{
6841 hdd_context_t *hdd_ctx = hdd_context;
6842 struct hdd_bpf_context *context;
6843
6844 ENTER();
6845
6846 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006847 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306848 data);
6849 return;
6850 }
6851
6852 spin_lock(&hdd_context_lock);
6853
6854 context = &bpf_context;
6855 /* The caller presumably timed out so there is nothing we can do */
6856 if (context->magic != BPF_CONTEXT_MAGIC) {
6857 spin_unlock(&hdd_context_lock);
6858 return;
6859 }
6860
6861 /* context is valid so caller is still waiting */
6862 /* paranoia: invalidate the magic */
6863 context->magic = 0;
6864
6865 context->capability_response = *data;
6866 complete(&context->completion);
6867
6868 spin_unlock(&hdd_context_lock);
6869
6870 return;
6871}
6872
6873/**
6874 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6875 * @hdd_context: hdd_context
6876 * @bpf_get_offload: struct for get offload
6877 *
6878 * Return: 0 on success, error number otherwise.
6879 */
6880static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6881 struct sir_bpf_get_offload *bpf_get_offload)
6882{
6883 struct sk_buff *skb;
6884 uint32_t nl_buf_len;
6885
6886 ENTER();
6887
6888 nl_buf_len = NLMSG_HDRLEN;
6889 nl_buf_len +=
6890 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6891 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6892
6893 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6894 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006895 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306896 return -ENOMEM;
6897 }
6898
Jeff Johnson77848112016-06-29 14:52:06 -07006899 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306900 bpf_get_offload->bpf_version,
6901 bpf_get_offload->max_bytes_for_bpf_inst);
6902
6903 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6904 bpf_get_offload->max_bytes_for_bpf_inst) ||
6905 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006906 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306907 goto nla_put_failure;
6908 }
6909
6910 cfg80211_vendor_cmd_reply(skb);
6911 EXIT();
6912 return 0;
6913
6914nla_put_failure:
6915 kfree_skb(skb);
6916 return -EINVAL;
6917}
6918
6919/**
6920 * hdd_get_bpf_offload - Get BPF offload Capabilities
6921 * @hdd_ctx: Hdd context
6922 *
6923 * Return: 0 on success, errno on failure
6924 */
6925static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6926{
6927 unsigned long rc;
Houston Hoffman59c097f2016-11-09 15:50:25 -08006928 static struct hdd_bpf_context *context;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306929 QDF_STATUS status;
6930 int ret;
6931
6932 ENTER();
6933
6934 spin_lock(&hdd_context_lock);
6935 context = &bpf_context;
6936 context->magic = BPF_CONTEXT_MAGIC;
6937 INIT_COMPLETION(context->completion);
6938 spin_unlock(&hdd_context_lock);
6939
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006940 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6941 hdd_get_bpf_offload_cb,
6942 hdd_ctx);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306943 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006944 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306945 return -EINVAL;
6946 }
6947 /* request was sent -- wait for the response */
6948 rc = wait_for_completion_timeout(&context->completion,
6949 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6950 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006951 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306952 spin_lock(&hdd_context_lock);
6953 context->magic = 0;
6954 spin_unlock(&hdd_context_lock);
6955
6956 return -ETIMEDOUT;
6957 }
6958 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6959 &bpf_context.capability_response);
6960 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006961 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306962
6963 EXIT();
6964 return ret;
6965}
6966
6967/**
6968 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6969 * @hdd_ctx: Hdd context
6970 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306971 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306972 *
6973 * Return: 0 on success; errno on failure
6974 */
6975static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6976 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306977 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306978{
6979 struct sir_bpf_set_offload *bpf_set_offload;
6980 QDF_STATUS status;
6981 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306982 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306983
6984 ENTER();
6985
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306986 if (adapter->device_mode == QDF_STA_MODE ||
6987 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6988 if (!hdd_conn_is_connected(
6989 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6990 hdd_err("Not in Connected state!");
6991 return -ENOTSUPP;
6992 }
6993 }
6994
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306995 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6996 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006997 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306998 return -ENOMEM;
6999 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307000
7001 /* Parse and fetch bpf packet size */
7002 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007003 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307004 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307005 goto fail;
7006 }
7007 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7008
7009 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07007010 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307011 goto post_sme;
7012 }
7013
7014 /* Parse and fetch bpf program */
7015 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007016 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307017 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307018 goto fail;
7019 }
7020
7021 prog_len = nla_len(tb[BPF_PROGRAM]);
7022 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307023
7024 if (bpf_set_offload->program == NULL) {
7025 hdd_err("qdf_mem_malloc failed for bpf offload program");
7026 ret = -ENOMEM;
7027 goto fail;
7028 }
7029
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307030 bpf_set_offload->current_length = prog_len;
7031 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307032 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307033
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307034 hdd_info("BPF set instructions");
7035 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
7036 bpf_set_offload->program, prog_len);
7037
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307038 /* Parse and fetch filter Id */
7039 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007040 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307041 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307042 goto fail;
7043 }
7044 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7045
7046 /* Parse and fetch current offset */
7047 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007048 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307049 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307050 goto fail;
7051 }
7052 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7053
7054post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07007055 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 +05307056 bpf_set_offload->session_id,
7057 bpf_set_offload->version,
7058 bpf_set_offload->filter_id,
7059 bpf_set_offload->total_length,
7060 bpf_set_offload->current_length,
7061 bpf_set_offload->current_offset);
7062
7063 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7064 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007065 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307066 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307067 goto fail;
7068 }
7069 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307070
7071fail:
7072 if (bpf_set_offload->current_length)
7073 qdf_mem_free(bpf_set_offload->program);
7074 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307075 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307076}
7077
7078/**
7079 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7080 * @wiphy: wiphy structure pointer
7081 * @wdev: Wireless device structure pointer
7082 * @data: Pointer to the data received
7083 * @data_len: Length of @data
7084 *
7085 * Return: 0 on success; errno on failure
7086 */
7087static int
7088__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7089 struct wireless_dev *wdev,
7090 const void *data, int data_len)
7091{
7092 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7093 struct net_device *dev = wdev->netdev;
7094 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7095 struct nlattr *tb[BPF_MAX + 1];
7096 int ret_val, packet_filter_subcmd;
7097
7098 ENTER();
7099
7100 ret_val = wlan_hdd_validate_context(hdd_ctx);
7101 if (ret_val)
7102 return ret_val;
7103
7104 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007105 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307106 return -EINVAL;
7107 }
7108
7109 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007110 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307111 return -ENOTSUPP;
7112 }
7113
7114 if (nla_parse(tb, BPF_MAX, data, data_len,
7115 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007116 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307117 return -EINVAL;
7118 }
7119
7120 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007121 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307122 return -EINVAL;
7123 }
7124
7125 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7126
7127 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7128 return hdd_get_bpf_offload(hdd_ctx);
7129 else
7130 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307131 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307132}
7133
7134/**
7135 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7136 * @wiphy: wiphy structure pointer
7137 * @wdev: Wireless device structure pointer
7138 * @data: Pointer to the data received
7139 * @data_len: Length of @data
7140 *
7141 * Return: 0 on success; errno on failure
7142 */
7143
7144static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7145 struct wireless_dev *wdev,
7146 const void *data, int data_len)
7147{
7148 int ret;
7149
7150 cds_ssr_protect(__func__);
7151 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7152 cds_ssr_unprotect(__func__);
7153
7154 return ret;
7155}
7156
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307157/**
7158 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7159 * @pre_cac_adapter: AP adapter used for pre cac
7160 * @status: Status (true or false)
7161 * @handle: Global handle
7162 *
7163 * Sets the status of pre cac i.e., whether the pre cac is active or not
7164 *
7165 * Return: Zero on success, non-zero on failure
7166 */
7167static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7168 bool status, tHalHandle handle)
7169{
7170 QDF_STATUS ret;
7171
7172 ret = wlan_sap_set_pre_cac_status(
7173 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7174 if (QDF_IS_STATUS_ERROR(ret))
7175 return -EINVAL;
7176
7177 return 0;
7178}
7179
7180/**
7181 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7182 * @ap_adapter: AP adapter
7183 * @chan_before_pre_cac: Channel
7184 *
7185 * Saves the channel which the AP was beaconing on before moving to the pre
7186 * cac channel. If radar is detected on the pre cac channel, this saved
7187 * channel will be used for AP operations.
7188 *
7189 * Return: Zero on success, non-zero on failure
7190 */
7191static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7192 uint8_t chan_before_pre_cac)
7193{
7194 QDF_STATUS ret;
7195
7196 ret = wlan_sap_set_chan_before_pre_cac(
7197 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7198 if (QDF_IS_STATUS_ERROR(ret))
7199 return -EINVAL;
7200
7201 return 0;
7202}
7203
7204/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307205 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7206 * are in nol list from provided channel list
7207 * @adapter: AP adapter
7208 * @channel_count: channel count
7209 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307210 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307211 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307212 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307213static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7214 uint32_t *channel_count,
7215 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307216{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307217 uint8_t i, j;
7218 uint32_t nol_len = 0;
7219 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7220 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7221 uint32_t chan_count;
7222 bool found;
7223 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307224
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307225 if (!hdd_ctx) {
7226 hdd_err("hdd ctx not found");
7227 *channel_count = 0;
7228 return;
7229 }
7230
7231 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7232 hdd_err("invalid channel count %d", *channel_count);
7233 return;
7234 }
7235
7236 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7237 if (nol_len == 0)
7238 return;
7239
7240 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7241 chan_count = *channel_count;
7242 qdf_mem_zero(channel_list, chan_count);
7243 *channel_count = 0;
7244
7245 for (i = 0 ; i < chan_count; i++) {
7246 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7247 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7248 continue;
7249 found = false;
7250 for (j = 0; j < nol_len; j++) {
7251 if (tmp_chan_list[i] == nol[j]) {
7252 found = true;
7253 hdd_notice("skipped channel %d due to nol",
7254 nol[j]);
7255 break;
7256 }
7257 }
7258 if (!found) {
7259 channel_list[*channel_count] = tmp_chan_list[i];
7260 *channel_count = *channel_count + 1;
7261 }
7262 }
7263}
7264
7265int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7266 uint32_t *channel_count,
7267 uint8_t *channel_list)
7268{
7269 tsap_Config_t *sap_config;
7270
7271 sap_config = &adapter->sessionCtx.ap.sapConfig;
7272
7273 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7274 sap_config->acs_cfg.ch_list_count);
7275 *channel_count = sap_config->acs_cfg.ch_list_count;
7276 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7277
7278 if (*channel_count == 0) {
7279 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307280 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307281 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307282
7283 return 0;
7284}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307285
7286/**
7287 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7288 * @hdd_ctx: HDD context
7289 * @ap_adapter: AP adapter
7290 * @channel: Channel requested by userspace
7291 * @pre_cac_chan: Pointer to the pre CAC channel
7292 *
7293 * Validates the channel provided by userspace. If user provided channel 0,
7294 * a valid outdoor channel must be selected from the regulatory channel.
7295 *
7296 * Return: Zero on success and non zero value on error
7297 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007298static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7299 hdd_adapter_t *ap_adapter,
7300 uint8_t channel,
7301 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307302{
7303 uint32_t i, j;
7304 QDF_STATUS status;
7305 int ret;
7306 uint8_t nol[QDF_MAX_NUM_CHAN];
7307 uint32_t nol_len = 0, weight_len = 0;
7308 bool found;
7309 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7310 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7311 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7312
7313 if (0 == channel) {
7314 /* Channel is not obtained from PCL because PCL may not have
7315 * the entire channel list. For example: if SAP is up on
7316 * channel 6 and PCL is queried for the next SAP interface,
7317 * if SCC is preferred, the PCL will contain only the channel
7318 * 6. But, we are in need of a DFS channel. So, going with the
7319 * first channel from the valid channel list.
7320 */
7321 status = cds_get_valid_chans(channel_list, &len);
7322 if (QDF_IS_STATUS_ERROR(status)) {
7323 hdd_err("Failed to get channel list");
7324 return -EINVAL;
7325 }
7326 cds_update_with_safe_channel_list(channel_list, &len,
7327 pcl_weights, weight_len);
7328 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7329 for (i = 0; i < len; i++) {
7330 found = false;
7331 for (j = 0; j < nol_len; j++) {
7332 if (channel_list[i] == nol[j]) {
7333 found = true;
7334 break;
7335 }
7336 }
7337 if (found)
7338 continue;
7339 if (CDS_IS_DFS_CH(channel_list[i])) {
7340 *pre_cac_chan = channel_list[i];
7341 break;
7342 }
7343 }
7344 if (*pre_cac_chan == 0) {
7345 hdd_err("unable to find outdoor channel");
7346 return -EINVAL;
7347 }
7348 } else {
7349 /* Only when driver selects a channel, check is done for
7350 * unnsafe and NOL channels. When user provides a fixed channel
7351 * the user is expected to take care of this.
7352 */
7353 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7354 !CDS_IS_DFS_CH(channel)) {
7355 hdd_err("Invalid channel for pre cac:%d", channel);
7356 return -EINVAL;
7357 } else {
7358 *pre_cac_chan = channel;
7359 }
7360 }
7361 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
7362 return 0;
7363}
7364
7365/**
7366 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7367 * @channel: Channel option provided by userspace
7368 *
7369 * Sets the driver to the required hardware mode and start an adapater for
7370 * pre CAC which will mimic an AP.
7371 *
7372 * Return: Zero on success, non-zero value on error
7373 */
7374int wlan_hdd_request_pre_cac(uint8_t channel)
7375{
Krunal Sonib37bb352016-12-20 14:12:21 -08007376 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307377 hdd_context_t *hdd_ctx;
7378 int ret;
7379 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7380 hdd_ap_ctx_t *hdd_ap_ctx;
7381 QDF_STATUS status;
7382 struct wiphy *wiphy;
7383 struct net_device *dev;
7384 struct cfg80211_chan_def chandef;
7385 enum nl80211_channel_type channel_type;
7386 uint32_t freq;
7387 struct ieee80211_channel *chan;
7388 tHalHandle handle;
7389 bool val;
7390
7391 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7392 if (0 != wlan_hdd_validate_context(hdd_ctx))
7393 return -EINVAL;
7394
7395 if (cds_get_connection_count() > 1) {
7396 hdd_err("pre cac not allowed in concurrency");
7397 return -EINVAL;
7398 }
7399
7400 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7401 if (!ap_adapter) {
7402 hdd_err("unable to get SAP adapter");
7403 return -EINVAL;
7404 }
7405
7406 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7407 if (!handle) {
7408 hdd_err("Invalid handle");
7409 return -EINVAL;
7410 }
7411
7412 val = wlan_sap_is_pre_cac_active(handle);
7413 if (val) {
7414 hdd_err("pre cac is already in progress");
7415 return -EINVAL;
7416 }
7417
7418 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7419 if (!hdd_ap_ctx) {
7420 hdd_err("SAP context is NULL");
7421 return -EINVAL;
7422 }
7423
7424 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7425 hdd_err("SAP is already on DFS channel:%d",
7426 hdd_ap_ctx->operatingChannel);
7427 return -EINVAL;
7428 }
7429
7430 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7431 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7432 hdd_ap_ctx->operatingChannel);
7433 return -EINVAL;
7434 }
7435
Krunal Sonib37bb352016-12-20 14:12:21 -08007436 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7437 if (!mac_addr) {
7438 hdd_err("can't add virtual intf: Not getting valid mac addr");
7439 return -EINVAL;
7440 }
7441
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307442 hdd_info("channel:%d", channel);
7443
7444 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7445 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007446 if (ret != 0) {
7447 hdd_err("can't validate pre-cac channel");
7448 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307449 }
7450
7451 hdd_debug("starting pre cac SAP adapter");
7452
7453 /* Starting a SAP adapter:
7454 * Instead of opening an adapter, we could just do a SME open session
7455 * for AP type. But, start BSS would still need an adapter.
7456 * So, this option is not taken.
7457 *
7458 * hdd open adapter is going to register this precac interface with
7459 * user space. This interface though exposed to user space will be in
7460 * DOWN state. Consideration was done to avoid this registration to the
7461 * user space. But, as part of SAP operations multiple events are sent
7462 * to user space. Some of these events received from unregistered
7463 * interface was causing crashes. So, retaining the registration.
7464 *
7465 * So, this interface would remain registered and will remain in DOWN
7466 * state for the CAC duration. We will add notes in the feature
7467 * announcement to not use this temporary interface for any activity
7468 * from user space.
7469 */
7470 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007471 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307472 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307473 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007474 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307475 }
7476
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307477 /*
7478 * This interface is internally created by the driver. So, no interface
7479 * up comes for this interface from user space and hence starting
7480 * the adapter internally.
7481 */
7482 if (hdd_start_adapter(pre_cac_adapter)) {
7483 hdd_err("error starting the pre cac adapter");
7484 goto close_pre_cac_adapter;
7485 }
7486
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307487 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7488
7489 wiphy = hdd_ctx->wiphy;
7490 dev = pre_cac_adapter->dev;
7491
7492 /* Since this is only a dummy interface lets us use the IEs from the
7493 * other active SAP interface. In regular scenarios, these IEs would
7494 * come from the user space entity
7495 */
7496 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7497 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7498 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7499 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307500 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307501 }
7502 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7503 ap_adapter->sessionCtx.ap.beacon,
7504 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7505 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7506 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7507 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7508 ap_adapter->sessionCtx.ap.sapConfig.authType;
7509
7510 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7511 * to operate on the same bandwidth as that of the 2.4GHz operations.
7512 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7513 */
7514 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7515 case CH_WIDTH_20MHZ:
7516 channel_type = NL80211_CHAN_HT20;
7517 break;
7518 case CH_WIDTH_40MHZ:
7519 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7520 ap_adapter->sessionCtx.ap.sapConfig.channel)
7521 channel_type = NL80211_CHAN_HT40PLUS;
7522 else
7523 channel_type = NL80211_CHAN_HT40MINUS;
7524 break;
7525 default:
7526 channel_type = NL80211_CHAN_NO_HT;
7527 break;
7528 }
7529
7530 freq = cds_chan_to_freq(pre_cac_chan);
7531 chan = __ieee80211_get_channel(wiphy, freq);
7532 if (!chan) {
7533 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307534 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307535 }
7536
7537 cfg80211_chandef_create(&chandef, chan, channel_type);
7538
7539 hdd_debug("orig width:%d channel_type:%d freq:%d",
7540 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7541 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007542 /*
7543 * Doing update after opening and starting pre-cac adapter will make
7544 * sure that driver won't do hardware mode change if there are any
7545 * initial hick-ups or issues in pre-cac adapter's configuration.
7546 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7547 * connection update should result in DBS mode
7548 */
7549 status = cds_update_and_wait_for_connection_update(
7550 ap_adapter->sessionId,
7551 pre_cac_chan,
7552 SIR_UPDATE_REASON_PRE_CAC);
7553 if (QDF_IS_STATUS_ERROR(status)) {
7554 hdd_err("error in moving to DBS mode");
7555 goto stop_close_pre_cac_adapter;
7556 }
7557
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307558
7559 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7560 if (0 != ret) {
7561 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307562 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307563 }
7564
7565 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7566 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007567 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307568 if (QDF_IS_STATUS_ERROR(status)) {
7569 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307570 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307571 }
7572
7573 /*
7574 * The pre cac status is set here. But, it would not be reset explicitly
7575 * anywhere, since after the pre cac success/failure, the pre cac
7576 * adapter itself would be removed.
7577 */
7578 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7579 if (0 != ret) {
7580 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307581 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307582 }
7583
7584 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7585 hdd_ap_ctx->operatingChannel);
7586 if (0 != ret) {
7587 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307588 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307589 }
7590
7591 ap_adapter->pre_cac_chan = pre_cac_chan;
7592
7593 return 0;
7594
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307595stop_close_pre_cac_adapter:
7596 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307597 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7598 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307599close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307600 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007601release_intf_addr_and_return_failure:
7602 /*
7603 * Release the interface address as the adapter
7604 * failed to start, if you don't release then next
7605 * adapter which is trying to come wouldn't get valid
7606 * mac address. Remember we have limited pool of mac addresses
7607 */
7608 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307609 return -EINVAL;
7610}
7611
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307612/**
7613 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7614 *
7615 * Return: None
7616 */
7617void hdd_init_bpf_completion(void)
7618{
7619 init_completion(&bpf_context.completion);
7620}
7621
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307622static const struct nla_policy
7623wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7624 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7625};
7626
Agrawal Ashish65634612016-08-18 13:24:32 +05307627static const struct nla_policy
7628wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7629 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7630 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7631};
7632
7633/**
7634 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7635 * @wiphy: Pointer to wireless phy
7636 * @wdev: Pointer to wireless device
7637 * @data: Pointer to data
7638 * @data_len: Length of @data
7639 *
7640 * This function parses the incoming NL vendor command data attributes and
7641 * updates the SAP context about channel_hint and DFS mode.
7642 * If channel_hint is set, SAP will choose that channel
7643 * as operating channel.
7644 *
7645 * If DFS mode is enabled, driver will include DFS channels
7646 * in ACS else driver will skip DFS channels.
7647 *
7648 * Return: 0 on success, negative errno on failure
7649 */
7650static int
7651__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7652 struct wireless_dev *wdev,
7653 const void *data, int data_len)
7654{
7655 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7656 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7657 int ret;
7658 struct acs_dfs_policy *acs_policy;
7659 int mode = DFS_MODE_NONE;
7660 int channel_hint = 0;
7661
7662 ENTER_DEV(wdev->netdev);
7663
7664 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7665 hdd_err("Command not allowed in FTM mode");
7666 return -EINVAL;
7667 }
7668
7669 ret = wlan_hdd_validate_context(hdd_ctx);
7670 if (0 != ret)
7671 return ret;
7672
7673 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7674 data, data_len,
7675 wlan_hdd_set_acs_dfs_config_policy)) {
7676 hdd_err("invalid attr");
7677 return -EINVAL;
7678 }
7679
7680 acs_policy = &hdd_ctx->acs_policy;
7681 /*
7682 * SCM sends this attribute to restrict SAP from choosing
7683 * DFS channels from ACS.
7684 */
7685 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7686 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7687
7688 if (!IS_DFS_MODE_VALID(mode)) {
7689 hdd_err("attr acs dfs mode is not valid");
7690 return -EINVAL;
7691 }
7692 acs_policy->acs_dfs_mode = mode;
7693
7694 /*
7695 * SCM sends this attribute to provide an active channel,
7696 * to skip redundant ACS between drivers, and save driver start up time
7697 */
7698 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7699 channel_hint = nla_get_u8(
7700 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7701
7702 if (!IS_CHANNEL_VALID(channel_hint)) {
7703 hdd_err("acs channel is not valid");
7704 return -EINVAL;
7705 }
7706 acs_policy->acs_channel = channel_hint;
7707
7708 return 0;
7709}
7710
7711/**
7712 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7713 * @wiphy: wiphy structure pointer
7714 * @wdev: Wireless device structure pointer
7715 * @data: Pointer to the data received
7716 * @data_len: Length of @data
7717 *
7718 * This function parses the incoming NL vendor command data attributes and
7719 * updates the SAP context about channel_hint and DFS mode.
7720 *
7721 * Return: 0 on success; errno on failure
7722 */
7723static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7724 struct wireless_dev *wdev,
7725 const void *data, int data_len)
7726{
7727 int ret;
7728
7729 cds_ssr_protect(__func__);
7730 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7731 cds_ssr_unprotect(__func__);
7732
7733 return ret;
7734}
7735
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307736/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307737 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7738 * @mode : cfg80211 dfs mode
7739 *
7740 * Return: return csr sta roam dfs mode else return NONE
7741 */
7742static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7743 enum dfs_mode mode)
7744{
7745 switch (mode) {
7746 case DFS_MODE_ENABLE:
7747 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7748 break;
7749 case DFS_MODE_DISABLE:
7750 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7751 break;
7752 case DFS_MODE_DEPRIORITIZE:
7753 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7754 break;
7755 default:
7756 hdd_err("STA Roam policy dfs mode is NONE");
7757 return CSR_STA_ROAM_POLICY_NONE;
7758 }
7759}
7760
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307761/*
7762 * hdd_get_sap_operating_band: Get current operating channel
7763 * for sap.
7764 * @hdd_ctx: hdd context
7765 *
7766 * Return : Corresponding band for SAP operating channel
7767 */
7768uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7769{
7770 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7771 QDF_STATUS status;
7772 hdd_adapter_t *adapter;
7773 uint8_t operating_channel = 0;
7774 uint8_t sap_operating_band = 0;
7775 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7776 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7777 adapter = adapter_node->pAdapter;
7778
7779 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7780 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7781 &next);
7782 adapter_node = next;
7783 continue;
7784 }
7785 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7786 if (IS_24G_CH(operating_channel))
7787 sap_operating_band = eCSR_BAND_24;
7788 else if (IS_5G_CH(operating_channel))
7789 sap_operating_band = eCSR_BAND_5G;
7790 else
7791 sap_operating_band = eCSR_BAND_ALL;
7792 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7793 &next);
bings373b99b2017-01-23 10:35:08 +08007794 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307795 }
7796 return sap_operating_band;
7797}
7798
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307799static const struct nla_policy
7800wlan_hdd_set_sta_roam_config_policy[
7801QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7802 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7803 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7804};
7805
7806/**
7807 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7808 * for station connection or roaming.
7809 * @wiphy: Pointer to wireless phy
7810 * @wdev: Pointer to wireless device
7811 * @data: Pointer to data
7812 * @data_len: Length of @data
7813 *
7814 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7815 * channels needs to be skipped in scanning or not.
7816 * If dfs_mode is disabled, driver will not scan DFS channels.
7817 * If skip_unsafe_channels is set, driver will skip unsafe channels
7818 * in Scanning.
7819 *
7820 * Return: 0 on success, negative errno on failure
7821 */
7822static int
7823__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7824 struct wireless_dev *wdev,
7825 const void *data, int data_len)
7826{
7827 struct net_device *dev = wdev->netdev;
7828 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7829 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7830 struct nlattr *tb[
7831 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7832 int ret;
7833 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7834 enum dfs_mode mode = DFS_MODE_NONE;
7835 bool skip_unsafe_channels = false;
7836 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307837 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307838
7839 ENTER_DEV(dev);
7840
7841 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7842 hdd_err("Command not allowed in FTM mode");
7843 return -EINVAL;
7844 }
7845
7846 ret = wlan_hdd_validate_context(hdd_ctx);
7847 if (0 != ret)
7848 return ret;
7849 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7850 data, data_len,
7851 wlan_hdd_set_sta_roam_config_policy)) {
7852 hdd_err("invalid attr");
7853 return -EINVAL;
7854 }
7855 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7856 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7857 if (!IS_DFS_MODE_VALID(mode)) {
7858 hdd_err("attr sta roam dfs mode policy is not valid");
7859 return -EINVAL;
7860 }
7861
7862 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7863
7864 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7865 skip_unsafe_channels = nla_get_u8(
7866 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307867 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307868 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307869 skip_unsafe_channels, adapter->sessionId,
7870 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307871
7872 if (!QDF_IS_STATUS_SUCCESS(status)) {
7873 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7874 return -EINVAL;
7875 }
7876 return 0;
7877}
7878
7879/**
7880 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7881 * connection and roaming for station.
7882 * @wiphy: wiphy structure pointer
7883 * @wdev: Wireless device structure pointer
7884 * @data: Pointer to the data received
7885 * @data_len: Length of @data
7886 *
7887 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7888 * channels needs to be skipped in scanning or not.
7889 * If dfs_mode is disabled, driver will not scan DFS channels.
7890 * If skip_unsafe_channels is set, driver will skip unsafe channels
7891 * in Scanning.
7892 * Return: 0 on success; errno on failure
7893 */
7894static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7895 struct wireless_dev *wdev,
7896 const void *data, int data_len)
7897{
7898 int ret;
7899
7900 cds_ssr_protect(__func__);
7901 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7902 cds_ssr_unprotect(__func__);
7903
7904 return ret;
7905}
7906
Agrawal Ashish467dde42016-09-08 18:44:22 +05307907#ifdef FEATURE_WLAN_CH_AVOID
7908/**
7909 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7910 * is on unsafe channel.
7911 * @wiphy: wiphy structure pointer
7912 * @wdev: Wireless device structure pointer
7913 * @data: Pointer to the data received
7914 * @data_len: Length of @data
7915 *
7916 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7917 * on any of unsafe channels.
7918 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7919 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7920 *
7921 * Return: 0 on success; errno on failure
7922 */
7923static int
7924__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7925 struct wireless_dev *wdev,
7926 const void *data, int data_len)
7927{
7928 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7929 int ret;
7930 uint16_t unsafe_channel_count;
7931 int unsafe_channel_index;
7932 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7933
7934 ENTER_DEV(wdev->netdev);
7935
7936 if (!qdf_ctx) {
7937 cds_err("qdf_ctx is NULL");
7938 return -EINVAL;
7939 }
7940
7941 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7942 hdd_err("Command not allowed in FTM mode");
7943 return -EINVAL;
7944 }
7945
7946 ret = wlan_hdd_validate_context(hdd_ctx);
7947 if (0 != ret)
7948 return ret;
7949 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7950 &(hdd_ctx->unsafe_channel_count),
7951 sizeof(hdd_ctx->unsafe_channel_list));
7952
7953 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7954 (uint16_t)NUM_CHANNELS);
7955 for (unsafe_channel_index = 0;
7956 unsafe_channel_index < unsafe_channel_count;
7957 unsafe_channel_index++) {
7958 hdd_info("Channel %d is not safe",
7959 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7960 }
7961 hdd_unsafe_channel_restart_sap(hdd_ctx);
7962 return 0;
7963}
7964
7965/**
7966 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7967 * is on unsafe channel.
7968 * @wiphy: wiphy structure pointer
7969 * @wdev: Wireless device structure pointer
7970 * @data: Pointer to the data received
7971 * @data_len: Length of @data
7972 *
7973 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7974 * on any of unsafe channels.
7975 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7976 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7977 *
7978 * Return: 0 on success; errno on failure
7979 */
7980static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7981 struct wireless_dev *wdev,
7982 const void *data, int data_len)
7983{
7984 int ret;
7985
7986 cds_ssr_protect(__func__);
7987 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7988 cds_ssr_unprotect(__func__);
7989
7990 return ret;
7991}
7992
7993#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307994/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307995 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7996 * SAP is on unsafe channel.
7997 * @wiphy: wiphy structure pointer
7998 * @wdev: Wireless device structure pointer
7999 * @data: Pointer to the data received
8000 * @data_len: Length of @data
8001 *
8002 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8003 * driver.
8004 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8005 * will initiate restart of sap.
8006 *
8007 * Return: 0 on success; errno on failure
8008 */
8009static int
8010__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8011 struct wireless_dev *wdev,
8012 const void *data, int data_len)
8013{
8014 struct net_device *ndev = wdev->netdev;
8015 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8016 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8017 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8018 uint8_t config_channel = 0;
8019 hdd_ap_ctx_t *ap_ctx;
8020 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308021 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308022
8023 ENTER();
8024
8025 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008026 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308027 return -EINVAL;
8028 }
8029
8030 ret = wlan_hdd_validate_context(hdd_ctx);
8031 if (0 != ret)
8032 return -EINVAL;
8033
8034 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8035 data, data_len,
8036 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008037 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308038 return -EINVAL;
8039 }
8040
8041 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8042 if (!test_bit(SOFTAP_BSS_STARTED,
8043 &hostapd_adapter->event_flags)) {
8044 hdd_err("SAP is not started yet. Restart sap will be invalid");
8045 return -EINVAL;
8046 }
8047
8048 config_channel =
8049 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8050
8051 if (!((IS_24G_CH(config_channel)) ||
8052 (IS_5G_CH(config_channel)))) {
8053 hdd_err("Channel %d is not valid to restart SAP",
8054 config_channel);
8055 return -ENOTSUPP;
8056 }
8057
8058 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8059 ap_ctx->sapConfig.channel = config_channel;
8060 ap_ctx->sapConfig.ch_params.ch_width =
8061 ap_ctx->sapConfig.ch_width_orig;
8062
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008063 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308064 ap_ctx->sapConfig.sec_ch,
8065 &ap_ctx->sapConfig.ch_params);
8066
8067 cds_restart_sap(hostapd_adapter);
8068 }
8069
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308070 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8071 uint32_t freq_len, i;
8072 uint32_t *freq;
8073 uint8_t chans[QDF_MAX_NUM_CHAN];
8074
8075 hdd_debug("setting mandatory freq/chan list");
8076
8077 freq_len = nla_len(
8078 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8079 sizeof(uint32_t);
8080
8081 if (freq_len > QDF_MAX_NUM_CHAN) {
8082 hdd_err("insufficient space to hold channels");
8083 return -ENOMEM;
8084 }
8085
8086 freq = nla_data(
8087 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8088
8089 hdd_debug("freq_len=%d", freq_len);
8090
8091 for (i = 0; i < freq_len; i++) {
8092 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8093 hdd_debug("freq[%d]=%d", i, freq[i]);
8094 }
8095
8096 status = cds_set_sap_mandatory_channels(chans, freq_len);
8097 if (QDF_IS_STATUS_ERROR(status))
8098 return -EINVAL;
8099 }
8100
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308101 return 0;
8102}
8103
8104/**
8105 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8106 * @wiphy: wiphy structure pointer
8107 * @wdev: Wireless device structure pointer
8108 * @data: Pointer to the data received
8109 * @data_len: Length of @data
8110 *
8111 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8112 * driver.
8113 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8114 * will initiate restart of sap.
8115 *
8116 * Return: 0 on success; errno on failure
8117 */
8118static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8119 struct wireless_dev *wdev,
8120 const void *data, int data_len)
8121{
8122 int ret;
8123
8124 cds_ssr_protect(__func__);
8125 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8126 wdev, data, data_len);
8127 cds_ssr_unprotect(__func__);
8128
8129 return ret;
8130}
8131
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308132#undef BPF_INVALID
8133#undef BPF_SET_RESET
8134#undef BPF_VERSION
8135#undef BPF_ID
8136#undef BPF_PACKET_SIZE
8137#undef BPF_CURRENT_OFFSET
8138#undef BPF_PROGRAM
8139#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308140
8141/**
8142 * define short names for the global vendor params
8143 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8144 */
8145#define PARAM_TOTAL_CMD_EVENT_WAKE \
8146 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8147#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8148 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8149#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8150 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8151#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8152 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8153#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8154 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8155#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8156 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8157#define PARAM_TOTAL_RX_DATA_WAKE \
8158 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8159#define PARAM_RX_UNICAST_CNT \
8160 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8161#define PARAM_RX_MULTICAST_CNT \
8162 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8163#define PARAM_RX_BROADCAST_CNT \
8164 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8165#define PARAM_ICMP_PKT \
8166 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8167#define PARAM_ICMP6_PKT \
8168 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8169#define PARAM_ICMP6_RA \
8170 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8171#define PARAM_ICMP6_NA \
8172 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8173#define PARAM_ICMP6_NS \
8174 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8175#define PARAM_ICMP4_RX_MULTICAST_CNT \
8176 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8177#define PARAM_ICMP6_RX_MULTICAST_CNT \
8178 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8179#define PARAM_OTHER_RX_MULTICAST_CNT \
8180 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308181#define PARAM_RSSI_BREACH_CNT \
8182 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8183#define PARAM_LOW_RSSI_CNT \
8184 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8185#define PARAM_GSCAN_CNT \
8186 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8187#define PARAM_PNO_COMPLETE_CNT \
8188 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8189#define PARAM_PNO_MATCH_CNT \
8190 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8191
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308192
8193
8194/**
8195 * hdd_send_wakelock_stats() - API to send wakelock stats
8196 * @ctx: context to be passed to callback
8197 * @data: data passed to callback
8198 *
8199 * This function is used to send wake lock stats to HAL layer
8200 *
8201 * Return: 0 on success, error number otherwise.
8202 */
8203static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8204 const struct sir_wake_lock_stats *data)
8205{
8206 struct sk_buff *skb;
8207 uint32_t nl_buf_len;
8208 uint32_t total_rx_data_wake, rx_multicast_cnt;
8209 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308210 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308211
8212 ENTER();
8213
8214 nl_buf_len = NLMSG_HDRLEN;
8215 nl_buf_len +=
8216 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8217 (NLMSG_HDRLEN + sizeof(uint32_t));
8218
8219 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8220
8221 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008222 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308223 return -ENOMEM;
8224 }
8225
Jeff Johnson64943bd2016-08-23 13:14:06 -07008226 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308227 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008228 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308229 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008230 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308231 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008232 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308233 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008234 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308235 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008236 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308237 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008238 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308239 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07008240 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
8241 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308242 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308243 hdd_info("wow_rssi_breach_wake_up_count %d",
8244 data->wow_rssi_breach_wake_up_count);
8245 hdd_info("wow_low_rssi_wake_up_count %d",
8246 data->wow_low_rssi_wake_up_count);
8247 hdd_info("wow_gscan_wake_up_count %d",
8248 data->wow_gscan_wake_up_count);
8249 hdd_info("wow_pno_complete_wake_up_count %d",
8250 data->wow_pno_complete_wake_up_count);
8251 hdd_info("wow_pno_match_wake_up_count %d",
8252 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308253
8254 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308255 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308256
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308257 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308258 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308259
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308260 rx_multicast_cnt =
8261 data->wow_ipv4_mcast_wake_up_count +
8262 ipv6_rx_multicast_addr_cnt;
8263
8264 total_rx_data_wake =
8265 data->wow_ucast_wake_up_count +
8266 data->wow_bcast_wake_up_count +
8267 rx_multicast_cnt;
8268
8269 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8270 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8271 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8272 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8273 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8274 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8275 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8276 total_rx_data_wake) ||
8277 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8278 data->wow_ucast_wake_up_count) ||
8279 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8280 rx_multicast_cnt) ||
8281 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8282 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308283 nla_put_u32(skb, PARAM_ICMP_PKT,
8284 data->wow_icmpv4_count) ||
8285 nla_put_u32(skb, PARAM_ICMP6_PKT,
8286 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308287 nla_put_u32(skb, PARAM_ICMP6_RA,
8288 data->wow_ipv6_mcast_ra_stats) ||
8289 nla_put_u32(skb, PARAM_ICMP6_NA,
8290 data->wow_ipv6_mcast_na_stats) ||
8291 nla_put_u32(skb, PARAM_ICMP6_NS,
8292 data->wow_ipv6_mcast_ns_stats) ||
8293 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8294 data->wow_ipv4_mcast_wake_up_count) ||
8295 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8296 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308297 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8298 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8299 data->wow_rssi_breach_wake_up_count) ||
8300 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8301 data->wow_low_rssi_wake_up_count) ||
8302 nla_put_u32(skb, PARAM_GSCAN_CNT,
8303 data->wow_gscan_wake_up_count) ||
8304 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8305 data->wow_pno_complete_wake_up_count) ||
8306 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8307 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008308 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308309 goto nla_put_failure;
8310 }
8311
8312 cfg80211_vendor_cmd_reply(skb);
8313
8314 EXIT();
8315 return 0;
8316
8317nla_put_failure:
8318 kfree_skb(skb);
8319 return -EINVAL;
8320}
8321
8322/**
8323 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8324 * @wiphy: wiphy pointer
8325 * @wdev: pointer to struct wireless_dev
8326 * @data: pointer to incoming NL vendor data
8327 * @data_len: length of @data
8328 *
8329 * This function parses the incoming NL vendor command data attributes and
8330 * invokes the SME Api and blocks on a completion variable.
8331 * WMA copies required data and invokes callback
8332 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8333 *
8334 * Return: 0 on success; error number otherwise.
8335 */
8336static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8337 struct wireless_dev *wdev,
8338 const void *data,
8339 int data_len)
8340{
8341 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8342 int status, ret;
8343 struct sir_wake_lock_stats wake_lock_stats;
8344 QDF_STATUS qdf_status;
8345
8346 ENTER();
8347
8348 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008349 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308350 return -EINVAL;
8351 }
8352
8353 status = wlan_hdd_validate_context(hdd_ctx);
8354 if (0 != status)
8355 return -EINVAL;
8356
8357 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8358 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008359 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308360 return -EINVAL;
8361 }
8362
8363 ret = hdd_send_wakelock_stats(hdd_ctx,
8364 &wake_lock_stats);
8365 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008366 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308367
8368 EXIT();
8369 return ret;
8370}
8371
8372/**
8373 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8374 * @wiphy: wiphy pointer
8375 * @wdev: pointer to struct wireless_dev
8376 * @data: pointer to incoming NL vendor data
8377 * @data_len: length of @data
8378 *
8379 * This function parses the incoming NL vendor command data attributes and
8380 * invokes the SME Api and blocks on a completion variable.
8381 * WMA copies required data and invokes callback
8382 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8383 *
8384 * Return: 0 on success; error number otherwise.
8385 */
8386static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8387 struct wireless_dev *wdev,
8388 const void *data, int data_len)
8389{
8390 int ret;
8391
8392 cds_ssr_protect(__func__);
8393 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8394 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008395 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308396
8397 return ret;
8398}
8399
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308400/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308401 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8402 * @wiphy: wiphy structure pointer
8403 * @wdev: Wireless device structure pointer
8404 * @data: Pointer to the data received
8405 * @data_len: Length of @data
8406 *
8407 * This function reads wmi max bus size and fill in the skb with
8408 * NL attributes and send up the NL event.
8409 * Return: 0 on success; errno on failure
8410 */
8411static int
8412__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8413 struct wireless_dev *wdev,
8414 const void *data, int data_len)
8415{
8416 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8417 int ret_val;
8418 struct sk_buff *skb;
8419 uint32_t nl_buf_len;
8420
8421 ENTER();
8422
8423 ret_val = wlan_hdd_validate_context(hdd_ctx);
8424 if (ret_val)
8425 return ret_val;
8426
8427 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8428 hdd_err("Command not allowed in FTM mode");
8429 return -EINVAL;
8430 }
8431
8432 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
8433
8434 nl_buf_len = NLMSG_HDRLEN;
8435 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8436
8437 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8438 if (!skb) {
8439 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8440 return -ENOMEM;
8441 }
8442
8443 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8444 hdd_ctx->wmi_max_len)) {
8445 hdd_err("nla put failure");
8446 goto nla_put_failure;
8447 }
8448
8449 cfg80211_vendor_cmd_reply(skb);
8450
8451 EXIT();
8452
8453 return 0;
8454
8455nla_put_failure:
8456 kfree_skb(skb);
8457 return -EINVAL;
8458}
8459
8460/**
8461 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8462 * @wiphy: wiphy structure pointer
8463 * @wdev: Wireless device structure pointer
8464 * @data: Pointer to the data received
8465 * @data_len: Length of @data
8466 *
8467 * Return: 0 on success; errno on failure
8468 */
8469static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8470 struct wireless_dev *wdev,
8471 const void *data, int data_len)
8472{
8473 int ret;
8474
8475 cds_ssr_protect(__func__);
8476 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8477 cds_ssr_unprotect(__func__);
8478
8479 return ret;
8480}
8481
8482/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308483 *__wlan_hdd_cfg80211_setband() - set band
8484 * @wiphy: Pointer to wireless phy
8485 * @wdev: Pointer to wireless device
8486 * @data: Pointer to data
8487 * @data_len: Length of @data
8488 *
8489 * Return: 0 on success, negative errno on failure
8490 */
8491static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8492 struct wireless_dev *wdev,
8493 const void *data, int data_len)
8494{
8495 struct net_device *dev = wdev->netdev;
8496 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8497 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8498 int ret;
8499 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8500 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8501
8502 ENTER();
8503
8504 ret = wlan_hdd_validate_context(hdd_ctx);
8505 if (ret)
8506 return ret;
8507
8508 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8509 hdd_err(FL("Invalid ATTR"));
8510 return -EINVAL;
8511 }
8512
8513 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8514 hdd_err(FL("attr SETBAND_VALUE failed"));
8515 return -EINVAL;
8516 }
8517
8518 ret = hdd_set_band(dev,
8519 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8520
8521 EXIT();
8522 return ret;
8523}
8524
8525/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308526 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8527 * @adapter: hdd adapter
8528 * @channel: channel number
8529 *
8530 * return: QDF status based on success or failure
8531 */
8532static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8533 int channel, int chan_bw)
8534{
8535 if (QDF_STATUS_SUCCESS !=
8536 wlan_hdd_validate_operation_channel(adapter, channel))
8537 return QDF_STATUS_E_FAILURE;
8538 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8539 channel,
8540 PHY_SINGLE_CHANNEL_CENTERED))) {
8541 hdd_notice("channel %d is in nol", channel);
8542 return -EINVAL;
8543 }
8544
8545 if ((wlansap_is_channel_leaking_in_nol(
8546 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8547 channel, chan_bw))) {
8548 hdd_notice("channel %d is leaking in nol", channel);
8549 return -EINVAL;
8550 }
8551
8552 return 0;
8553
8554}
8555
Kapil Gupta8878ad92017-02-13 11:56:04 +05308556static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8557 tsap_Config_t *sap_config,
8558 struct hdd_vendor_chan_info *channel_list)
8559{
8560 sap_config->channel = channel_list->pri_ch;
8561
8562 sap_config->ch_params.center_freq_seg0 =
8563 channel_list->vht_seg0_center_ch;
8564 sap_config->ch_params.center_freq_seg1 =
8565 channel_list->vht_seg1_center_ch;
8566
8567 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8568 sap_config->ch_params.ch_width = channel_list->chan_width;
8569 if (sap_config->channel >= 36)
8570 sap_config->ch_width_orig =
8571 hdd_ctx->config->vhtChannelWidth;
8572 else
8573 sap_config->ch_width_orig =
8574 hdd_ctx->config->nChannelBondingMode24GHz ?
8575 eHT_CHANNEL_WIDTH_40MHZ :
8576 eHT_CHANNEL_WIDTH_20MHZ;
8577
8578 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8579 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8580 sap_config->acs_cfg.vht_seg0_center_ch =
8581 channel_list->vht_seg0_center_ch;
8582 sap_config->acs_cfg.vht_seg1_center_ch =
8583 channel_list->vht_seg1_center_ch;
8584 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8585}
8586
8587static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8588 uint8_t channel_cnt,
8589 struct hdd_vendor_chan_info *channel_list)
8590{
8591 tsap_Config_t *sap_config;
8592 hdd_ap_ctx_t *hdd_ap_ctx;
8593 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8594 QDF_STATUS status = QDF_STATUS_SUCCESS;
8595
8596 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8597 sap_config = &adapter->sessionCtx.ap.sapConfig;
8598
8599 if (QDF_TIMER_STATE_RUNNING ==
8600 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8601 ap.vendor_acs_timer)) {
8602 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8603 }
8604
8605 if (channel_list && channel_list->pri_ch == 0) {
8606 /* Check mode, set default channel */
8607 channel_list->pri_ch = 6;
8608 /*
8609 * sap_select_default_oper_chan(hdd_ctx->hHal,
8610 * sap_config->acs_cfg.hw_mode);
8611 */
8612 }
8613
8614 switch (reason) {
8615 /* SAP init case */
8616 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8617 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8618 /* Update Hostapd */
8619 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8620 break;
8621
8622 /* DFS detected on current channel */
8623 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8624 wlan_sap_update_next_channel(
8625 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8626 channel_list->pri_ch,
8627 channel_list->chan_width);
8628 status = sme_update_new_channel_event(
8629 WLAN_HDD_GET_HAL_CTX(adapter),
8630 adapter->sessionId);
8631 break;
8632
8633 /* LTE coex event on current channel */
8634 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8635 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8636 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8637 hdd_ap_ctx->sapConfig.ch_width_orig =
8638 channel_list->chan_width;
8639 hdd_restart_sap(adapter, sap_config->acs_cfg.pri_ch);
8640 break;
8641
8642 default:
8643 hdd_info("invalid reason for timer invoke");
8644 }
8645 qdf_mem_free(channel_list);
8646 EXIT();
8647 return status;
8648}
8649
8650/**
8651 * Define short name for vendor channel set config
8652 */
8653#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8654#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8655#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8656#define SET_CHAN_PRIMARY_CHANNEL \
8657 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8658#define SET_CHAN_SECONDARY_CHANNEL \
8659 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8660#define SET_CHAN_SEG0_CENTER_CHANNEL \
8661 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8662#define SET_CHAN_SEG1_CENTER_CHANNEL \
8663 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8664#define SET_CHAN_CHANNEL_WIDTH \
8665 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8666#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8667
8668/**
8669 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8670 * @channel_list: pointer to hdd_vendor_chan_info
8671 * @reason: channel change reason
8672 * @channel_cnt: channel count
8673 * @data: data
8674 * @data_len: data len
8675 *
8676 * Return: 0 on success, negative errno on failure
8677 */
8678static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8679 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8680 const void *data, int data_len)
8681{
8682 int rem, i = 0;
8683 struct nlattr *tb[SET_CHAN_MAX + 1];
8684 struct nlattr *tb2[SET_CHAN_MAX + 1];
8685 struct nlattr *curr_attr;
8686 struct hdd_vendor_chan_info *channel_list;
8687
8688 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8689 hdd_err("Invalid ATTR");
8690 return -EINVAL;
8691 }
8692
8693 if (tb[SET_CHAN_REASON])
8694 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8695
8696 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8697 *channel_cnt = nla_get_u8(tb[
8698 SET_CHAN_CHANNEL_COUNT]);
8699 hdd_info("channel count %d", *channel_cnt);
8700 }
8701
8702 if (!(*channel_cnt)) {
8703 hdd_err("channel count is %d", *channel_cnt);
8704 return -EINVAL;
8705 }
8706
8707 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8708 (*channel_cnt));
8709
8710 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8711 if (nla_parse(tb2,
8712 SET_CHAN_MAX,
8713 nla_data(curr_attr), nla_len(curr_attr),
8714 NULL)) {
8715 hdd_err("nla_parse failed");
8716 return -EINVAL;
8717 }
8718 /* Parse and Fetch allowed SSID list*/
8719 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8720 channel_list[i].pri_ch =
8721 nla_get_u8(
8722 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8723 }
8724 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8725 channel_list[i].ht_sec_ch =
8726 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8727 }
8728 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8729 channel_list[i].vht_seg0_center_ch =
8730 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8731 }
8732 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8733 channel_list[i].vht_seg1_center_ch =
8734 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8735 }
8736 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8737 channel_list[i].chan_width =
8738 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8739 }
8740 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8741 i, channel_list[i].pri_ch,
8742 channel_list[i].ht_sec_ch,
8743 channel_list[i].vht_seg0_center_ch,
8744 channel_list[i].vht_seg1_center_ch,
8745 channel_list[i].chan_width);
8746 i++;
8747 if (i > *channel_cnt)
8748 break;
8749 }
8750 *chan_list_ptr = channel_list;
8751
8752 return 0;
8753}
8754
8755/**
8756 * Undef short names for vendor set channel configuration
8757 */
8758#undef SET_CHAN_REASON
8759#undef SET_CHAN_CHANNEL_COUNT
8760#undef SET_CHAN_CHAN_LIST
8761#undef SET_CHAN_PRIMARY_CHANNEL
8762#undef SET_CHAN_SECONDARY_CHANNEL
8763#undef SET_CHAN_SEG0_CENTER_CHANNEL
8764#undef SET_CHAN_SEG1_CENTER_CHANNEL
8765#undef SET_CHAN_CHANNEL_WIDTH
8766#undef SET_CHAN_MAX
8767
8768/**
8769 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8770 * @wiphy: Pointer to wireless phy
8771 * @wdev: Pointer to wireless device
8772 * @data: Pointer to data
8773 * @data_len: Length of @data
8774 *
8775 * Return: 0 on success, negative errno on failure
8776 */
8777static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8778 struct wireless_dev *wdev,
8779 const void *data, int data_len)
8780{
8781 int ret_val;
8782 QDF_STATUS qdf_status;
8783 uint8_t channel_cnt = 0, reason = -1;
8784 struct hdd_vendor_chan_info *channel_list = NULL;
8785 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8786 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8787
8788 ENTER();
8789
8790 ret_val = wlan_hdd_validate_context(hdd_ctx);
8791 if (ret_val)
8792 return ret_val;
8793
8794 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8795 hdd_err("Command not allowed in FTM mode");
8796 return -EINVAL;
8797 }
8798
8799 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8800 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8801 else {
8802 hdd_err("already timeout happened for acs");
8803 return -EINVAL;
8804 }
8805
8806 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8807 &channel_cnt, data, data_len);
8808 if (ret_val)
8809 return ret_val;
8810
8811 /* Validate channel to be set */
8812 while (channel_cnt && channel_list) {
8813 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8814 channel_list->pri_ch,
8815 channel_list->chan_width);
8816 if (qdf_status == QDF_STATUS_SUCCESS)
8817 break;
8818 channel_cnt--;
8819 channel_list++;
8820 }
8821 if ((channel_cnt <= 0) || !channel_list) {
8822 hdd_err("no available channel/chanlist %p", channel_list);
8823 return -EINVAL;
8824 }
8825
8826 qdf_status = hdd_update_acs_channel(adapter, reason,
8827 channel_cnt, channel_list);
8828 return qdf_status_to_os_return(qdf_status);
8829}
8830
8831/**
8832 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8833 * @wiphy: Pointer to wireless phy
8834 * @wdev: Pointer to wireless device
8835 * @data: Pointer to data
8836 * @data_len: Length of @data
8837 *
8838 * Return: 0 on success, negative errno on failure
8839 */
8840static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8841 struct wireless_dev *wdev,
8842 const void *data, int data_len)
8843{
8844 int ret;
8845
8846 cds_ssr_protect(__func__);
8847 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8848 data_len);
8849 cds_ssr_protect(__func__);
8850
8851 return ret;
8852}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308853
8854/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308855 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8856 * @wiphy: wiphy structure pointer
8857 * @wdev: Wireless device structure pointer
8858 * @data: Pointer to the data received
8859 * @data_len: Length of @data
8860 *
8861 * Return: 0 on success; errno on failure
8862 */
8863static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8864 struct wireless_dev *wdev,
8865 const void *data, int data_len)
8866{
8867 int ret;
8868
8869 cds_ssr_protect(__func__);
8870 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8871 cds_ssr_unprotect(__func__);
8872
8873 return ret;
8874}
8875
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008876/**
8877 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8878 * @nl80211_value: Vendor command attribute value
8879 * @wmi_value: Pointer to return converted WMI return value
8880 *
8881 * Convert NL80211 vendor command value for SAR limit set to WMI value
8882 * Return: 0 on success, -1 on invalid value
8883 */
8884static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8885 u32 *wmi_value)
8886{
8887 int ret = 0;
8888
8889 switch (nl80211_value) {
8890 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8891 *wmi_value = WMI_SAR_FEATURE_OFF;
8892 break;
8893 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8894 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8895 break;
8896 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8897 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8898 break;
8899 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8900 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8901 break;
8902 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8903 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8904 break;
8905 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8906 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8907 break;
8908 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8909 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8910 break;
8911 default:
8912 ret = -1;
8913 }
8914 return ret;
8915}
8916
8917/**
8918 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8919 * @nl80211_value: Vendor command attribute value
8920 * @wmi_value: Pointer to return converted WMI return value
8921 *
8922 * Convert NL80211 vendor command value for SAR BAND to WMI value
8923 * Return: 0 on success, -1 on invalid value
8924 */
8925static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8926{
8927 int ret = 0;
8928
8929 switch (nl80211_value) {
8930 case NL80211_BAND_2GHZ:
8931 *wmi_value = WMI_SAR_2G_ID;
8932 break;
8933 case NL80211_BAND_5GHZ:
8934 *wmi_value = WMI_SAR_5G_ID;
8935 break;
8936 default:
8937 ret = -1;
8938 }
8939 return ret;
8940}
8941
8942/**
8943 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8944 * @nl80211_value: Vendor command attribute value
8945 * @wmi_value: Pointer to return converted WMI return value
8946 *
8947 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8948 * Return: 0 on success, -1 on invalid value
8949 */
8950static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8951 u32 *wmi_value)
8952{
8953 int ret = 0;
8954
8955 switch (nl80211_value) {
8956 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8957 *wmi_value = WMI_SAR_MOD_CCK;
8958 break;
8959 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8960 *wmi_value = WMI_SAR_MOD_OFDM;
8961 break;
8962 default:
8963 ret = -1;
8964 }
8965 return ret;
8966}
8967
8968
8969/**
8970 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
8971 * @wiphy: Pointer to wireless phy
8972 * @wdev: Pointer to wireless device
8973 * @data: Pointer to data
8974 * @data_len: Length of @data
8975 *
8976 * This function is used to setup Specific Absorption Rate limit specs.
8977 *
8978 * Return: 0 on success, negative errno on failure
8979 */
8980static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
8981 struct wireless_dev *wdev,
8982 const void *data, int data_len)
8983{
8984 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8985 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8986 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8987 *sar_spec_list;
8988 struct sar_limit_cmd_params sar_limit_cmd = {0};
8989 int ret = -EINVAL, i = 0, rem = 0;
8990
8991 ENTER();
8992
8993 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8994 hdd_err("Command not allowed in FTM mode");
8995 return -EPERM;
8996 }
8997
8998 if (wlan_hdd_validate_context(hdd_ctx))
8999 return -EINVAL;
9000
9001 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9002 data, data_len, NULL)) {
9003 hdd_err("Invalid SAR attributes");
9004 return -EINVAL;
9005 }
9006
9007 /* Vendor command manadates all SAR Specs in single call */
9008 sar_limit_cmd.commit_limits = 1;
9009 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9010 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9011 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9012 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9013 &sar_limit_cmd.sar_enable) < 0) {
9014 hdd_err("Invalid SAR Enable attr");
9015 goto fail;
9016 }
9017 }
9018 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
9019
9020 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9021 sar_limit_cmd.num_limit_rows = nla_get_u32(
9022 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
9023 hdd_info("attr sar num_limit_rows %d",
9024 sar_limit_cmd.num_limit_rows);
9025 }
9026 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9027 hdd_err("SAR Spec list exceed supported size");
9028 goto fail;
9029 }
9030 if (sar_limit_cmd.num_limit_rows == 0)
9031 goto send_sar_limits;
9032 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9033 struct sar_limit_cmd_row) *
9034 sar_limit_cmd.num_limit_rows);
9035 if (!sar_limit_cmd.sar_limit_row_list) {
9036 ret = -ENOMEM;
9037 goto fail;
9038 }
9039 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9040 hdd_err("Invalid SAR SPECs list");
9041 goto fail;
9042 }
9043
9044 nla_for_each_nested(sar_spec_list,
9045 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9046 if (i == sar_limit_cmd.num_limit_rows) {
9047 hdd_warn("SAR Cmd has excess SPECs in list");
9048 break;
9049 }
9050
9051 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9052 nla_data(sar_spec_list), nla_len(sar_spec_list),
9053 NULL)) {
9054 hdd_err("nla_parse failed for SAR Spec list");
9055 goto fail;
9056 }
9057 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9058 if (sar_spec[
9059 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9060 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9061 nla_get_u32(sar_spec[
9062 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9063 } else {
9064 hdd_err("SAR Spec does not have power limit value");
9065 goto fail;
9066 }
9067
9068 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9069 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9070 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9071 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9072 < 0) {
9073 hdd_err("Invalid SAR Band attr");
9074 goto fail;
9075 }
9076 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9077 WMI_SAR_BAND_ID_VALID_MASK;
9078 }
9079 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9080 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9081 nla_get_u32(sar_spec[
9082 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9083 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9084 WMI_SAR_CHAIN_ID_VALID_MASK;
9085 }
9086 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9087 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9088 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9089 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9090 < 0) {
9091 hdd_err("Invalid SAR Modulation attr");
9092 goto fail;
9093 }
9094 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9095 WMI_SAR_MOD_ID_VALID_MASK;
9096 }
9097 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
9098 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9099 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9100 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9101 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9102 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9103 i++;
9104 }
9105
9106 if (i < sar_limit_cmd.num_limit_rows) {
9107 hdd_warn("SAR Cmd has less SPECs in list");
9108 sar_limit_cmd.num_limit_rows = i;
9109 }
9110
9111send_sar_limits:
9112 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9113 QDF_STATUS_SUCCESS)
9114 ret = 0;
9115fail:
9116 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9117 return ret;
9118}
9119
9120/**
9121 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9122 * @wiphy: Pointer to wireless phy
9123 * @wdev: Pointer to wireless device
9124 * @data: Pointer to data
9125 * @data_len: Length of @data
9126 *
9127 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9128 *
9129 * Return: 0 on success, negative errno on failure
9130 */
9131static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9132 struct wireless_dev *wdev,
9133 const void *data,
9134 int data_len)
9135{
9136 int ret;
9137
9138 cds_ssr_protect(__func__);
9139 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9140 data_len);
9141 cds_ssr_unprotect(__func__);
9142
9143 return ret;
9144}
9145
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309146static const struct
9147nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9148 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9149 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9150 .len = QDF_MAC_ADDR_SIZE},
9151};
9152
9153/**
9154 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9155 * @wiphy: Pointer to wireless phy
9156 * @wdev: Pointer to wireless device
9157 * @data: Pointer to data
9158 * @data_len: Length of @data
9159 *
9160 * This function is used to enable/disable roaming using vendor commands
9161 *
9162 * Return: 0 on success, negative errno on failure
9163 */
9164static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9165 struct wireless_dev *wdev,
9166 const void *data, int data_len)
9167{
9168 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9169 struct net_device *dev = wdev->netdev;
9170 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9171 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9172 uint32_t is_fast_roam_enabled;
9173 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309174 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309175
9176 ENTER_DEV(dev);
9177
9178 ret = wlan_hdd_validate_context(hdd_ctx);
9179 if (0 != ret)
9180 return ret;
9181
9182 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9183 hdd_err("Command not allowed in FTM mode");
9184 return -EINVAL;
9185 }
9186
9187 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9188 qca_wlan_vendor_attr);
9189 if (ret) {
9190 hdd_err("Invalid ATTR");
9191 return -EINVAL;
9192 }
9193
9194 /* Parse and fetch Enable flag */
9195 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9196 hdd_err("attr enable failed");
9197 return -EINVAL;
9198 }
9199
9200 is_fast_roam_enabled = nla_get_u32(
9201 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009202 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
9203 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309204
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009205 if (!adapter->fast_roaming_allowed) {
9206 hdd_err("fast roaming not allowed on %s interface",
9207 adapter->dev->name);
9208 return -EINVAL;
9209 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309210 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309211 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009212 (is_fast_roam_enabled &&
9213 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309214 if (qdf_status != QDF_STATUS_SUCCESS)
9215 hdd_err("sme_config_fast_roaming failed with status=%d",
9216 qdf_status);
9217 ret = qdf_status_to_os_return(qdf_status);
9218
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309219 EXIT();
9220 return ret;
9221}
9222
9223/**
9224 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9225 * @wiphy: Pointer to wireless phy
9226 * @wdev: Pointer to wireless device
9227 * @data: Pointer to data
9228 * @data_len: Length of @data
9229 *
9230 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9231 *
9232 * Return: 0 on success, negative errno on failure
9233 */
9234static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9235 struct wireless_dev *wdev,
9236 const void *data, int data_len)
9237{
9238 int ret;
9239
9240 cds_ssr_protect(__func__);
9241 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9242 cds_ssr_unprotect(__func__);
9243
9244 return ret;
9245}
9246
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309247static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9248 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9249 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9250 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9251 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9252};
9253
9254/**
9255 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9256 * @wiphy: Pointer to wireless phy
9257 * @wdev: Pointer to wireless device
9258 * @data: Pointer to data
9259 * @data_len: Length of @data
9260 *
9261 * Return: 0 on success, negative errno on failure
9262 */
9263static int
9264__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9265 struct wireless_dev *wdev,
9266 const void *data,
9267 int data_len)
9268{
9269 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9270 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9271 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9272 struct nlattr *apth;
9273 int rem;
9274 int ret = 1;
9275 int print_idx = -1;
9276 int module_id = -1;
9277 int bit_mask = -1;
9278 int status;
9279
9280 ENTER();
9281
9282 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9283 hdd_err("Command not allowed in FTM mode");
9284 return -EINVAL;
9285 }
9286
9287 ret = wlan_hdd_validate_context(hdd_ctx);
9288 if (ret != 0)
9289 return -EINVAL;
9290
9291 print_idx = qdf_get_pidx();
9292 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9293 hdd_err("Invalid print controle object index");
9294 return -EINVAL;
9295 }
9296
9297 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9298 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9299 hdd_err("Invalid attr");
9300 return -EINVAL;
9301 }
9302
9303 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9304 hdd_err("attr trace level param failed");
9305 return -EINVAL;
9306 }
9307
9308 nla_for_each_nested(apth,
9309 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9310 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9311 nla_data(apth), nla_len(apth), NULL)) {
9312 hdd_err("Invalid attr");
9313 return -EINVAL;
9314 }
9315
9316 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9317 hdd_err("attr Module ID failed");
9318 return -EINVAL;
9319 }
9320 module_id = nla_get_u32
9321 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9322
9323 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9324 hdd_err("attr Verbose mask failed");
9325 return -EINVAL;
9326 }
9327 bit_mask = nla_get_u32
9328 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9329
9330 status = hdd_qdf_trace_enable(module_id, bit_mask);
9331
9332 if (status != 0)
9333 hdd_err("can not set verbose mask %d for the category %d",
9334 bit_mask, module_id);
9335 }
9336
9337 EXIT();
9338 return ret;
9339}
9340
9341/**
9342 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9343 * @wiphy: Pointer to wireless phy
9344 * @wdev: Pointer to wireless device
9345 * @data: Pointer to data
9346 * @data_len: Length of @data
9347 *
9348 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9349 *
9350 * Return: 0 on success, negative errno on failure
9351 */
9352
9353static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9354 struct wireless_dev *wdev,
9355 const void *data,
9356 int data_len)
9357{
9358 int ret;
9359
9360 cds_ssr_protect(__func__);
9361 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9362 cds_ssr_unprotect(__func__);
9363
9364 return ret;
9365}
9366
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009367const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9368 {
9369 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9370 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9371 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309372 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009373 .doit = is_driver_dfs_capable
9374 },
9375
9376#ifdef WLAN_FEATURE_NAN
9377 {
9378 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9379 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9380 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9381 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9382 .doit = wlan_hdd_cfg80211_nan_request
9383 },
9384#endif
9385
9386#ifdef WLAN_FEATURE_STATS_EXT
9387 {
9388 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9389 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9390 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9391 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9392 .doit = wlan_hdd_cfg80211_stats_ext_request
9393 },
9394#endif
9395#ifdef FEATURE_WLAN_EXTSCAN
9396 {
9397 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9398 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9399 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9400 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9401 .doit = wlan_hdd_cfg80211_extscan_start
9402 },
9403 {
9404 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9405 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9406 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9407 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9408 .doit = wlan_hdd_cfg80211_extscan_stop
9409 },
9410 {
9411 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9412 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9413 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9414 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9415 },
9416 {
9417 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9418 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9419 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9420 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9421 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9422 },
9423 {
9424 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9425 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9426 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9427 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9428 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9429 },
9430 {
9431 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9432 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9433 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9434 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9435 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9436 },
9437 {
9438 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9439 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9440 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9441 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9442 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9443 },
9444 {
9445 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9446 .info.subcmd =
9447 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9448 .flags =
9449 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9450 WIPHY_VENDOR_CMD_NEED_RUNNING,
9451 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9452 },
9453 {
9454 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9455 .info.subcmd =
9456 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9457 .flags =
9458 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9459 WIPHY_VENDOR_CMD_NEED_RUNNING,
9460 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9461 },
9462 {
9463 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9464 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9465 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9466 WIPHY_VENDOR_CMD_NEED_NETDEV |
9467 WIPHY_VENDOR_CMD_NEED_RUNNING,
9468 .doit = wlan_hdd_cfg80211_set_epno_list
9469 },
9470#endif /* FEATURE_WLAN_EXTSCAN */
9471
9472#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9473 {
9474 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9475 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9476 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9477 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9478 .doit = wlan_hdd_cfg80211_ll_stats_clear
9479 },
9480
9481 {
9482 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9483 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9484 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9485 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9486 .doit = wlan_hdd_cfg80211_ll_stats_set
9487 },
9488
9489 {
9490 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9491 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9492 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9493 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9494 .doit = wlan_hdd_cfg80211_ll_stats_get
9495 },
9496#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9497#ifdef FEATURE_WLAN_TDLS
9498 {
9499 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9500 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9501 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9502 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9503 .doit = wlan_hdd_cfg80211_exttdls_enable
9504 },
9505 {
9506 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9507 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9508 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9509 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9510 .doit = wlan_hdd_cfg80211_exttdls_disable
9511 },
9512 {
9513 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9514 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9515 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9516 .doit = wlan_hdd_cfg80211_exttdls_get_status
9517 },
9518#endif
9519 {
9520 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9521 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9522 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9523 .doit = wlan_hdd_cfg80211_get_supported_features
9524 },
9525 {
9526 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9527 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9528 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9529 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9530 },
9531 {
9532 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9533 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9534 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309535 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009536 },
9537 {
9538 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9539 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9540 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9541 WIPHY_VENDOR_CMD_NEED_NETDEV,
9542 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9543 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009544 {
9545 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9546 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9547 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9548 WIPHY_VENDOR_CMD_NEED_NETDEV,
9549 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9550 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009551 {
9552 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309553 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9554 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9555 WIPHY_VENDOR_CMD_NEED_NETDEV |
9556 WIPHY_VENDOR_CMD_NEED_RUNNING,
9557 .doit = hdd_cfg80211_get_station_cmd
9558 },
9559 {
9560 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009561 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9562 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9563 WIPHY_VENDOR_CMD_NEED_NETDEV |
9564 WIPHY_VENDOR_CMD_NEED_RUNNING,
9565 .doit = wlan_hdd_cfg80211_do_acs
9566 },
9567
9568 {
9569 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9570 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9571 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9572 WIPHY_VENDOR_CMD_NEED_NETDEV,
9573 .doit = wlan_hdd_cfg80211_get_features
9574 },
9575#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9576 {
9577 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9578 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9579 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9580 WIPHY_VENDOR_CMD_NEED_NETDEV |
9581 WIPHY_VENDOR_CMD_NEED_RUNNING,
9582 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9583 },
9584#endif
9585#ifdef FEATURE_WLAN_EXTSCAN
9586 {
9587 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9588 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9589 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9590 WIPHY_VENDOR_CMD_NEED_NETDEV |
9591 WIPHY_VENDOR_CMD_NEED_RUNNING,
9592 .doit = wlan_hdd_cfg80211_set_passpoint_list
9593 },
9594 {
9595 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9596 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9597 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9598 WIPHY_VENDOR_CMD_NEED_NETDEV |
9599 WIPHY_VENDOR_CMD_NEED_RUNNING,
9600 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9601 },
9602 {
9603 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9604 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
9605 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9606 WIPHY_VENDOR_CMD_NEED_NETDEV |
9607 WIPHY_VENDOR_CMD_NEED_RUNNING,
9608 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
9609 },
9610 {
9611 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9612 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
9613 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9614 WIPHY_VENDOR_CMD_NEED_NETDEV |
9615 WIPHY_VENDOR_CMD_NEED_RUNNING,
9616 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
9617 },
9618#endif /* FEATURE_WLAN_EXTSCAN */
9619 {
9620 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9621 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9622 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9623 WIPHY_VENDOR_CMD_NEED_NETDEV,
9624 .doit = wlan_hdd_cfg80211_get_wifi_info
9625 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009626#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009627 {
9628 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9629 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9630 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9631 WIPHY_VENDOR_CMD_NEED_NETDEV |
9632 WIPHY_VENDOR_CMD_NEED_RUNNING,
9633 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9634 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009635#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009636 {
9637 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9638 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9639 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9640 WIPHY_VENDOR_CMD_NEED_NETDEV,
9641 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9642 },
9643 {
9644 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9645 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9646 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9647 WIPHY_VENDOR_CMD_NEED_NETDEV,
9648 .doit = wlan_hdd_cfg80211_wifi_logger_start
9649 },
9650 {
9651 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9652 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9653 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9654 WIPHY_VENDOR_CMD_NEED_NETDEV,
9655 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9656 },
9657 {
9658 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9659 .info.subcmd =
9660 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9661 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9662 WIPHY_VENDOR_CMD_NEED_NETDEV |
9663 WIPHY_VENDOR_CMD_NEED_RUNNING,
9664 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9665 },
9666 {
9667 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9668 .info.subcmd =
9669 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9670 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9671 WIPHY_VENDOR_CMD_NEED_NETDEV |
9672 WIPHY_VENDOR_CMD_NEED_RUNNING,
9673 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9674 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009675#ifdef WLAN_FEATURE_TSF
9676 {
9677 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9678 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9679 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9680 WIPHY_VENDOR_CMD_NEED_NETDEV |
9681 WIPHY_VENDOR_CMD_NEED_RUNNING,
9682 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9683 },
9684#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009685#ifdef FEATURE_WLAN_TDLS
9686 {
9687 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9688 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9689 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9690 WIPHY_VENDOR_CMD_NEED_NETDEV |
9691 WIPHY_VENDOR_CMD_NEED_RUNNING,
9692 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9693 },
9694#endif
9695#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9696 {
9697 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9698 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9699 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9700 WIPHY_VENDOR_CMD_NEED_NETDEV |
9701 WIPHY_VENDOR_CMD_NEED_RUNNING,
9702 .doit = wlan_hdd_cfg80211_offloaded_packets
9703 },
9704#endif
9705 {
9706 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9707 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9708 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9709 WIPHY_VENDOR_CMD_NEED_NETDEV |
9710 WIPHY_VENDOR_CMD_NEED_RUNNING,
9711 .doit = wlan_hdd_cfg80211_monitor_rssi
9712 },
9713 {
9714 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309715 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9716 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9717 WIPHY_VENDOR_CMD_NEED_NETDEV |
9718 WIPHY_VENDOR_CMD_NEED_RUNNING,
9719 .doit = wlan_hdd_cfg80211_set_ns_offload
9720 },
9721 {
9722 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009723 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9724 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9725 WIPHY_VENDOR_CMD_NEED_NETDEV |
9726 WIPHY_VENDOR_CMD_NEED_RUNNING,
9727 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9728 },
9729#ifdef WLAN_FEATURE_MEMDUMP
9730 {
9731 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9732 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9733 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9734 WIPHY_VENDOR_CMD_NEED_NETDEV |
9735 WIPHY_VENDOR_CMD_NEED_RUNNING,
9736 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9737 },
9738#endif /* WLAN_FEATURE_MEMDUMP */
9739 {
9740 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9741 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9742 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9743 WIPHY_VENDOR_CMD_NEED_NETDEV |
9744 WIPHY_VENDOR_CMD_NEED_RUNNING,
9745 .doit = wlan_hdd_cfg80211_vendor_scan
9746 },
9747
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309748 /* Vendor abort scan */
9749 {
9750 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9751 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9752 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9753 WIPHY_VENDOR_CMD_NEED_NETDEV |
9754 WIPHY_VENDOR_CMD_NEED_RUNNING,
9755 .doit = wlan_hdd_vendor_abort_scan
9756 },
9757
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009758 /* OCB commands */
9759 {
9760 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9761 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9762 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9763 WIPHY_VENDOR_CMD_NEED_NETDEV |
9764 WIPHY_VENDOR_CMD_NEED_RUNNING,
9765 .doit = wlan_hdd_cfg80211_ocb_set_config
9766 },
9767 {
9768 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9769 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9770 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9771 WIPHY_VENDOR_CMD_NEED_NETDEV |
9772 WIPHY_VENDOR_CMD_NEED_RUNNING,
9773 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9774 },
9775 {
9776 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9777 .info.subcmd =
9778 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9779 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9780 WIPHY_VENDOR_CMD_NEED_NETDEV |
9781 WIPHY_VENDOR_CMD_NEED_RUNNING,
9782 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9783 },
9784 {
9785 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9786 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9787 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9788 WIPHY_VENDOR_CMD_NEED_NETDEV |
9789 WIPHY_VENDOR_CMD_NEED_RUNNING,
9790 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9791 },
9792 {
9793 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9794 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9795 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9796 WIPHY_VENDOR_CMD_NEED_NETDEV |
9797 WIPHY_VENDOR_CMD_NEED_RUNNING,
9798 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9799 },
9800 {
9801 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9802 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9803 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9804 WIPHY_VENDOR_CMD_NEED_NETDEV |
9805 WIPHY_VENDOR_CMD_NEED_RUNNING,
9806 .doit = wlan_hdd_cfg80211_dcc_get_stats
9807 },
9808 {
9809 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9810 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9811 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9812 WIPHY_VENDOR_CMD_NEED_NETDEV |
9813 WIPHY_VENDOR_CMD_NEED_RUNNING,
9814 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9815 },
9816 {
9817 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9818 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9819 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9820 WIPHY_VENDOR_CMD_NEED_NETDEV |
9821 WIPHY_VENDOR_CMD_NEED_RUNNING,
9822 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9823 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309824 {
9825 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9826 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9827 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9828 WIPHY_VENDOR_CMD_NEED_NETDEV |
9829 WIPHY_VENDOR_CMD_NEED_RUNNING,
9830 .doit = wlan_hdd_cfg80211_get_link_properties
9831 },
Peng Xu278d0122015-09-24 16:34:17 -07009832 {
Peng Xud2220962016-07-11 17:59:17 -07009833 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009834 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9835 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9836 WIPHY_VENDOR_CMD_NEED_NETDEV |
9837 WIPHY_VENDOR_CMD_NEED_RUNNING,
9838 .doit = wlan_hdd_cfg80211_set_ota_test
9839 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009840#ifdef FEATURE_LFR_SUBNET_DETECTION
9841 {
9842 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9843 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9844 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9845 WIPHY_VENDOR_CMD_NEED_NETDEV |
9846 WIPHY_VENDOR_CMD_NEED_RUNNING,
9847 .doit = wlan_hdd_cfg80211_set_gateway_params
9848 },
9849#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009850 {
Peng Xud2220962016-07-11 17:59:17 -07009851 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009852 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9853 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9854 WIPHY_VENDOR_CMD_NEED_NETDEV |
9855 WIPHY_VENDOR_CMD_NEED_RUNNING,
9856 .doit = wlan_hdd_cfg80211_txpower_scale
9857 },
9858 {
9859 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9860 .info.subcmd =
9861 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9862 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9863 WIPHY_VENDOR_CMD_NEED_NETDEV |
9864 WIPHY_VENDOR_CMD_NEED_RUNNING,
9865 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9866 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309867 {
9868 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9869 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9870 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9871 WIPHY_VENDOR_CMD_NEED_NETDEV |
9872 WIPHY_VENDOR_CMD_NEED_RUNNING,
9873 .doit = wlan_hdd_cfg80211_bpf_offload
9874 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309875 {
9876 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309877 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9878 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9879 WIPHY_VENDOR_CMD_NEED_NETDEV |
9880 WIPHY_VENDOR_CMD_NEED_RUNNING,
9881 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9882 },
9883 {
9884 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309885 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9886 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9887 WIPHY_VENDOR_CMD_NEED_NETDEV |
9888 WIPHY_VENDOR_CMD_NEED_RUNNING,
9889 .doit = wlan_hdd_cfg80211_sta_roam_policy
9890 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309891#ifdef FEATURE_WLAN_CH_AVOID
9892 {
9893 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9894 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9895 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9896 WIPHY_VENDOR_CMD_NEED_NETDEV |
9897 WIPHY_VENDOR_CMD_NEED_RUNNING,
9898 .doit = wlan_hdd_cfg80211_avoid_freq
9899 },
9900#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309901 {
9902 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309903 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9904 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9905 WIPHY_VENDOR_CMD_NEED_NETDEV |
9906 WIPHY_VENDOR_CMD_NEED_RUNNING,
9907 .doit = wlan_hdd_cfg80211_sap_configuration_set
9908 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009909 {
Peng Xu4225c152016-07-14 21:18:14 -07009910 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009911 .info.subcmd =
9912 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9913 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9914 WIPHY_VENDOR_CMD_NEED_NETDEV |
9915 WIPHY_VENDOR_CMD_NEED_RUNNING,
9916 .doit = wlan_hdd_cfg80211_p2p_lo_start
9917 },
9918 {
9919 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9920 .info.subcmd =
9921 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9922 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9923 WIPHY_VENDOR_CMD_NEED_NETDEV |
9924 WIPHY_VENDOR_CMD_NEED_RUNNING,
9925 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9926 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309927 {
9928 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9929 .info.subcmd =
9930 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9931 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9932 WIPHY_VENDOR_CMD_NEED_NETDEV |
9933 WIPHY_VENDOR_CMD_NEED_RUNNING,
9934 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9935 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009936#ifdef WLAN_FEATURE_NAN_DATAPATH
9937 {
9938 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9939 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9940 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9941 WIPHY_VENDOR_CMD_NEED_NETDEV |
9942 WIPHY_VENDOR_CMD_NEED_RUNNING,
9943 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9944 },
9945#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309946 {
9947 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9948 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9949 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9950 WIPHY_VENDOR_CMD_NEED_NETDEV |
9951 WIPHY_VENDOR_CMD_NEED_RUNNING,
9952 .doit = wlan_hdd_cfg80211_get_wakelock_stats
9953 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309954 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309955 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9956 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
9957 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9958 WIPHY_VENDOR_CMD_NEED_NETDEV |
9959 WIPHY_VENDOR_CMD_NEED_RUNNING,
9960 .doit = wlan_hdd_cfg80211_get_bus_size
9961 },
9962 {
Kapil Gupta8878ad92017-02-13 11:56:04 +05309963 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9964 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
9965 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9966 WIPHY_VENDOR_CMD_NEED_NETDEV |
9967 WIPHY_VENDOR_CMD_NEED_RUNNING,
9968 .doit = wlan_hdd_cfg80211_update_vendor_channel
9969 },
9970 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309971 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
9972 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9973 WIPHY_VENDOR_CMD_NEED_NETDEV |
9974 WIPHY_VENDOR_CMD_NEED_RUNNING,
9975 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309976 },
9977 {
9978 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9979 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
9980 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9981 WIPHY_VENDOR_CMD_NEED_NETDEV |
9982 WIPHY_VENDOR_CMD_NEED_RUNNING,
9983 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05309984 },
9985#ifdef WLAN_FEATURE_DISA
9986 {
9987 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9988 .info.subcmd =
9989 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
9990 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9991 WIPHY_VENDOR_CMD_NEED_NETDEV |
9992 WIPHY_VENDOR_CMD_NEED_RUNNING,
9993 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
9994 },
9995#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07009996#ifdef FEATURE_WLAN_TDLS
9997 {
9998 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9999 .info.subcmd =
10000 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10001 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10002 WIPHY_VENDOR_CMD_NEED_NETDEV |
10003 WIPHY_VENDOR_CMD_NEED_RUNNING,
10004 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010005 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010006#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010007 {
10008 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10009 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10010 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10011 WIPHY_VENDOR_CMD_NEED_RUNNING,
10012 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10013 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010014 {
10015 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10016 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10017 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10018 WIPHY_VENDOR_CMD_NEED_NETDEV |
10019 WIPHY_VENDOR_CMD_NEED_RUNNING,
10020 .doit = wlan_hdd_cfg80211_set_trace_level
10021 },
10022
Paul Zhang3a210c52016-12-08 10:18:12 +080010023#ifdef WLAN_UMAC_CONVERGENCE
10024 COMMON_VENDOR_COMMANDS
10025#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010026};
10027
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010028#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10029 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10030 defined(FEATURE_WLAN_SCAN_PNO)
10031/**
10032 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10033 * @wiphy: pointer to wiphy
10034 * @config: pointer to config
10035 *
10036 * Return: None
10037 */
10038static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10039 struct hdd_config *config)
10040{
10041 if (config->configPNOScanSupport) {
10042 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10043 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
10044 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
10045 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
10046 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
10047 if (config->max_sched_scan_plan_interval)
10048 wiphy->max_sched_scan_plan_interval =
10049 config->max_sched_scan_plan_interval;
10050 if (config->max_sched_scan_plan_iterations)
10051 wiphy->max_sched_scan_plan_iterations =
10052 config->max_sched_scan_plan_iterations;
10053 }
10054}
10055#else
10056static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10057 struct hdd_config *config)
10058{
10059}
10060#endif
10061
10062
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010063/**
10064 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10065 * @priv_size: Size of the hdd context.
10066 *
10067 * Allocate wiphy context and hdd context.
10068 *
10069 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010070 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010071hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010072{
10073 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010074 hdd_context_t *hdd_ctx;
10075
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010076 ENTER();
10077
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010078 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10079
10080 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010081 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010082 return NULL;
10083 }
10084
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010085 hdd_ctx = wiphy_priv(wiphy);
10086
10087 hdd_ctx->wiphy = wiphy;
10088
10089 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010090}
10091
10092/*
10093 * FUNCTION: wlan_hdd_cfg80211_update_band
10094 * This function is called from the supplicant through a
10095 * private ioctl to change the band value
10096 */
10097int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10098{
10099 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010100 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010101
10102 ENTER();
10103
Dustin Browna30892e2016-10-12 17:28:36 -070010104 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010105
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010106 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010107 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010108
10109 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10110 struct ieee80211_supported_band *band = wiphy->bands[i];
10111
10112 channelEnabledState =
10113 cds_get_channel_state(band->channels[j].
10114 hw_value);
10115
Dustin Browna30892e2016-10-12 17:28:36 -070010116 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010117 /* 5G only */
10118#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10119 /* Enable Social channels for P2P */
10120 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10121 (band->channels[j].center_freq)
10122 && CHANNEL_STATE_ENABLE ==
10123 channelEnabledState)
10124 band->channels[j].flags &=
10125 ~IEEE80211_CHAN_DISABLED;
10126 else
10127#endif
10128 band->channels[j].flags |=
10129 IEEE80211_CHAN_DISABLED;
10130 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010131 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010132 eCSR_BAND_24 == eBand) {
10133 /* 2G only */
10134 band->channels[j].flags |=
10135 IEEE80211_CHAN_DISABLED;
10136 continue;
10137 }
10138
Amar Singhal6842e8f2016-02-23 16:30:32 -080010139 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010140 band->channels[j].flags &=
10141 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010142 }
10143 }
10144 return 0;
10145}
10146
Peng Xuacfdda12017-02-06 16:15:38 -080010147#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010148/*
10149 * FUNCTION: wlan_hdd_cfg80211_init
10150 * This function is called by hdd_wlan_startup()
10151 * during initialization.
10152 * This function is used to initialize and register wiphy structure.
10153 */
10154int wlan_hdd_cfg80211_init(struct device *dev,
10155 struct wiphy *wiphy, struct hdd_config *pCfg)
10156{
10157 int i, j;
10158 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10159
10160 ENTER();
10161
10162 /* Now bind the underlying wlan device with wiphy */
10163 set_wiphy_dev(wiphy, dev);
10164
10165 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010167#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10168 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010169 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010170#else
10171 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010172 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010173#endif
10174
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010175 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10176 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10177 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10178#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10179 | WIPHY_FLAG_4ADDR_STATION
10180#endif
10181 | WIPHY_FLAG_OFFCHAN_TX;
10182
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010183#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10184 wiphy->wowlan = &wowlan_support_cfg80211_init;
10185#else
10186 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10187 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10188 wiphy->wowlan.pattern_min_len = 1;
10189 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10190#endif
10191
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010192 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010193#ifdef FEATURE_WLAN_ESE
10194 || pCfg->isEseIniFeatureEnabled
10195#endif
10196 ) {
10197 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10198 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010199#ifdef FEATURE_WLAN_TDLS
10200 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10201 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10202#endif
10203
10204 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10205
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010206#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10207 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10208#endif
10209
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010210 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010211
10212#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010213 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010214#endif
10215
10216 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010217 * driver can still register regulatory callback and
10218 * it will get regulatory settings in wiphy->band[], but
10219 * driver need to determine what to do with both
10220 * regulatory settings
10221 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010222
10223 wiphy->reg_notifier = hdd_reg_notifier;
10224
10225#if defined QCA_WIFI_FTM
10226}
10227#endif
10228
10229 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10230
10231 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10232
10233 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10234
Arun Khandavallifae92942016-08-01 13:31:08 +053010235 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10236 | BIT(NL80211_IFTYPE_ADHOC)
10237 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10238 | BIT(NL80211_IFTYPE_P2P_GO)
10239 | BIT(NL80211_IFTYPE_AP)
10240 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010241
Arun Khandavallifae92942016-08-01 13:31:08 +053010242 if (pCfg->advertiseConcurrentOperation) {
10243 if (pCfg->enableMCC) {
10244 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010245
Arun Khandavallifae92942016-08-01 13:31:08 +053010246 for (i = 0;
10247 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10248 i++) {
10249 if (!pCfg->allowMCCGODiffBI)
10250 wlan_hdd_iface_combination[i].
10251 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010252 }
10253 }
10254 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010255 ARRAY_SIZE(wlan_hdd_iface_combination);
10256 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010257 }
10258
10259 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010260 * on ini values
10261 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010262 if (!pCfg->ShortGI20MhzEnable) {
10263 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10264 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010265 }
10266
10267 if (!pCfg->ShortGI40MhzEnable) {
10268 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10269 }
10270
10271 if (!pCfg->nChannelBondingMode5GHz) {
10272 wlan_hdd_band_5_ghz.ht_cap.cap &=
10273 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10274 }
10275
Abhishek Singhf512bf32016-05-04 16:47:46 +053010276 /*
10277 * In case of static linked driver at the time of driver unload,
10278 * module exit doesn't happens. Module cleanup helps in cleaning
10279 * of static memory.
10280 * If driver load happens statically, at the time of driver unload,
10281 * wiphy flags don't get reset because of static memory.
10282 * It's better not to store channel in static memory.
10283 */
Dustin Browna30892e2016-10-12 17:28:36 -070010284 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10285 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010286 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010287 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010288 hdd_err("Not enough memory to allocate channels");
10289 return -ENOMEM;
10290 }
Dustin Browna30892e2016-10-12 17:28:36 -070010291 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010292 &hdd_channels_2_4_ghz[0],
10293 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010294 if ((hdd_is_5g_supported(pHddCtx)) &&
10295 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10296 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10297 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10298 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010299 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10300 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010301 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010302 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010303 hdd_err("Not enough memory to allocate channels");
10304 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010305 bands[NL80211_BAND_2GHZ]->channels);
10306 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010307 return -ENOMEM;
10308 }
Dustin Browna30892e2016-10-12 17:28:36 -070010309 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010310 &hdd_channels_5_ghz[0],
10311 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010312 }
10313
Dustin Browna30892e2016-10-12 17:28:36 -070010314 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010315
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010316 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010317 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010318
10319 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10320 struct ieee80211_supported_band *band = wiphy->bands[i];
10321
Dustin Browna30892e2016-10-12 17:28:36 -070010322 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010323 eCSR_BAND_5G == pCfg->nBandCapability) {
10324 /* 5G only */
10325#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10326 /* Enable social channels for P2P */
10327 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10328 (band->channels[j].center_freq))
10329 band->channels[j].flags &=
10330 ~IEEE80211_CHAN_DISABLED;
10331 else
10332#endif
10333 band->channels[j].flags |=
10334 IEEE80211_CHAN_DISABLED;
10335 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010336 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010337 eCSR_BAND_24 == pCfg->nBandCapability) {
10338 /* 2G only */
10339 band->channels[j].flags |=
10340 IEEE80211_CHAN_DISABLED;
10341 continue;
10342 }
10343 }
10344 }
10345 /*Initialise the supported cipher suite details */
10346 wiphy->cipher_suites = hdd_cipher_suites;
10347 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10348
10349 /*signal strength in mBm (100*dBm) */
10350 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10351 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10352
Anurag Chouhan6d760662016-02-20 16:05:43 +053010353 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010354 wiphy->n_vendor_commands =
10355 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10356 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10357
10358 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10359 wiphy->n_vendor_events =
10360 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10361 }
10362
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010363 if (pCfg->enableDFSMasterCap) {
10364 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10365 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010366
10367 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10368
10369#ifdef QCA_HT_2040_COEX
10370 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10371#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010372 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010373 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010374 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010376 EXIT();
10377 return 0;
10378}
10379
Abhishek Singhf512bf32016-05-04 16:47:46 +053010380/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010381 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10382 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010383 *
10384 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010385 * memory allocated in wlan_hdd_cfg80211_init also
10386 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010387 *
10388 * Return: void
10389 */
10390void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10391{
10392 int i;
10393
Dustin Browna30892e2016-10-12 17:28:36 -070010394 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010395 if (NULL != wiphy->bands[i] &&
10396 (NULL != wiphy->bands[i]->channels)) {
10397 qdf_mem_free(wiphy->bands[i]->channels);
10398 wiphy->bands[i]->channels = NULL;
10399 }
10400 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010401 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010402}
10403
Yingying Tang80e15f32016-09-27 18:23:01 +080010404/**
10405 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10406 * @hdd_ctx: HDD context
10407 *
10408 * this function will update capabilities for supported bands
10409 *
10410 * Return: void
10411 */
10412static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10413{
10414 uint32_t val32;
10415 uint16_t val16;
10416 tSirMacHTCapabilityInfo *ht_cap_info;
10417 QDF_STATUS status;
10418
10419 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10420 if (QDF_STATUS_SUCCESS != status) {
10421 hdd_err("could not get HT capability info");
10422 val32 = 0;
10423 }
10424 val16 = (uint16_t)val32;
10425 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10426
10427 if (ht_cap_info->txSTBC == true) {
10428 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10429 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10430 IEEE80211_HT_CAP_TX_STBC;
10431 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10432 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10433 IEEE80211_HT_CAP_TX_STBC;
10434 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010435
10436 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10437 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10438 vht_cap.vht_supported = 0;
10439 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10440 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10441 vht_cap.vht_supported = 0;
10442 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10443 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010444}
10445
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010446/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010447 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010448 * initialization. In wlan_hdd_cfg80211_init, only the
10449 * default values will be initialized. The final initialization
10450 * of all required members can be done here.
10451 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010452void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010453{
Yingying Tang80e15f32016-09-27 18:23:01 +080010454 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10455
10456 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010457}
10458
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010459/**
10460 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10461 * @cfg: hdd cfg
10462 *
10463 * this function update 11n mode in hdd cfg
10464 *
10465 * Return: void
10466 */
10467void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10468{
10469 if (sme_is_feature_supported_by_fw(DOT11AC)) {
10470 hdd_notice("support 11ac");
10471 } else {
10472 hdd_notice("not support 11ac");
10473 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10474 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10475 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10476 cfg->sap_p2p_11ac_override = 0;
10477 }
10478 }
10479}
10480
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010481/* In this function we are registering wiphy. */
10482int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10483{
10484 ENTER();
10485 /* Register our wiphy dev with cfg80211 */
10486 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010487 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010488 return -EIO;
10489 }
10490
10491 EXIT();
10492 return 0;
10493}
10494
10495/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010496 * HDD function to update wiphy capability based on target offload status.
10497 *
10498 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10499 * capability even before downloading firmware to the target. In discrete
10500 * case, host will get know certain offload capability (say sched_scan
10501 * caps) only after downloading firmware to the target and target boots up.
10502 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10503 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010504 */
10505void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10506{
10507#ifdef FEATURE_WLAN_SCAN_PNO
10508 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10509 struct hdd_config *pCfg = pHddCtx->config;
10510
10511 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10512 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010513 * have PNO support.
10514 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010515 if (!pCfg->PnoOffload) {
10516 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10517 wiphy->max_sched_scan_ssids = 0;
10518 wiphy->max_match_sets = 0;
10519 wiphy->max_sched_scan_ie_len = 0;
10520 }
10521#endif
10522}
10523
10524/* This function registers for all frame which supplicant is interested in */
10525void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10526{
10527 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10528 /* Register for all P2P action, public action etc frames */
10529 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10530
10531 ENTER();
10532
Abhishek Singh7996eb72015-12-30 17:24:02 +053010533 /* Register frame indication call back */
10534 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10535
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010536 /* Register for p2p ack indication */
10537 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10538
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010539 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010540 * initialized. Once we will move to 2.6.37 kernel, in which we have
10541 * frame register ops, we will move this code as a part of that
10542 */
10543
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010544 /* GAS Initial Request */
10545 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10546 (uint8_t *) GAS_INITIAL_REQ,
10547 GAS_INITIAL_REQ_SIZE);
10548
10549 /* GAS Initial Response */
10550 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10551 (uint8_t *) GAS_INITIAL_RSP,
10552 GAS_INITIAL_RSP_SIZE);
10553
10554 /* GAS Comeback Request */
10555 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10556 (uint8_t *) GAS_COMEBACK_REQ,
10557 GAS_COMEBACK_REQ_SIZE);
10558
10559 /* GAS Comeback Response */
10560 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10561 (uint8_t *) GAS_COMEBACK_RSP,
10562 GAS_COMEBACK_RSP_SIZE);
10563
10564 /* P2P Public Action */
10565 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10566 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10567 P2P_PUBLIC_ACTION_FRAME_SIZE);
10568
10569 /* P2P Action */
10570 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10571 (uint8_t *) P2P_ACTION_FRAME,
10572 P2P_ACTION_FRAME_SIZE);
10573
10574 /* WNM BSS Transition Request frame */
10575 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10576 (uint8_t *) WNM_BSS_ACTION_FRAME,
10577 WNM_BSS_ACTION_FRAME_SIZE);
10578
10579 /* WNM-Notification */
10580 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10581 (uint8_t *) WNM_NOTIFICATION_FRAME,
10582 WNM_NOTIFICATION_FRAME_SIZE);
10583}
10584
10585void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10586{
10587 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10588 /* Register for all P2P action, public action etc frames */
10589 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10590
10591 ENTER();
10592
10593 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010594 * initialized. Once we will move to 2.6.37 kernel, in which we have
10595 * frame register ops, we will move this code as a part of that
10596 */
10597
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010598 /* GAS Initial Request */
10599
10600 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10601 (uint8_t *) GAS_INITIAL_REQ,
10602 GAS_INITIAL_REQ_SIZE);
10603
10604 /* GAS Initial Response */
10605 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10606 (uint8_t *) GAS_INITIAL_RSP,
10607 GAS_INITIAL_RSP_SIZE);
10608
10609 /* GAS Comeback Request */
10610 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10611 (uint8_t *) GAS_COMEBACK_REQ,
10612 GAS_COMEBACK_REQ_SIZE);
10613
10614 /* GAS Comeback Response */
10615 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10616 (uint8_t *) GAS_COMEBACK_RSP,
10617 GAS_COMEBACK_RSP_SIZE);
10618
10619 /* P2P Public Action */
10620 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10621 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10622 P2P_PUBLIC_ACTION_FRAME_SIZE);
10623
10624 /* P2P Action */
10625 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10626 (uint8_t *) P2P_ACTION_FRAME,
10627 P2P_ACTION_FRAME_SIZE);
10628
10629 /* WNM-Notification */
10630 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10631 (uint8_t *) WNM_NOTIFICATION_FRAME,
10632 WNM_NOTIFICATION_FRAME_SIZE);
10633}
10634
10635#ifdef FEATURE_WLAN_WAPI
10636void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10637 const uint8_t *mac_addr, const uint8_t *key,
10638 int key_Len)
10639{
10640 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10641 tCsrRoamSetKey setKey;
10642 bool isConnected = true;
10643 int status = 0;
10644 uint32_t roamId = 0xFF;
10645 uint8_t *pKeyPtr = NULL;
10646 int n = 0;
10647
Jeff Johnson46b40792016-06-29 14:03:14 -070010648 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010649 hdd_device_mode_to_string(pAdapter->device_mode),
10650 pAdapter->device_mode);
10651
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010652 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010653 setKey.keyId = key_index; /* Store Key ID */
10654 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10655 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10656 setKey.paeRole = 0; /* the PAE role */
10657 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010658 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010659 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010660 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010661 }
10662 setKey.keyLength = key_Len;
10663 pKeyPtr = setKey.Key;
10664 memcpy(pKeyPtr, key, key_Len);
10665
Jeff Johnson46b40792016-06-29 14:03:14 -070010666 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010667 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -070010668 hdd_notice("WAPI KEY Data[%d]:%02x ",
10669 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010670
10671 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10672 if (isConnected) {
10673 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10674 pAdapter->sessionId, &setKey, &roamId);
10675 }
10676 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -070010677 hdd_err("sme_roam_set_key returned ERROR status= %d",
10678 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010679 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10680 }
10681}
10682#endif /* FEATURE_WLAN_WAPI */
10683
10684uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10685 uint8_t eid)
10686{
10687 int left = length;
10688 uint8_t *ptr = (uint8_t *)ies_ptr;
10689 uint8_t elem_id, elem_len;
10690
10691 while (left >= 2) {
10692 elem_id = ptr[0];
10693 elem_len = ptr[1];
10694 left -= 2;
10695 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -070010696 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010697 eid, elem_len, left);
10698 return NULL;
10699 }
10700 if (elem_id == eid) {
10701 return ptr;
10702 }
10703
10704 left -= elem_len;
10705 ptr += (elem_len + 2);
10706 }
10707 return NULL;
10708}
10709
10710/*
10711 * FUNCTION: wlan_hdd_validate_operation_channel
10712 * called by wlan_hdd_cfg80211_start_bss() and
10713 * wlan_hdd_set_channel()
10714 * This function validates whether given channel is part of valid
10715 * channel list.
10716 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010717QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010718 int channel)
10719{
10720
10721 uint32_t num_ch = 0;
10722 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10723 u32 indx = 0;
10724 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10725 uint8_t fValidChannel = false, count = 0;
10726 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10727
10728 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10729
10730 if (hdd_pConfig_ini->sapAllowAllChannel) {
10731 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010732 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010733 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010734 fValidChannel = true;
10735 break;
10736 }
10737 }
10738 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -070010739 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010740 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010741 }
10742 } else {
10743 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10744 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010745 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010746 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010747 }
10748 for (indx = 0; indx < num_ch; indx++) {
10749 if (channel == valid_ch[indx]) {
10750 break;
10751 }
10752 }
10753
10754 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -070010755 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010756 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010757 }
10758 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010759 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010760
10761}
10762
10763#ifdef DHCP_SERVER_OFFLOAD
10764static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10765{
10766 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10767 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10768 uint8_t numEntries = 0;
10769 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10770 uint8_t num;
10771 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010772 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010773 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010774 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010775 return;
10776 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010777 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10778 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10779 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10780 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10781 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10782 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -070010783 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010784 goto end;
10785 }
10786 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010787 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010788 goto end;
10789 }
10790 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -070010791 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010792 goto end;
10793 }
10794 for (num = 0; num < numEntries; num++) {
10795 temp = srv_ip[num];
10796 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10797 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010798 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010799 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010800 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010801 goto end;
10802 }
Jeff Johnson77848112016-06-29 14:52:06 -070010803 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010804end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010805 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010806 return;
10807}
10808#endif /* DHCP_SERVER_OFFLOAD */
10809
10810static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10811 struct net_device *dev,
10812 struct bss_parameters *params)
10813{
10814 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10815 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10816 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010817 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010818
10819 ENTER();
10820
Anurag Chouhan6d760662016-02-20 16:05:43 +053010821 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010822 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010823 return -EINVAL;
10824 }
10825
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010826 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10827 hdd_err("invalid session id: %d", pAdapter->sessionId);
10828 return -EINVAL;
10829 }
10830
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010831 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010832 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10833 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -070010834 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010835 hdd_device_mode_to_string(pAdapter->device_mode),
10836 pAdapter->device_mode, params->ap_isolate);
10837
10838 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10839 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010840 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010841 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010842
Krunal Sonib4326f22016-03-10 13:05:51 -080010843 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10844 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010845 return -EOPNOTSUPP;
10846 }
10847
10848 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010849 * want to update this parameter
10850 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010851 if (-1 != params->ap_isolate) {
10852 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10853 !!params->ap_isolate;
10854
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010855 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856 pAdapter->sessionId,
10857 pAdapter->sessionCtx.
10858 ap.
10859 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010860 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010861 ret = -EINVAL;
10862 }
10863 }
10864
10865 EXIT();
10866 return ret;
10867}
10868
Krunal Soni8c37e322016-02-03 16:08:37 -080010869/**
10870 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10871 * @ndev: pointer to net device provided by supplicant
10872 * @type: type of the interface, upper layer wanted to change
10873 *
10874 * Upper layer provides the new interface mode that needs to be changed
10875 * for given net device
10876 *
10877 * Return: success or failure in terms of integer value
10878 */
10879static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010880 enum nl80211_iftype type)
10881{
Krunal Soni8c37e322016-02-03 16:08:37 -080010882 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10883 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10884 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010885 hdd_wext_state_t *wext;
10886 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010887 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010888
10889 ENTER();
10890
Krunal Soni8c37e322016-02-03 16:08:37 -080010891 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010892 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010893 return 0;
10894 }
10895
10896 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080010897 hdd_stop_adapter(hdd_ctx, adapter, true);
10898 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010899 wdev->iftype = type;
10900 /*Check for sub-string p2p to confirm its a p2p interface */
10901 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080010902 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010903 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010904 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080010905 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080010906 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010907 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080010908 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010909 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010910 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010911 }
Krunal Soni8c37e322016-02-03 16:08:37 -080010912 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
10913 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080010914 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
10915 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010916 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080010917 adapter->scan_info.scanAddIE.length;
10918 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010919 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080010920 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
10921 wext->roamProfile.phyMode =
10922 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
10923 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010924 EXIT();
10925 return status;
10926}
10927
10928static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10929 struct net_device *dev,
10930 struct bss_parameters *params)
10931{
10932 int ret;
10933
10934 cds_ssr_protect(__func__);
10935 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
10936 cds_ssr_unprotect(__func__);
10937
10938 return ret;
10939}
10940
10941/* FUNCTION: wlan_hdd_change_country_code_cd
10942 * to wait for contry code completion
10943 */
10944void *wlan_hdd_change_country_code_cb(void *pAdapter)
10945{
10946 hdd_adapter_t *call_back_pAdapter = pAdapter;
10947 complete(&call_back_pAdapter->change_country_code);
10948 return NULL;
10949}
10950
Rajeev Kumar98edb772016-01-19 12:42:19 -080010951/**
10952 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10953 * @wiphy: Pointer to the wiphy structure
10954 * @ndev: Pointer to the net device
10955 * @type: Interface type
10956 * @flags: Flags for change interface
10957 * @params: Pointer to change interface parameters
10958 *
10959 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960 */
10961static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
10962 struct net_device *ndev,
10963 enum nl80211_iftype type,
10964 u32 *flags,
10965 struct vif_params *params)
10966{
10967 struct wireless_dev *wdev;
10968 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10969 hdd_context_t *pHddCtx;
10970 tCsrRoamProfile *pRoamProfile = NULL;
10971 eCsrRoamBssType LastBSSType;
10972 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010973 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010974 int status;
10975
10976 ENTER();
10977
Anurag Chouhan6d760662016-02-20 16:05:43 +053010978 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010979 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010980 return -EINVAL;
10981 }
10982
10983 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10984 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010985 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010986 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010987
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010988 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010989 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
10990 pAdapter->sessionId, type));
10991
Jeff Johnson77848112016-06-29 14:52:06 -070010992 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010993 pAdapter->device_mode, type);
10994
Arun Khandavallifae92942016-08-01 13:31:08 +053010995 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
10996 if (status) {
10997 hdd_err("Failed to start modules");
10998 return -EINVAL;
10999 }
11000
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011001 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11003 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011004 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011005 return -EINVAL;
11006 }
11007
11008 pConfig = pHddCtx->config;
11009 wdev = ndev->ieee80211_ptr;
11010
11011 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011012 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011013
11014 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
11015
Krunal Sonib4326f22016-03-10 13:05:51 -080011016 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11017 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11018 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11019 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011020 hdd_wext_state_t *pWextState =
11021 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11022
11023 pRoamProfile = &pWextState->roamProfile;
11024 LastBSSType = pRoamProfile->BSSType;
11025
11026 switch (type) {
11027 case NL80211_IFTYPE_STATION:
11028 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011029 case NL80211_IFTYPE_ADHOC:
11030 if (type == NL80211_IFTYPE_ADHOC) {
11031 wlan_hdd_tdls_exit(pAdapter);
11032 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070011033 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011034 }
11035 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11036 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011037 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011038 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011039 if (hdd_start_adapter(pAdapter)) {
11040 hdd_err("Failed to start adapter :%d",
11041 pAdapter->device_mode);
11042 return -EINVAL;
11043 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011044 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011045 case NL80211_IFTYPE_AP:
11046 case NL80211_IFTYPE_P2P_GO:
11047 {
Jeff Johnson77848112016-06-29 14:52:06 -070011048 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011049 (type ==
11050 NL80211_IFTYPE_AP) ? "SoftAP" :
11051 "P2pGo");
11052
11053 /* Cancel any remain on channel for GO mode */
11054 if (NL80211_IFTYPE_P2P_GO == type) {
11055 wlan_hdd_cancel_existing_remain_on_channel
11056 (pAdapter);
11057 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011058
Arun Khandavallifae92942016-08-01 13:31:08 +053011059 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011060 /* De-init the adapter */
11061 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11062 memset(&pAdapter->sessionCtx, 0,
11063 sizeof(pAdapter->sessionCtx));
11064 pAdapter->device_mode =
11065 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011066 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11067 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011068
11069 /*
11070 * Fw will take care incase of concurrency
11071 */
11072
Krunal Sonib4326f22016-03-10 13:05:51 -080011073 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011074 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011075 /* To meet Android requirements create
11076 * a randomized MAC address of the
11077 * form 02:1A:11:Fx:xx:xx
11078 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011079 get_random_bytes(&ndev->dev_addr[3], 3);
11080 ndev->dev_addr[0] = 0x02;
11081 ndev->dev_addr[1] = 0x1A;
11082 ndev->dev_addr[2] = 0x11;
11083 ndev->dev_addr[3] |= 0xF0;
11084 memcpy(pAdapter->macAddressCurrent.
11085 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011086 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011087 pr_info("wlan: Generated HotSpot BSSID "
11088 MAC_ADDRESS_STR "\n",
11089 MAC_ADDR_ARRAY(ndev->dev_addr));
11090 }
11091
11092 hdd_set_ap_ops(pAdapter->dev);
11093
Arun Khandavallifae92942016-08-01 13:31:08 +053011094 if (hdd_start_adapter(pAdapter)) {
11095 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011096 return -EINVAL;
11097 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011098 /* Interface type changed update in wiphy structure */
11099 if (wdev) {
11100 wdev->iftype = type;
11101 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011102 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011103 return -EINVAL;
11104 }
11105 goto done;
11106 }
11107
11108 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011109 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011110 type);
11111 return -EOPNOTSUPP;
11112 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011113 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11114 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011115 switch (type) {
11116 case NL80211_IFTYPE_STATION:
11117 case NL80211_IFTYPE_P2P_CLIENT:
11118 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011119 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11120 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011121 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011122 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011123 if (hdd_start_adapter(pAdapter)) {
11124 hdd_err("Failed to start adapter :%d",
11125 pAdapter->device_mode);
11126 return -EINVAL;
11127 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011128 goto done;
11129
11130 case NL80211_IFTYPE_AP:
11131 case NL80211_IFTYPE_P2P_GO:
11132 wdev->iftype = type;
11133 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011134 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011135 goto done;
11136
11137 default:
Jeff Johnson77848112016-06-29 14:52:06 -070011138 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011139 type);
11140 return -EOPNOTSUPP;
11141 }
11142 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011143 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011144 pAdapter->device_mode);
11145 return -EOPNOTSUPP;
11146 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011147done:
11148 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011149 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011150
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011151 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011152
11153 EXIT();
11154 return 0;
11155}
11156
Rajeev Kumar98edb772016-01-19 12:42:19 -080011157/**
11158 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11159 * @wiphy: Pointer to the wiphy structure
11160 * @ndev: Pointer to the net device
11161 * @type: Interface type
11162 * @flags: Flags for change interface
11163 * @params: Pointer to change interface parameters
11164 *
11165 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011166 */
11167static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11168 struct net_device *ndev,
11169 enum nl80211_iftype type,
11170 u32 *flags,
11171 struct vif_params *params)
11172{
11173 int ret;
11174
11175 cds_ssr_protect(__func__);
11176 ret =
11177 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11178 cds_ssr_unprotect(__func__);
11179
11180 return ret;
11181}
11182
11183#ifdef FEATURE_WLAN_TDLS
11184static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11185 int index, uint8_t match)
11186{
11187 int i;
11188 for (i = 0; i < index; i++) {
11189 if (arr[i] == match)
11190 return true;
11191 }
11192 return false;
11193}
11194#endif
11195
11196/**
11197 * __wlan_hdd_change_station() - change station
11198 * @wiphy: Pointer to the wiphy structure
11199 * @dev: Pointer to the net device.
11200 * @mac: bssid
11201 * @params: Pointer to station parameters
11202 *
11203 * Return: 0 for success, error number on failure.
11204 */
11205#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11206static int __wlan_hdd_change_station(struct wiphy *wiphy,
11207 struct net_device *dev,
11208 const uint8_t *mac,
11209 struct station_parameters *params)
11210#else
11211static int __wlan_hdd_change_station(struct wiphy *wiphy,
11212 struct net_device *dev,
11213 uint8_t *mac,
11214 struct station_parameters *params)
11215#endif
11216{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011217 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011218 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11219 hdd_context_t *pHddCtx;
11220 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011221 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011222#ifdef FEATURE_WLAN_TDLS
11223 tCsrStaParams StaParams = { 0 };
11224 uint8_t isBufSta = 0;
11225 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011226 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011227#endif
11228 int ret;
11229
11230 ENTER();
11231
Anurag Chouhan6d760662016-02-20 16:05:43 +053011232 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011233 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011234 return -EINVAL;
11235 }
11236
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011237 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238 TRACE_CODE_HDD_CHANGE_STATION,
11239 pAdapter->sessionId, params->listen_interval));
11240
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011241 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11242 hdd_err("invalid session id: %d", pAdapter->sessionId);
11243 return -EINVAL;
11244 }
11245
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011246 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11247 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011248 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011249 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250
11251 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11252
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011253 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011254
Krunal Sonib4326f22016-03-10 13:05:51 -080011255 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11256 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011257 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11258 status =
11259 hdd_softap_change_sta_state(pAdapter,
11260 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011261 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011262
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011263 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011264 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011265 return -EINVAL;
11266 }
11267 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011268 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11269 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270#ifdef FEATURE_WLAN_TDLS
11271 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011272
11273 if (cds_is_sub_20_mhz_enabled()) {
11274 hdd_err("TDLS not allowed with sub 20 MHz");
11275 return -EINVAL;
11276 }
11277
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011278 StaParams.capability = params->capability;
11279 StaParams.uapsd_queues = params->uapsd_queues;
11280 StaParams.max_sp = params->max_sp;
11281
11282 /* Convert (first channel , number of channels) tuple to
11283 * the total list of channels. This goes with the assumption
11284 * that if the first channel is < 14, then the next channels
11285 * are an incremental of 1 else an incremental of 4 till the number
11286 * of channels.
11287 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011288 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011289 if (0 != params->supported_channels_len) {
11290 int i = 0, j = 0, k = 0, no_of_channels = 0;
11291 int num_unique_channels;
11292 int next;
11293 for (i = 0;
11294 i < params->supported_channels_len
11295 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11296 int wifi_chan_index;
11297 if (!wlan_hdd_is_duplicate_channel
11298 (StaParams.supported_channels, j,
11299 params->supported_channels[i])) {
11300 StaParams.
11301 supported_channels[j] =
11302 params->
11303 supported_channels[i];
11304 } else {
11305 continue;
11306 }
11307 wifi_chan_index =
11308 ((StaParams.supported_channels[j] <=
11309 HDD_CHANNEL_14) ? 1 : 4);
11310 no_of_channels =
11311 params->supported_channels[i + 1];
11312
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011313 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 -080011314 StaParams.
11315 supported_channels[j],
11316 wifi_chan_index,
11317 no_of_channels);
11318 for (k = 1; k <= no_of_channels &&
11319 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11320 k++) {
11321 next =
11322 StaParams.
11323 supported_channels[j] +
11324 wifi_chan_index;
11325 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11326 StaParams.
11327 supported_channels[j
11328 +
11329 1]
11330 = next;
11331 } else {
11332 continue;
11333 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011334 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011335 j + 1,
11336 StaParams.
11337 supported_channels[j +
11338 1]);
11339 j += 1;
11340 }
11341 }
11342 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011343 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011344 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011345 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011346 StaParams.
11347 supported_channels[i]);
11348 }
11349 if (MAX_CHANNEL < num_unique_channels)
11350 num_unique_channels = MAX_CHANNEL;
11351 StaParams.supported_channels_len =
11352 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011353 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011354 StaParams.supported_channels_len);
11355 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011356 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011357 params->supported_oper_classes,
11358 params->supported_oper_classes_len);
11359 StaParams.supported_oper_classes_len =
11360 params->supported_oper_classes_len;
11361
11362 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011363 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011364 params->ext_capab,
11365 sizeof(StaParams.extn_capability));
11366
11367 if (NULL != params->ht_capa) {
11368 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011369 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011370 sizeof(tSirHTCap));
11371 }
11372
11373 StaParams.supported_rates_len =
11374 params->supported_rates_len;
11375
11376 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11377 * The supported_rates array , for all the structures propogating till Add Sta
11378 * to the firmware has to be modified , if the supplicant (ieee80211) is
11379 * modified to send more rates.
11380 */
11381
11382 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11383 */
11384 if (StaParams.supported_rates_len >
11385 SIR_MAC_MAX_SUPP_RATES)
11386 StaParams.supported_rates_len =
11387 SIR_MAC_MAX_SUPP_RATES;
11388
11389 if (0 != StaParams.supported_rates_len) {
11390 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011391 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011392 params->supported_rates,
11393 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011394 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011395 StaParams.supported_rates_len);
11396 for (i = 0; i < StaParams.supported_rates_len;
11397 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011398 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011399 StaParams.supported_rates[i]);
11400 }
11401
11402 if (NULL != params->vht_capa) {
11403 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011404 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011405 params->vht_capa,
11406 sizeof(tSirVHTCap));
11407 }
11408
11409 if (0 != params->ext_capab_len) {
11410 /*Define A Macro : TODO Sunil */
11411 if ((1 << 4) & StaParams.extn_capability[3]) {
11412 isBufSta = 1;
11413 }
11414 /* TDLS Channel Switching Support */
11415 if ((1 << 6) & StaParams.extn_capability[3]) {
11416 isOffChannelSupported = 1;
11417 }
11418 }
11419
Nitesh Shah99934ac2016-09-05 15:54:08 +053011420 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011421 (params->ht_capa || params->vht_capa ||
11422 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011423 is_qos_wmm_sta = true;
11424
11425 hdd_notice("%s: TDLS Peer is QOS capable"
11426 " is_qos_wmm_sta= %d HTcapPresent = %d",
11427 __func__, is_qos_wmm_sta,
11428 StaParams.htcap_present);
11429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011430 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011431 &StaParams,
11432 isBufSta,
11433 isOffChannelSupported,
11434 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011435 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011436 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011437 return -EINVAL;
11438 }
11439
11440 status =
11441 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11442 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011443 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011444 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011445 return -EINVAL;
11446 }
11447 }
11448#endif
11449 }
11450 EXIT();
11451 return ret;
11452}
11453
11454/**
11455 * wlan_hdd_change_station() - cfg80211 change station handler function
11456 * @wiphy: Pointer to the wiphy structure
11457 * @dev: Pointer to the net device.
11458 * @mac: bssid
11459 * @params: Pointer to station parameters
11460 *
11461 * This is the cfg80211 change station handler function which invokes
11462 * the internal function @__wlan_hdd_change_station with
11463 * SSR protection.
11464 *
11465 * Return: 0 for success, error number on failure.
11466 */
11467#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11468static int wlan_hdd_change_station(struct wiphy *wiphy,
11469 struct net_device *dev,
11470 const u8 *mac,
11471 struct station_parameters *params)
11472#else
11473static int wlan_hdd_change_station(struct wiphy *wiphy,
11474 struct net_device *dev,
11475 u8 *mac,
11476 struct station_parameters *params)
11477#endif
11478{
11479 int ret;
11480
11481 cds_ssr_protect(__func__);
11482 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11483 cds_ssr_unprotect(__func__);
11484
11485 return ret;
11486}
11487
11488/*
11489 * FUNCTION: __wlan_hdd_cfg80211_add_key
11490 * This function is used to initialize the key information
11491 */
11492static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11493 struct net_device *ndev,
11494 u8 key_index, bool pairwise,
11495 const u8 *mac_addr,
11496 struct key_params *params)
11497{
11498 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11499 tCsrRoamSetKey setKey;
11500 int status;
11501 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011502 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011503 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011504 hdd_context_t *pHddCtx;
11505 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11506
11507 ENTER();
11508
Anurag Chouhan6d760662016-02-20 16:05:43 +053011509 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011510 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011511 return -EINVAL;
11512 }
11513
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011514 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11515 hdd_err("invalid session id: %d", pAdapter->sessionId);
11516 return -EINVAL;
11517 }
11518
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011519 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011520 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11521 pAdapter->sessionId, params->key_len));
11522 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11523 status = wlan_hdd_validate_context(pHddCtx);
11524
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011525 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011526 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011527
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011528 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011529 hdd_device_mode_to_string(pAdapter->device_mode),
11530 pAdapter->device_mode);
11531
11532 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011533 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011534
11535 return -EINVAL;
11536 }
11537
11538 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011539 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011540
11541 return -EINVAL;
11542 }
11543
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011544 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011545
11546 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011547 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011548 setKey.keyId = key_index;
11549 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011550 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011551
11552 switch (params->cipher) {
11553 case WLAN_CIPHER_SUITE_WEP40:
11554 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11555 break;
11556
11557 case WLAN_CIPHER_SUITE_WEP104:
11558 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11559 break;
11560
11561 case WLAN_CIPHER_SUITE_TKIP:
11562 {
11563 u8 *pKey = &setKey.Key[0];
11564 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11565
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011566 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011567
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011568 /* Supplicant sends the 32bytes key in this order
11569 *
11570 * |--------------|----------|----------|
11571 * | Tk1 |TX-MIC | RX Mic |
11572 * |--------------|----------|----------|
11573 * <---16bytes---><--8bytes--><--8bytes-->
11574 *
11575 * Sme expects the 32 bytes key to be in the below order
11576 *
11577 * |--------------|----------|----------|
11578 * | Tk1 |RX-MIC | TX Mic |
11579 * |--------------|----------|----------|
11580 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011581 */
11582 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011583 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011584
11585 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011586 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587
11588 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011589 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011590
11591 break;
11592 }
11593
11594 case WLAN_CIPHER_SUITE_CCMP:
11595 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11596 break;
11597
11598#ifdef FEATURE_WLAN_WAPI
11599 case WLAN_CIPHER_SUITE_SMS4:
11600 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011601 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011602 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11603 mac_addr, params->key,
11604 params->key_len);
11605 return 0;
11606 }
11607#endif
11608
11609#ifdef FEATURE_WLAN_ESE
11610 case WLAN_CIPHER_SUITE_KRK:
11611 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11612 break;
11613#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11614 case WLAN_CIPHER_SUITE_BTK:
11615 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11616 break;
11617#endif
11618#endif
11619
11620#ifdef WLAN_FEATURE_11W
11621 case WLAN_CIPHER_SUITE_AES_CMAC:
11622 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11623 break;
11624#endif
11625
11626 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011627 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011628 return -EOPNOTSUPP;
11629 }
11630
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011631 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011632
11633 if (!pairwise) {
11634 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011635 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011636 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011637 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011638 } else {
11639 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011640 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011642 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011643 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011644 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011645 /* if a key is already installed, block all subsequent ones */
11646 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011647 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011648 return 0;
11649 }
11650
11651 setKey.keyDirection = eSIR_TX_RX;
11652 /*Set the group key */
11653 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11654 pAdapter->sessionId, &setKey, &roamId);
11655
11656 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011657 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658 return -EINVAL;
11659 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011660 /* Save the keys here and call sme_roam_set_key for setting
11661 * the PTK after peer joins the IBSS network
11662 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011663 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011664 &setKey, sizeof(tCsrRoamSetKey));
11665
11666 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11667 return status;
11668 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011669 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11670 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011671 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11672 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011673 status = wlansap_set_key_sta(
11674 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011675 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011676 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011677 __LINE__, status);
11678 }
11679 }
11680
11681 /* Save the key in ap ctx for use on START_BASS and restart */
11682 if (pairwise ||
11683 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11684 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011685 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011686 sizeof(tCsrRoamSetKey));
11687 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011688 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011689 sizeof(tCsrRoamSetKey));
11690
Krunal Sonib4326f22016-03-10 13:05:51 -080011691 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11692 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011693 hdd_wext_state_t *pWextState =
11694 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11695 hdd_station_ctx_t *pHddStaCtx =
11696 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11697
11698 if (!pairwise) {
11699 /* set group key */
11700 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011701 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011702 __func__, __LINE__);
11703 hdd_perform_roam_set_key_complete(pAdapter);
11704 }
11705 }
11706
11707 pWextState->roamProfile.Keys.KeyLength[key_index] =
11708 (u8) params->key_len;
11709
11710 pWextState->roamProfile.Keys.defaultIndex = key_index;
11711
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011712 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011713 KeyMaterial[key_index][0], params->key,
11714 params->key_len);
11715
11716 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11717
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011718 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011719 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11720 setKey.keyDirection);
11721
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011722 /* The supplicant may attempt to set the PTK once
11723 * pre-authentication is done. Save the key in the
11724 * UMAC and include it in the ADD BSS request
11725 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011726 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011727 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011728 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011729 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011730 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011731 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011732 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011733 return -EINVAL;
11734 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011735
11736 /* issue set key request to SME */
11737 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11738 pAdapter->sessionId, &setKey, &roamId);
11739
11740 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011741 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011742 pHddStaCtx->roam_info.roamingState =
11743 HDD_ROAM_STATE_NONE;
11744 return -EINVAL;
11745 }
11746
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011747 /* in case of IBSS as there was no information
11748 * available about WEP keys during IBSS join, group
11749 * key intialized with NULL key, so re-initialize
11750 * group key with correct value
11751 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011752 if ((eCSR_BSS_TYPE_START_IBSS ==
11753 pWextState->roamProfile.BSSType)
11754 &&
11755 !((IW_AUTH_KEY_MGMT_802_1X ==
11756 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11757 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11758 pHddStaCtx->conn_info.authType)
11759 )
11760 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11761 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11762 )
11763 ) {
11764 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011765 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011766
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011767 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011768 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11769 setKey.keyDirection);
11770
11771 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11772 pAdapter->sessionId, &setKey,
11773 &roamId);
11774
11775 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011776 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011777 pHddStaCtx->roam_info.roamingState =
11778 HDD_ROAM_STATE_NONE;
11779 return -EINVAL;
11780 }
11781 }
11782 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011783 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011784 return 0;
11785}
11786
11787static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11788 struct net_device *ndev,
11789 u8 key_index, bool pairwise,
11790 const u8 *mac_addr,
11791 struct key_params *params)
11792{
11793 int ret;
11794 cds_ssr_protect(__func__);
11795 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11796 mac_addr, params);
11797 cds_ssr_unprotect(__func__);
11798
11799 return ret;
11800}
11801
11802/*
11803 * FUNCTION: __wlan_hdd_cfg80211_get_key
11804 * This function is used to get the key information
11805 */
11806static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11807 struct net_device *ndev,
11808 u8 key_index, bool pairwise,
11809 const u8 *mac_addr, void *cookie,
11810 void (*callback)(void *cookie,
11811 struct key_params *)
11812 )
11813{
11814 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11815 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11816 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11817 struct key_params params;
11818
11819 ENTER();
11820
Anurag Chouhan6d760662016-02-20 16:05:43 +053011821 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011822 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011823 return -EINVAL;
11824 }
11825
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011826 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011827 hdd_device_mode_to_string(pAdapter->device_mode),
11828 pAdapter->device_mode);
11829
11830 memset(&params, 0, sizeof(params));
11831
11832 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011833 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 key_index);
11835 return -EINVAL;
11836 }
11837
11838 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11839 case eCSR_ENCRYPT_TYPE_NONE:
11840 params.cipher = IW_AUTH_CIPHER_NONE;
11841 break;
11842
11843 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11844 case eCSR_ENCRYPT_TYPE_WEP40:
11845 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11846 break;
11847
11848 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11849 case eCSR_ENCRYPT_TYPE_WEP104:
11850 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11851 break;
11852
11853 case eCSR_ENCRYPT_TYPE_TKIP:
11854 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11855 break;
11856
11857 case eCSR_ENCRYPT_TYPE_AES:
11858 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11859 break;
11860
11861 default:
11862 params.cipher = IW_AUTH_CIPHER_NONE;
11863 break;
11864 }
11865
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011866 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011867 TRACE_CODE_HDD_CFG80211_GET_KEY,
11868 pAdapter->sessionId, params.cipher));
11869
11870 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11871 params.seq_len = 0;
11872 params.seq = NULL;
11873 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11874 callback(cookie, &params);
11875
11876 EXIT();
11877 return 0;
11878}
11879
11880static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11881 struct net_device *ndev,
11882 u8 key_index, bool pairwise,
11883 const u8 *mac_addr, void *cookie,
11884 void (*callback)(void *cookie,
11885 struct key_params *)
11886 )
11887{
11888 int ret;
11889
11890 cds_ssr_protect(__func__);
11891 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11892 mac_addr, cookie, callback);
11893 cds_ssr_unprotect(__func__);
11894
11895 return ret;
11896}
11897
11898/**
11899 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
11900 * @wiphy: wiphy interface context
11901 * @ndev: pointer to net device
11902 * @key_index: Key index used in 802.11 frames
11903 * @unicast: true if it is unicast key
11904 * @multicast: true if it is multicast key
11905 *
11906 * This function is required for cfg80211_ops API.
11907 * It is used to delete the key information
11908 * Underlying hardware implementation does not have API to delete the
11909 * encryption key. It is automatically deleted when the peer is
11910 * removed. Hence this function currently does nothing.
11911 * Future implementation may interprete delete key operation to
11912 * replacing the key with a random junk value, effectively making it
11913 * useless.
11914 *
11915 * Return: status code, always 0.
11916 */
11917
11918static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11919 struct net_device *ndev,
11920 u8 key_index,
11921 bool pairwise, const u8 *mac_addr)
11922{
11923 EXIT();
11924 return 0;
11925}
11926
11927/**
11928 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
11929 * @wiphy: Pointer to wiphy structure.
11930 * @dev: Pointer to net_device structure.
11931 * @key_index: key index
11932 * @pairwise: pairwise
11933 * @mac_addr: mac address
11934 *
11935 * This is the cfg80211 delete key handler function which invokes
11936 * the internal function @__wlan_hdd_cfg80211_del_key with
11937 * SSR protection.
11938 *
11939 * Return: 0 for success, error number on failure.
11940 */
11941static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
11942 struct net_device *dev,
11943 u8 key_index,
11944 bool pairwise, const u8 *mac_addr)
11945{
11946 int ret;
11947
11948 cds_ssr_protect(__func__);
11949 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
11950 pairwise, mac_addr);
11951 cds_ssr_unprotect(__func__);
11952
11953 return ret;
11954}
11955
11956/*
11957 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
11958 * This function is used to set the default tx key index
11959 */
11960static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
11961 struct net_device *ndev,
11962 u8 key_index,
11963 bool unicast, bool multicast)
11964{
11965 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11966 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11967 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11968 hdd_context_t *pHddCtx;
11969 int status;
11970
11971 ENTER();
11972
Anurag Chouhan6d760662016-02-20 16:05:43 +053011973 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011974 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011975 return -EINVAL;
11976 }
11977
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011978 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11979 hdd_err("invalid session id: %d", pAdapter->sessionId);
11980 return -EINVAL;
11981 }
11982
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011983 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011984 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
11985 pAdapter->sessionId, key_index));
11986
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011987 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011988 hdd_device_mode_to_string(pAdapter->device_mode),
11989 pAdapter->device_mode, key_index);
11990
11991 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011992 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011993 return -EINVAL;
11994 }
11995
11996 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11997 status = wlan_hdd_validate_context(pHddCtx);
11998
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011999 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012000 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012001
Krunal Sonib4326f22016-03-10 13:05:51 -080012002 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12003 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012004 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12005 pHddStaCtx->conn_info.ucEncryptionType) &&
12006 (eCSR_ENCRYPT_TYPE_AES !=
12007 pHddStaCtx->conn_info.ucEncryptionType)) {
12008 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012009 * then update the default key index
12010 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012011
12012 tCsrRoamSetKey setKey;
12013 uint32_t roamId = 0xFF;
12014 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12015
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012016 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012017
12018 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012019 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012020 setKey.keyId = key_index;
12021 setKey.keyLength = Keys->KeyLength[key_index];
12022
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012023 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012024 &Keys->KeyMaterial[key_index][0],
12025 Keys->KeyLength[key_index]);
12026
12027 setKey.keyDirection = eSIR_TX_RX;
12028
Anurag Chouhanc5548422016-02-24 18:33:27 +053012029 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012030 &pHddStaCtx->conn_info.bssId);
12031
12032 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12033 pWextState->roamProfile.EncryptionType.
12034 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012035 /* In the case of dynamic wep
12036 * supplicant hardcodes DWEP type to
12037 * eCSR_ENCRYPT_TYPE_WEP104 even
12038 * though ap is configured for WEP-40
12039 * encryption. In this canse the key
12040 * length is 5 but the encryption type
12041 * is 104 hence checking the key
12042 * lenght(5) and encryption type(104)
12043 * and switching encryption type to 40
12044 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012045 pWextState->roamProfile.EncryptionType.
12046 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12047 pWextState->roamProfile.mcEncryptionType.
12048 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12049 }
12050
12051 setKey.encType =
12052 pWextState->roamProfile.EncryptionType.
12053 encryptionType[0];
12054
12055 /* Issue set key request */
12056 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12057 pAdapter->sessionId, &setKey,
12058 &roamId);
12059
12060 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012061 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012062 status);
12063 return -EINVAL;
12064 }
12065 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012066 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012067 /* In SoftAp mode setting key direction for default mode */
12068 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12069 pWextState->roamProfile.EncryptionType.encryptionType[0])
12070 && (eCSR_ENCRYPT_TYPE_AES !=
12071 pWextState->roamProfile.EncryptionType.
12072 encryptionType[0])) {
12073 /* Saving key direction for default key index to TX default */
12074 hdd_ap_ctx_t *pAPCtx =
12075 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12076 pAPCtx->wepKey[key_index].keyDirection =
12077 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012078 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012079 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012080 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012081 }
12082 }
12083
12084 EXIT();
12085 return status;
12086}
12087
12088static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12089 struct net_device *ndev,
12090 u8 key_index,
12091 bool unicast, bool multicast)
12092{
12093 int ret;
12094 cds_ssr_protect(__func__);
12095 ret =
12096 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12097 multicast);
12098 cds_ssr_unprotect(__func__);
12099
12100 return ret;
12101}
12102
Abhishek Singhc9941602016-08-09 16:06:22 +053012103/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012104 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12105 * interface that BSS might have been lost.
12106 * @pAdapter: adaptor
12107 * @bssid: bssid which might have been lost
12108 *
12109 * Return: bss which is unlinked from kernel cache
12110 */
12111struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12112 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012113{
12114 struct net_device *dev = pAdapter->dev;
12115 struct wireless_dev *wdev = dev->ieee80211_ptr;
12116 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012117 struct cfg80211_bss *bss = NULL;
12118
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012119 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012120 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012121 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012122 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012123 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053012124 hdd_info("cfg80211_unlink_bss called for BSSID "
12125 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012126 cfg80211_unlink_bss(wiphy, bss);
12127 }
12128 return bss;
12129}
12130
Abhishek Singhc9941602016-08-09 16:06:22 +053012131
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012132/**
12133 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12134 * @pAdapter: Pointer to adapter
12135 * @bss_desc: Pointer to bss descriptor
12136 *
12137 * This function is used to inform the BSS details to nl80211 interface.
12138 *
12139 * Return: struct cfg80211_bss pointer
12140 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012141struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12142 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012143{
12144 /*
12145 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12146 * already exists in bss data base of cfg80211 for that particular BSS
12147 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12148 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12149 * As of now there is no possibility to get the mgmt(probe response)
12150 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12151 * and passing to cfg80211_inform_bss_frame.
12152 */
12153 struct net_device *dev = pAdapter->dev;
12154 struct wireless_dev *wdev = dev->ieee80211_ptr;
12155 struct wiphy *wiphy = wdev->wiphy;
12156 int chan_no = bss_desc->channelId;
12157#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12158 qcom_ie_age *qie_age = NULL;
12159 int ie_length =
12160 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12161#else
12162 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12163#endif
12164 const char *ie =
12165 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12166 unsigned int freq;
12167 struct ieee80211_channel *chan;
12168 struct ieee80211_mgmt *mgmt = NULL;
12169 struct cfg80211_bss *bss_status = NULL;
12170 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12171 int rssi = 0;
12172 hdd_context_t *pHddCtx;
12173 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012175 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012176
12177 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12178 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012179 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012180 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012181
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012182 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012183 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012184 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012185 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012186 return NULL;
12187 }
12188
12189 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012191 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012192 * Instead it wants a monotonic increasing value
12193 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012194 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012195 mgmt->u.probe_resp.timestamp =
12196 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012197
12198 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12199 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12200
12201#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12202 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12203 /* Assuming this is the last IE, copy at the end */
12204 ie_length -= sizeof(qcom_ie_age);
12205 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12206 qie_age->element_id = QCOM_VENDOR_IE_ID;
12207 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12208 qie_age->oui_1 = QCOM_OUI1;
12209 qie_age->oui_2 = QCOM_OUI2;
12210 qie_age->oui_3 = QCOM_OUI3;
12211 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012212 /*
12213 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12214 * all bss related timestamp is in units of ms. Due to this when scan
12215 * results are sent to lowi the scan age is high.To address this,
12216 * send age in units of 1/10 ms.
12217 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012218 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012219 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012220 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012221 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12222 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012223 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12224 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012225#endif
12226
12227 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12228 if (bss_desc->fProbeRsp) {
12229 mgmt->frame_control |=
12230 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12231 } else {
12232 mgmt->frame_control |=
12233 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12234 }
12235
12236 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012237 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012238 freq =
12239 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012240 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012241 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012242 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012243 freq =
12244 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012245 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012246 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012247 hdd_err("Invalid chan_no %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012248 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012249 return NULL;
12250 }
12251
12252 chan = __ieee80211_get_channel(wiphy, freq);
12253 /* When the band is changed on the fly using the GUI, three things are done
12254 * 1. scan abort
12255 * 2. flush scan results from cache
12256 * 3. update the band with the new band user specified (refer to the
12257 * hdd_set_band_helper function) as part of the scan abort, message will be
12258 * queued to PE and we proceed with flushing and changinh the band.
12259 * PE will stop the scanning further and report back the results what ever
12260 * it had till now by calling the call back function.
12261 * if the time between update band and scandone call back is sufficient
12262 * enough the band change reflects in SME, SME validates the channels
12263 * and discards the channels correponding to previous band and calls back
12264 * with zero bss results. but if the time between band update and scan done
12265 * callback is very small then band change will not reflect in SME and SME
12266 * reports to HDD all the channels correponding to previous band.this is due
12267 * to race condition.but those channels are invalid to the new band and so
12268 * this function __ieee80211_get_channel will return NULL.Each time we
12269 * report scan result with this pointer null warning kernel trace is printed.
12270 * if the scan results contain large number of APs continuosly kernel
12271 * warning trace is printed and it will lead to apps watch dog bark.
12272 * So drop the bss and continue to next bss.
12273 */
12274 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012275 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12276 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012277 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012278 return NULL;
12279 }
12280
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012281 /* Based on .ini configuration, raw rssi can be reported for bss.
12282 * Raw rssi is typically used for estimating power.
12283 */
12284
12285 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12286 bss_desc->rssi;
12287
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012288 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012289 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012290
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053012291 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012292 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012293 (int)(rssi / 100),
12294 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012295
12296 bss_status =
12297 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
12298 GFP_KERNEL);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012299 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012300 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012301 return bss_status;
12302}
12303
12304/**
12305 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12306 * @pAdapter: Pointer to adapter
12307 * @pRoamInfo: Pointer to roam info
12308 *
12309 * This function is used to update the BSS data base of CFG8011
12310 *
12311 * Return: struct cfg80211_bss pointer
12312 */
12313struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12314 tCsrRoamInfo *pRoamInfo)
12315{
12316 tCsrRoamConnectedProfile roamProfile;
12317 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12318 struct cfg80211_bss *bss = NULL;
12319
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012320 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12321 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12322
12323 if (NULL != roamProfile.pBssDesc) {
12324 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12325 roamProfile.pBssDesc);
12326
12327 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012328 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012329
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012330 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012331 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012332 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012333 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334 return bss;
12335}
12336/**
12337 * wlan_hdd_cfg80211_update_bss() - update bss
12338 * @wiphy: Pointer to wiphy
12339 * @pAdapter: Pointer to adapter
12340 * @scan_time: scan request timestamp
12341 *
12342 * Return: zero if success, non-zero otherwise
12343 */
12344int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12345 hdd_adapter_t *pAdapter,
12346 uint32_t scan_time)
12347{
12348 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12349 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012350 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012351 tScanResultHandle pResult;
12352 struct cfg80211_bss *bss_status = NULL;
12353 hdd_context_t *pHddCtx;
12354 int ret;
12355
12356 ENTER();
12357
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012358 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12359 hdd_err("invalid session id: %d", pAdapter->sessionId);
12360 return -EINVAL;
12361 }
12362
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012363 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012364 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12365 NO_SESSION, pAdapter->sessionId));
12366
12367 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12368 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012369 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012370 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012371
12372 /* start getting scan results and populate cgf80211 BSS database */
12373 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12374
12375 /* no scan results */
12376 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012377 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012378 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012379 }
12380
12381 pScanResult = sme_scan_result_get_first(hHal, pResult);
12382
12383 while (pScanResult) {
12384 /*
12385 * - cfg80211_inform_bss() is not updating ie field of bss
12386 * entry if entry already exists in bss data base of cfg80211
12387 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12388 * to update thebss entry instead of cfg80211_inform_bss,
12389 * But this call expects mgmt packet as input. As of now
12390 * there is no possibility to get the mgmt(probe response)
12391 * frame from PE, converting bss_desc to
12392 * ieee80211_mgmt(probe response) and passing to c
12393 * fg80211_inform_bss_frame.
12394 * - Update BSS only if beacon timestamp is later than
12395 * scan request timestamp.
12396 */
12397 if ((scan_time == 0) ||
12398 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012399 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012400 bss_status =
12401 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12402 &pScanResult->BssDescriptor);
12403
12404 if (NULL == bss_status) {
12405 hdd_info("NULL returned by cfg80211_inform_bss_frame");
12406 } else {
12407 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012408 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012409 bss_status);
12410 }
12411 } else {
12412 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
12413 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12414 }
12415 pScanResult = sme_scan_result_get_next(hHal, pResult);
12416 }
12417
12418 sme_scan_result_purge(hHal, pResult);
12419 /*
12420 * For SAP mode, scan is invoked by hostapd during SAP start
12421 * if hostapd is restarted, we need to flush previous scan
12422 * result so that it will reflect environment change
12423 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012424 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012425#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12426 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12427#endif
12428 )
12429 sme_scan_flush_result(hHal);
12430
12431 EXIT();
12432 return 0;
12433}
12434
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012435/**
12436 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12437 * @pAdapter: Pointer to adapter
12438 * @pRoamInfo: Pointer to roam info
12439 * @index: Index
12440 * @preauth: Preauth flag
12441 *
12442 * This function is used to notify the supplicant of a new PMKSA candidate.
12443 *
12444 * Return: 0 for success, non-zero for failure
12445 */
12446int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12447 tCsrRoamInfo *pRoamInfo,
12448 int index, bool preauth)
12449{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012450 struct net_device *dev = pAdapter->dev;
12451 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12452
12453 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012454 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012455
12456 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012457 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012458 return -EINVAL;
12459 }
12460
12461 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012462 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012463 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12464 cfg80211_pmksa_candidate_notify(dev, index,
12465 pRoamInfo->bssid.bytes,
12466 preauth, GFP_KERNEL);
12467 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012468 return 0;
12469}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012470
12471#ifdef FEATURE_WLAN_LFR_METRICS
12472/**
12473 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12474 * @pAdapter: Pointer to adapter
12475 * @pRoamInfo: Pointer to roam info
12476 *
12477 * 802.11r/LFR metrics reporting function to report preauth initiation
12478 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012479 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012480 */
12481#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012482QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012483 tCsrRoamInfo *pRoamInfo)
12484{
12485 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12486 union iwreq_data wrqu;
12487
12488 ENTER();
12489
12490 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012491 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012492 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012493 }
12494
12495 /* create the event */
12496 memset(&wrqu, 0, sizeof(wrqu));
12497 memset(metrics_notification, 0, sizeof(metrics_notification));
12498
12499 wrqu.data.pointer = metrics_notification;
12500 wrqu.data.length = scnprintf(metrics_notification,
12501 sizeof(metrics_notification),
12502 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12503 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12504
12505 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12506 metrics_notification);
12507
12508 EXIT();
12509
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012510 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012511}
12512
12513/**
12514 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12515 * @pAdapter: Pointer to adapter
12516 * @pRoamInfo: Pointer to roam info
12517 * @preauth_status: Preauth status
12518 *
12519 * 802.11r/LFR metrics reporting function to report handover initiation
12520 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012521 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012522 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012523QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012524wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12525 tCsrRoamInfo *pRoamInfo,
12526 bool preauth_status)
12527{
12528 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12529 union iwreq_data wrqu;
12530
12531 ENTER();
12532
12533 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012534 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012535 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012536 }
12537
12538 /* create the event */
12539 memset(&wrqu, 0, sizeof(wrqu));
12540 memset(metrics_notification, 0, sizeof(metrics_notification));
12541
12542 scnprintf(metrics_notification, sizeof(metrics_notification),
12543 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12544 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12545
12546 if (1 == preauth_status)
12547 strlcat(metrics_notification, " true",
12548 sizeof(metrics_notification));
12549 else
12550 strlcat(metrics_notification, " false",
12551 sizeof(metrics_notification));
12552
12553 wrqu.data.pointer = metrics_notification;
12554 wrqu.data.length = strlen(metrics_notification);
12555
12556 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12557 metrics_notification);
12558
12559 EXIT();
12560
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012561 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012562}
12563
12564/**
12565 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12566 * @pAdapter: Pointer to adapter
12567 * @pRoamInfo: Pointer to roam info
12568 *
12569 * 802.11r/LFR metrics reporting function to report handover initiation
12570 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012571 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012572 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012573QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012574 tCsrRoamInfo *pRoamInfo)
12575{
12576 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12577 union iwreq_data wrqu;
12578
12579 ENTER();
12580
12581 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012582 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012583 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012584 }
12585
12586 /* create the event */
12587 memset(&wrqu, 0, sizeof(wrqu));
12588 memset(metrics_notification, 0, sizeof(metrics_notification));
12589
12590 wrqu.data.pointer = metrics_notification;
12591 wrqu.data.length = scnprintf(metrics_notification,
12592 sizeof(metrics_notification),
12593 "QCOM: LFR_PREAUTH_HANDOVER "
12594 MAC_ADDRESS_STR,
12595 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12596
12597 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12598 metrics_notification);
12599
12600 EXIT();
12601
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012602 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012603}
12604#endif
12605
12606/**
12607 * hdd_select_cbmode() - select channel bonding mode
12608 * @pAdapter: Pointer to adapter
12609 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012610 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012611 *
12612 * Return: none
12613 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012614void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12615 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012616{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012617 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012618 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012619 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012620
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012621 /*
12622 * CDS api expects secondary channel for calculating
12623 * the channel params
12624 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012625 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012626 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12627 if (operationChannel >= 1 && operationChannel <= 5)
12628 sec_ch = operationChannel + 4;
12629 else if (operationChannel >= 6 && operationChannel <= 13)
12630 sec_ch = operationChannel - 4;
12631 }
12632
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012633 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012634 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012635
12636 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012637 eHddDot11Mode hdd_dot11_mode;
12638 uint8_t iniDot11Mode =
12639 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12640
12641 hdd_notice("Dot11Mode is %u", iniDot11Mode);
12642 switch (iniDot11Mode) {
12643 case eHDD_DOT11_MODE_AUTO:
12644 case eHDD_DOT11_MODE_11ac:
12645 case eHDD_DOT11_MODE_11ac_ONLY:
12646 if (sme_is_feature_supported_by_fw(DOT11AC))
12647 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12648 else
12649 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12650 break;
12651 case eHDD_DOT11_MODE_11n:
12652 case eHDD_DOT11_MODE_11n_ONLY:
12653 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12654 break;
12655 default:
12656 hdd_dot11_mode = iniDot11Mode;
12657 break;
12658 }
12659 ch_info->channel_width = ch_params->ch_width;
12660 ch_info->phy_mode =
12661 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012662 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012663 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012664 hdd_info("ch_info width %d, phymode %d channel %d",
12665 ch_info->channel_width, ch_info->phy_mode,
12666 ch_info->channel);
12667 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012668}
12669
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012670/**
12671 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12672 * @adapter: STA adapter
12673 * @roam_profile: STA roam profile
12674 *
12675 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12676 *
12677 * Return: false if sta-sap conc is not allowed, else return true
12678 */
12679static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12680 tCsrRoamProfile *roam_profile)
12681{
12682 hdd_context_t *hdd_ctx;
12683 hdd_adapter_t *ap_adapter;
12684 hdd_ap_ctx_t *hdd_ap_ctx;
12685 hdd_hostapd_state_t *hostapd_state;
12686 uint8_t channel = 0;
12687 QDF_STATUS status;
12688
12689 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12690 if (!hdd_ctx) {
12691 hdd_err("HDD context is NULL");
12692 return true;
12693 }
12694
12695 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12696 /* probably no sap running, no handling required */
12697 if (ap_adapter == NULL)
12698 return true;
12699
12700 /*
12701 * sap is not in started state, so it is fine to go ahead with sta.
12702 * if sap is currently doing CAC then don't allow sta to go further.
12703 */
12704 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12705 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12706 return true;
12707
12708 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12709 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12710 return false;
12711 }
12712
12713 /*
12714 * log and return error, if we allow STA to go through, we don't
12715 * know what is going to happen better stop sta connection
12716 */
12717 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12718 if (NULL == hdd_ap_ctx) {
12719 hdd_err("AP context not found");
12720 return false;
12721 }
12722
12723 /* sap is on non-dfs channel, nothing to handle */
12724 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
12725 hdd_info("sap is on non-dfs channel, sta is allowed");
12726 return true;
12727 }
12728 /*
12729 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012730 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012731 */
12732 status = cds_get_channel_from_scan_result(adapter,
12733 roam_profile, &channel);
12734
Nitesh Shah59774522016-09-16 15:14:21 +053012735 /*
12736 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12737 * channels for roaming case.
12738 */
12739 if (CDS_IS_CHANNEL_24GHZ(channel)) {
12740 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
12741 return true;
12742 }
12743
12744 /*
12745 * If channel is 0 or DFS then better to call pcl and find out the
12746 * best channel. If channel is non-dfs 5 GHz then better move SAP
12747 * to STA's channel to make scc, so we have room for 3port MCC
12748 * scenario.
12749 */
12750 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012751 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
12752 true);
12753
12754 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12755 qdf_event_reset(&hostapd_state->qdf_event);
12756 status = wlansap_set_channel_change_with_csa(
12757 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12758 hdd_ap_ctx->sapConfig.ch_width_orig);
12759
12760 if (QDF_STATUS_SUCCESS != status) {
12761 hdd_err("Set channel with CSA IE failed, can't allow STA");
12762 return false;
12763 }
12764
12765 /*
12766 * wait here for SAP to finish the channel switch. When channel
12767 * switch happens, SAP sends few beacons with CSA_IE. After
12768 * successfully Transmission of those beacons, it will move its
12769 * state from started to disconnected and move to new channel.
12770 * once it moves to new channel, sap again moves its state
12771 * machine from disconnected to started and set this event.
12772 * wait for 10 secs to finish this.
12773 */
12774 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12775 if (!QDF_IS_STATUS_SUCCESS(status)) {
12776 hdd_err("wait for qdf_event failed, STA not allowed!!");
12777 return false;
12778 }
12779
12780 return true;
12781}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012782
Krunal Soni31949422016-07-29 17:17:53 -070012783/**
12784 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012785 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012786 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012787 * @ssid_len: Length of ssid
12788 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012789 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012790 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012791 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012792 *
12793 * This function is used to start the association process
12794 *
12795 * Return: 0 for success, non-zero for failure
12796 */
Krunal Soni31949422016-07-29 17:17:53 -070012797static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012798 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012799 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012800 u8 operatingChannel,
12801 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012802{
12803 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012804 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012805 hdd_wext_state_t *pWextState;
12806 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012807 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012808 uint32_t roamId;
12809 tCsrRoamProfile *pRoamProfile;
12810 eCsrAuthType RSNAuthType;
12811 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012812 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012813
12814 ENTER();
12815
12816 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12817 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012818 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012819
12820 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012821 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012822 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012823
12824 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012825 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012826 return -EINVAL;
12827 }
12828
12829 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053012830 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
12831 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012832
12833 if (pRoamProfile) {
12834 hdd_station_ctx_t *pHddStaCtx;
12835 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12836
12837 if (HDD_WMM_USER_MODE_NO_QOS ==
12838 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
12839 /*QoS not enabled in cfg file */
12840 pRoamProfile->uapsd_mask = 0;
12841 } else {
12842 /*QoS enabled, update uapsd mask from cfg file */
12843 pRoamProfile->uapsd_mask =
12844 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
12845 }
12846
12847 pRoamProfile->SSIDs.numOfSSIDs = 1;
12848 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012849 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012850 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012851 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012852 ssid, ssid_len);
12853
Deepak Dhamdherea2785822016-11-17 01:17:45 -080012854 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012855 /* cleanup bssid hint */
12856 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
12857 QDF_MAC_ADDR_SIZE);
12858 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
12859 QDF_MAC_ADDR_SIZE);
12860
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012861 if (bssid) {
12862 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053012863 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012864 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012865 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012866 /*
12867 * Save BSSID in seperate variable as
12868 * pRoamProfile's BSSID is getting zeroed out in the
12869 * association process. In case of join failure
12870 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012871 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012872 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012873 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012874 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012875 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053012876 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
12877 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070012878 /*
12879 * Save BSSID in a separate variable as
12880 * pRoamProfile's BSSID is getting zeroed out in the
12881 * association process. In case of join failure
12882 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012883 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012884 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053012885 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070012886 hdd_info("bssid_hint is given by upper layer %pM",
12887 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012888 }
12889
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012890 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012891 pRoamProfile->SSIDs.SSIDList->SSID.length,
12892 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
12893 operatingChannel);
12894
12895 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
12896 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012897 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012898 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
12899 }
12900#ifdef FEATURE_WLAN_WAPI
12901 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012902 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012903 switch (pAdapter->wapi_info.wapiAuthMode) {
12904 case WAPI_AUTH_MODE_PSK:
12905 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012906 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012907 pAdapter->wapi_info.wapiAuthMode);
12908 pRoamProfile->AuthType.authType[0] =
12909 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
12910 break;
12911 }
12912 case WAPI_AUTH_MODE_CERT:
12913 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012914 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012915 pAdapter->wapi_info.wapiAuthMode);
12916 pRoamProfile->AuthType.authType[0] =
12917 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
12918 break;
12919 }
12920 } /* End of switch */
12921 if (pAdapter->wapi_info.wapiAuthMode ==
12922 WAPI_AUTH_MODE_PSK
12923 || pAdapter->wapi_info.wapiAuthMode ==
12924 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012925 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012926 pRoamProfile->AuthType.numEntries = 1;
12927 pRoamProfile->EncryptionType.numEntries = 1;
12928 pRoamProfile->EncryptionType.encryptionType[0] =
12929 eCSR_ENCRYPT_TYPE_WPI;
12930 pRoamProfile->mcEncryptionType.numEntries = 1;
12931 pRoamProfile->mcEncryptionType.
12932 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
12933 }
12934 }
Krunal Soni31949422016-07-29 17:17:53 -070012935#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012936#ifdef WLAN_FEATURE_GTK_OFFLOAD
12937 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080012938 if ((QDF_STA_MODE == pAdapter->device_mode) ||
12939 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012940 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
12941 sizeof(tSirGtkOffloadParams));
12942 pHddStaCtx->gtkOffloadReqParams.ulFlags =
12943 GTK_OFFLOAD_DISABLE;
12944 }
12945#endif
12946 pRoamProfile->csrPersona = pAdapter->device_mode;
12947
12948 if (operatingChannel) {
12949 pRoamProfile->ChannelInfo.ChannelList =
12950 &operatingChannel;
12951 pRoamProfile->ChannelInfo.numOfChannels = 1;
12952 } else {
12953 pRoamProfile->ChannelInfo.ChannelList = NULL;
12954 pRoamProfile->ChannelInfo.numOfChannels = 0;
12955 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012956 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012957 && operatingChannel) {
12958 /*
12959 * Need to post the IBSS power save parameters
12960 * to WMA. WMA will configure this parameters
12961 * to firmware if power save is enabled by the
12962 * firmware.
12963 */
12964 status = hdd_set_ibss_power_save_params(pAdapter);
12965
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012966 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012967 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012968 return -EINVAL;
12969 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012970 pRoamProfile->ch_params.ch_width =
12971 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053012972 /*
12973 * In IBSS mode while operating in 2.4 GHz,
12974 * the device supports only 20 MHz.
12975 */
12976 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
12977 pRoamProfile->ch_params.ch_width =
12978 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012979 hdd_select_cbmode(pAdapter, operatingChannel,
12980 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012981 }
Abhishek Singh99bce862016-06-20 15:10:51 +053012982 /*
12983 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12984 * or pmf=2 is an explicit configuration in the supplicant
12985 * configuration, drop the connection request.
12986 */
12987 if (pWextState->roamProfile.MFPEnabled &&
12988 !(pWextState->roamProfile.MFPRequired ||
12989 pWextState->roamProfile.MFPCapable)) {
12990 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12991 pWextState->roamProfile.MFPEnabled,
12992 pWextState->roamProfile.MFPRequired,
12993 pWextState->roamProfile.MFPCapable);
12994 return -EINVAL;
12995 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012996
Krunal Soni3091bcc2016-06-23 12:28:21 -070012997 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012998 hdd_err("Connection refused: conn in progress");
12999 return -EINVAL;
13000 }
13001
Krunal Soni31949422016-07-29 17:17:53 -070013002 /*
13003 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013004 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013005 * enhancements, the supplicant is not issuing the scan command
13006 * now. So the unicast frames which are sent from the host are
13007 * not having the additional IEs. If it is P2P CLIENT and there
13008 * is no additional IE present in roamProfile, then use the
13009 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013010 */
13011
Krunal Sonib4326f22016-03-10 13:05:51 -080013012 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013013 (!pRoamProfile->pAddIEScan)) {
13014 pRoamProfile->pAddIEScan =
13015 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13016 pRoamProfile->nAddIEScanLength =
13017 pAdapter->scan_info.scanAddIE.length;
13018 }
13019 /*
13020 * When policy manager is enabled from ini file, we shouldn't
13021 * check for other concurrency rules.
13022 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070013023 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080013024 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013025 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013026 pAdapter, pRoamProfile, &roamId))
13027 return 0;
13028 }
13029
Krunal Soni3091bcc2016-06-23 12:28:21 -070013030 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013031 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
13032 pRoamProfile))) {
13033 hdd_err("sap-sta conc will fail, can't allow sta");
13034 hdd_conn_set_connection_state(pAdapter,
13035 eConnectionState_NotConnected);
13036 return -ENOMEM;
13037 }
13038
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013039 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013040 if (!sme_config) {
13041 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013042 hdd_conn_set_connection_state(pAdapter,
13043 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013044 return -ENOMEM;
13045 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013046 sme_get_config_param(pHddCtx->hHal, sme_config);
13047 /* These values are not sessionized. So, any change in these SME
13048 * configs on an older or parallel interface will affect the
13049 * cb mode. So, restoring the default INI params before starting
13050 * interfaces such as sta, cli etc.,
13051 */
13052 sme_config->csrConfig.channelBondingMode5GHz =
13053 pHddCtx->config->nChannelBondingMode5GHz;
13054 sme_config->csrConfig.channelBondingMode24GHz =
13055 pHddCtx->config->nChannelBondingMode24GHz;
13056 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013057 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013058 /*
13059 * Change conn_state to connecting before sme_roam_connect(),
13060 * because sme_roam_connect() has a direct path to call
13061 * hdd_sme_roam_callback(), which will change the conn_state
13062 * If direct path, conn_state will be accordingly changed to
13063 * NotConnected or Associated by either
13064 * hdd_association_completion_handler() or
13065 * hdd_dis_connect_handler() in sme_RoamCallback()if
13066 * sme_RomConnect is to be queued,
13067 * Connecting state will remain until it is completed.
13068 *
13069 * If connection state is not changed, connection state will
13070 * remain in eConnectionState_NotConnected state.
13071 * In hdd_association_completion_handler, "hddDisconInProgress"
13072 * is set to true if conn state is
13073 * eConnectionState_NotConnected.
13074 * If "hddDisconInProgress" is set to true then cfg80211 layer
13075 * is not informed of connect result indication which
13076 * is an issue.
13077 */
13078 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013079 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013080 hdd_conn_set_connection_state(pAdapter,
13081 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013082
Komal Seelama89be8d2016-09-29 11:09:26 +053013083 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13084 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013085 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013086 pAdapter->sessionId, pRoamProfile,
13087 &roamId);
13088
Rajeev Kumard31e1542017-01-13 14:37:42 -080013089 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013090 (QDF_STA_MODE == pAdapter->device_mode ||
13091 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013092 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013093 "qdf_status %d. -> NotConnected",
13094 pAdapter->sessionId, qdf_status);
13095 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013096 /* change back to NotAssociated */
13097 hdd_conn_set_connection_state(pAdapter,
13098 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013099 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13100 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013101 }
13102
13103 pRoamProfile->ChannelInfo.ChannelList = NULL;
13104 pRoamProfile->ChannelInfo.numOfChannels = 0;
13105
Nitesh Shah044fd672016-10-13 18:53:25 +053013106 if ((QDF_STA_MODE == pAdapter->device_mode)
Krunal Soni4274f362016-12-14 19:55:25 -080013107 && wma_is_current_hwmode_dbs()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053013108 cds_get_channel_from_scan_result(pAdapter,
13109 pRoamProfile, &channel);
13110 if (channel)
13111 cds_checkn_update_hw_mode_single_mac_mode
13112 (channel);
13113 }
13114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013115 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013116 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013117 return -EINVAL;
13118 }
13119 EXIT();
13120 return status;
13121}
13122
13123/**
13124 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13125 * @pAdapter: Pointer to adapter
13126 * @auth_type: Auth type
13127 *
13128 * This function is used to set the authentication type (OPEN/SHARED).
13129 *
13130 * Return: 0 for success, non-zero for failure
13131 */
13132static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13133 enum nl80211_auth_type auth_type)
13134{
13135 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13136 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13137
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013138 /*set authentication type */
13139 switch (auth_type) {
13140 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013141 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013142 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13143 break;
13144
13145 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013146 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013147 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013148 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13149 break;
13150
13151 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013152 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013153 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13154 break;
13155#ifdef FEATURE_WLAN_ESE
13156 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013157 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013158 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13159 break;
13160#endif
13161
13162 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013163 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013164 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13165 return -EINVAL;
13166 }
13167
13168 pWextState->roamProfile.AuthType.authType[0] =
13169 pHddStaCtx->conn_info.authType;
13170 return 0;
13171}
13172
13173/**
13174 * wlan_hdd_set_akm_suite() - set key management type
13175 * @pAdapter: Pointer to adapter
13176 * @key_mgmt: Key management type
13177 *
13178 * This function is used to set the key mgmt type(PSK/8021x).
13179 *
13180 * Return: 0 for success, non-zero for failure
13181 */
13182static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13183{
13184 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13185
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013186#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
13187#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
13188 /*set key mgmt type */
13189 switch (key_mgmt) {
13190 case WLAN_AKM_SUITE_PSK:
13191 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013192 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013193 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013194 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13195 break;
13196
13197 case WLAN_AKM_SUITE_8021X_SHA256:
13198 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013199 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013200 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013201 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13202 break;
13203#ifdef FEATURE_WLAN_ESE
13204#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13205#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13206 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013207 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013208 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13209 break;
13210#endif
13211#ifndef WLAN_AKM_SUITE_OSEN
13212#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13213#endif
13214 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013215 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013216 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13217 break;
13218
13219 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013220 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013221 return -EINVAL;
13222
13223 }
13224 return 0;
13225}
13226
13227/**
13228 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13229 * @pAdapter: Pointer to adapter
13230 * @cipher: Cipher type
13231 * @ucast: Unicast flag
13232 *
13233 * This function is used to set the encryption type
13234 * (NONE/WEP40/WEP104/TKIP/CCMP).
13235 *
13236 * Return: 0 for success, non-zero for failure
13237 */
13238static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13239 u32 cipher, bool ucast)
13240{
13241 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13242 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13243 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13244
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013245 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013246 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013247 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13248 } else {
13249
13250 /*set encryption method */
13251 switch (cipher) {
13252 case IW_AUTH_CIPHER_NONE:
13253 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13254 break;
13255
13256 case WLAN_CIPHER_SUITE_WEP40:
13257 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13258 break;
13259
13260 case WLAN_CIPHER_SUITE_WEP104:
13261 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13262 break;
13263
13264 case WLAN_CIPHER_SUITE_TKIP:
13265 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13266 break;
13267
13268 case WLAN_CIPHER_SUITE_CCMP:
13269 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13270 break;
13271#ifdef FEATURE_WLAN_WAPI
13272 case WLAN_CIPHER_SUITE_SMS4:
13273 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13274 break;
13275#endif
13276
13277#ifdef FEATURE_WLAN_ESE
13278 case WLAN_CIPHER_SUITE_KRK:
13279 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13280 break;
13281#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13282 case WLAN_CIPHER_SUITE_BTK:
13283 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13284 break;
13285#endif
13286#endif
13287 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013288 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013289 return -EOPNOTSUPP;
13290 }
13291 }
13292
13293 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013294 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013295 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13296 pWextState->roamProfile.EncryptionType.numEntries = 1;
13297 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13298 encryptionType;
13299 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013300 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013301 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13302 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13303 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13304 encryptionType;
13305 }
13306
13307 return 0;
13308}
13309
13310/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013311 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13312 * @wext_state: Pointer to wext state
13313 * @gen_ie: Pointer to IE data
13314 * @len: length of IE data
13315 *
13316 * Return: 0 for success, non-zero for failure
13317 */
13318static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13319 const uint8_t *gen_ie, uint16_t len)
13320{
13321 uint16_t cur_add_ie_len =
13322 wext_state->assocAddIE.length;
13323
13324 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13325 (wext_state->assocAddIE.length + len)) {
13326 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13327 QDF_ASSERT(0);
13328 return -ENOMEM;
13329 }
13330 memcpy(wext_state->assocAddIE.addIEdata +
13331 cur_add_ie_len, gen_ie, len);
13332 wext_state->assocAddIE.length += len;
13333
13334 wext_state->roamProfile.pAddIEAssoc =
13335 wext_state->assocAddIE.addIEdata;
13336 wext_state->roamProfile.nAddIEAssocLength =
13337 wext_state->assocAddIE.length;
13338 return 0;
13339}
13340
13341/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013342 * wlan_hdd_cfg80211_set_ie() - set IEs
13343 * @pAdapter: Pointer to adapter
13344 * @ie: Pointer ot ie
13345 * @ie: IE length
13346 *
13347 * Return: 0 for success, non-zero for failure
13348 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013349static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013350 size_t ie_len)
13351{
13352 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13353 const uint8_t *genie = ie;
13354 uint16_t remLen = ie_len;
13355#ifdef FEATURE_WLAN_WAPI
13356 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13357 u16 *tmp;
13358 uint16_t akmsuiteCount;
13359 int *akmlist;
13360#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013361 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013362
13363 /* clear previous assocAddIE */
13364 pWextState->assocAddIE.length = 0;
13365 pWextState->roamProfile.bWPSAssociation = false;
13366 pWextState->roamProfile.bOSENAssociation = false;
13367
13368 while (remLen >= 2) {
13369 uint16_t eLen = 0;
13370 uint8_t elementId;
13371 elementId = *genie++;
13372 eLen = *genie++;
13373 remLen -= 2;
13374
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013375 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013376
13377 switch (elementId) {
13378 case DOT11F_EID_WPA:
13379 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 -070013380 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013381 return -EINVAL;
13382 } else if (0 ==
13383 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13384 uint16_t curAddIELen =
13385 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013386 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013387
13388 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13389 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013390 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013391 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013392 return -ENOMEM;
13393 }
13394 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13395 memcpy(pWextState->assocAddIE.addIEdata +
13396 curAddIELen, genie - 2, eLen + 2);
13397 pWextState->assocAddIE.length += eLen + 2;
13398
13399 pWextState->roamProfile.bWPSAssociation = true;
13400 pWextState->roamProfile.pAddIEAssoc =
13401 pWextState->assocAddIE.addIEdata;
13402 pWextState->roamProfile.nAddIEAssocLength =
13403 pWextState->assocAddIE.length;
13404 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013405 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013406 memset(pWextState->WPARSNIE, 0,
13407 MAX_WPA_RSN_IE_LEN);
13408 memcpy(pWextState->WPARSNIE, genie - 2,
13409 (eLen + 2));
13410 pWextState->roamProfile.pWPAReqIE =
13411 pWextState->WPARSNIE;
13412 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13413 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13414 P2P_OUI_TYPE_SIZE))) {
13415 uint16_t curAddIELen =
13416 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013417 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013418
13419 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13420 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013421 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013422 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013423 return -ENOMEM;
13424 }
13425 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13426 memcpy(pWextState->assocAddIE.addIEdata +
13427 curAddIELen, genie - 2, eLen + 2);
13428 pWextState->assocAddIE.length += eLen + 2;
13429
13430 pWextState->roamProfile.pAddIEAssoc =
13431 pWextState->assocAddIE.addIEdata;
13432 pWextState->roamProfile.nAddIEAssocLength =
13433 pWextState->assocAddIE.length;
13434 }
13435#ifdef WLAN_FEATURE_WFD
13436 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13437 WFD_OUI_TYPE_SIZE)) &&
13438 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013439 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013440 pAdapter->device_mode)) {
13441 uint16_t curAddIELen =
13442 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013443 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013444
13445 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13446 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013447 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013448 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013449 return -ENOMEM;
13450 }
13451 /* WFD IE is saved to Additional IE ; it should
13452 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013453 * WFD IE
13454 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013455 memcpy(pWextState->assocAddIE.addIEdata +
13456 curAddIELen, genie - 2, eLen + 2);
13457 pWextState->assocAddIE.length += eLen + 2;
13458
13459 pWextState->roamProfile.pAddIEAssoc =
13460 pWextState->assocAddIE.addIEdata;
13461 pWextState->roamProfile.nAddIEAssocLength =
13462 pWextState->assocAddIE.length;
13463 }
13464#endif
13465 /* Appending HS 2.0 Indication Element in Assiciation Request */
13466 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13467 HS20_OUI_TYPE_SIZE))) {
13468 uint16_t curAddIELen =
13469 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013470 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013471
13472 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13473 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013474 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013475 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013476 return -ENOMEM;
13477 }
13478 memcpy(pWextState->assocAddIE.addIEdata +
13479 curAddIELen, genie - 2, eLen + 2);
13480 pWextState->assocAddIE.length += eLen + 2;
13481
13482 pWextState->roamProfile.pAddIEAssoc =
13483 pWextState->assocAddIE.addIEdata;
13484 pWextState->roamProfile.nAddIEAssocLength =
13485 pWextState->assocAddIE.length;
13486 }
13487 /* Appending OSEN Information Element in Assiciation Request */
13488 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13489 OSEN_OUI_TYPE_SIZE))) {
13490 uint16_t curAddIELen =
13491 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013492 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013493
13494 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13495 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013496 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013497 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013498 return -ENOMEM;
13499 }
13500 memcpy(pWextState->assocAddIE.addIEdata +
13501 curAddIELen, genie - 2, eLen + 2);
13502 pWextState->assocAddIE.length += eLen + 2;
13503
13504 pWextState->roamProfile.bOSENAssociation = true;
13505 pWextState->roamProfile.pAddIEAssoc =
13506 pWextState->assocAddIE.addIEdata;
13507 pWextState->roamProfile.nAddIEAssocLength =
13508 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013509 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13510 MBO_OUI_TYPE_SIZE))){
13511 hdd_info("Set MBO IE(len %d)", eLen + 2);
13512 status = wlan_hdd_add_assoc_ie(pWextState,
13513 genie - 2, eLen + 2);
13514 if (status)
13515 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013516 } else {
13517 uint16_t add_ie_len =
13518 pWextState->assocAddIE.length;
13519
13520 hdd_info("Set OSEN IE(len %d)", eLen + 2);
13521
13522 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13523 (pWextState->assocAddIE.length + eLen)) {
13524 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013525 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013526 return -ENOMEM;
13527 }
13528
13529 memcpy(pWextState->assocAddIE.addIEdata +
13530 add_ie_len, genie - 2, eLen + 2);
13531 pWextState->assocAddIE.length += eLen + 2;
13532
13533 pWextState->roamProfile.pAddIEAssoc =
13534 pWextState->assocAddIE.addIEdata;
13535 pWextState->roamProfile.nAddIEAssocLength =
13536 pWextState->assocAddIE.length;
13537 }
13538 break;
13539 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013540 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013541 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13542 memcpy(pWextState->WPARSNIE, genie - 2,
13543 (eLen + 2));
13544 pWextState->roamProfile.pRSNReqIE =
13545 pWextState->WPARSNIE;
13546 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13547 break;
13548 /*
13549 * Appending Extended Capabilities with Interworking bit set
13550 * in Assoc Req.
13551 *
13552 * In assoc req this EXT Cap will only be taken into account if
13553 * interworkingService bit is set to 1. Currently
13554 * driver is only interested in interworkingService capability
13555 * from supplicant. If in future any other EXT Cap info is
13556 * required from supplicat, it needs to be handled while
13557 * sending Assoc Req in LIM.
13558 */
13559 case DOT11F_EID_EXTCAP:
13560 {
13561 uint16_t curAddIELen =
13562 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013563 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013564
13565 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13566 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013567 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013568 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013569 return -ENOMEM;
13570 }
13571 memcpy(pWextState->assocAddIE.addIEdata +
13572 curAddIELen, genie - 2, eLen + 2);
13573 pWextState->assocAddIE.length += eLen + 2;
13574
13575 pWextState->roamProfile.pAddIEAssoc =
13576 pWextState->assocAddIE.addIEdata;
13577 pWextState->roamProfile.nAddIEAssocLength =
13578 pWextState->assocAddIE.length;
13579 break;
13580 }
13581#ifdef FEATURE_WLAN_WAPI
13582 case WLAN_EID_WAPI:
13583 /* Setting WAPI Mode to ON=1 */
13584 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013585 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013586 tmp = (u16 *) ie;
13587 tmp = tmp + 2; /* Skip element Id and Len, Version */
13588 akmsuiteCount = WPA_GET_LE16(tmp);
13589 tmp = tmp + 1;
13590 akmlist = (int *)(tmp);
13591 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13592 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13593 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013594 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013595 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013596 return -EINVAL;
13597 }
13598
13599 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013600 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013601 pAdapter->wapi_info.wapiAuthMode =
13602 WAPI_AUTH_MODE_PSK;
13603 }
13604 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013605 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013606 pAdapter->wapi_info.wapiAuthMode =
13607 WAPI_AUTH_MODE_CERT;
13608 }
13609 break;
13610#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013611 case DOT11F_EID_SUPPOPERATINGCLASSES:
13612 {
13613 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
13614 status = wlan_hdd_add_assoc_ie(pWextState,
13615 genie - 2, eLen + 2);
13616 if (status)
13617 return status;
13618 break;
13619 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013620 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013621 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013622 /* when Unknown IE is received we break
13623 * and continue to the next IE in the buffer
13624 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013625 break;
13626 }
13627 genie += eLen;
13628 remLen -= eLen;
13629 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013630 return 0;
13631}
13632
13633/**
13634 * hdd_is_wpaie_present() - check for WPA ie
13635 * @ie: Pointer to ie
13636 * @ie_len: Ie length
13637 *
13638 * Parse the received IE to find the WPA IE
13639 *
13640 * Return: true if wpa ie is found else false
13641 */
13642static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13643{
13644 uint8_t eLen = 0;
13645 uint16_t remLen = ie_len;
13646 uint8_t elementId = 0;
13647
13648 while (remLen >= 2) {
13649 elementId = *ie++;
13650 eLen = *ie++;
13651 remLen -= 2;
13652 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013653 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013654 return false;
13655 }
13656 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13657 /* OUI - 0x00 0X50 0XF2
13658 * WPA Information Element - 0x01
13659 * WPA version - 0x01
13660 */
13661 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13662 return true;
13663 }
13664 ie += eLen;
13665 remLen -= eLen;
13666 }
13667 return false;
13668}
13669
13670/**
13671 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13672 * @pAdapter: Pointer to adapter
13673 * @req: Pointer to security parameters
13674 *
13675 * Return: 0 for success, non-zero for failure
13676 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013677static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13678 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013679{
13680 int status = 0;
13681 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13682 ENTER();
13683
13684 /*set wpa version */
13685 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13686
13687 if (req->crypto.wpa_versions) {
13688 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13689 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13690 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13691 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13692 }
13693 }
13694
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013695 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013696
13697 /*set authentication type */
13698 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13699
13700 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013701 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013702 return status;
13703 }
13704
13705 /*set key mgmt type */
13706 if (req->crypto.n_akm_suites) {
13707 status =
13708 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13709 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013710 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013711 return status;
13712 }
13713 }
13714
13715 /*set pairwise cipher type */
13716 if (req->crypto.n_ciphers_pairwise) {
13717 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13718 req->crypto.
13719 ciphers_pairwise[0],
13720 true);
13721 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013722 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013723 return status;
13724 }
13725 } else {
13726 /*Reset previous cipher suite to none */
13727 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13728 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013729 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013730 return status;
13731 }
13732 }
13733
13734 /*set group cipher type */
13735 status =
13736 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13737 false);
13738
13739 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013740 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013741 return status;
13742 }
13743#ifdef WLAN_FEATURE_11W
13744 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13745#endif
13746
13747 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13748 if (req->ie_len) {
13749 status =
13750 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13751 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013752 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013753 return status;
13754 }
13755 }
13756
13757 /*incase of WEP set default key information */
13758 if (req->key && req->key_len) {
13759 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13760 || (WLAN_CIPHER_SUITE_WEP104 ==
13761 req->crypto.ciphers_pairwise[0])
13762 ) {
13763 if (IW_AUTH_KEY_MGMT_802_1X
13764 ==
13765 (pWextState->
13766 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013767 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013768 return -EOPNOTSUPP;
13769 } else {
13770 u8 key_len = req->key_len;
13771 u8 key_idx = req->key_idx;
13772
13773 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
13774 key_len)
13775 && (CSR_MAX_NUM_KEY > key_idx)
13776 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013777 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013778 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013779 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013780 Keys.
13781 KeyMaterial[key_idx][0],
13782 req->key, key_len);
13783 pWextState->roamProfile.Keys.
13784 KeyLength[key_idx] = (u8) key_len;
13785 pWextState->roamProfile.Keys.
13786 defaultIndex = (u8) key_idx;
13787 }
13788 }
13789 }
13790 }
13791
13792 return status;
13793}
13794
13795/**
13796 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
13797 * @pAdapter: Pointer to adapter
13798 *
13799 * This function is used to disconnect from previous connection
13800 *
13801 * Return: 0 for success, non-zero for failure
13802 */
13803static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
13804{
13805 unsigned long rc;
13806 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013807 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013808
13809 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13810
Jeff Johnson9edf9572016-10-03 15:24:49 -070013811 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053013812 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
13813 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
13814 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013815 hdd_conn_set_connection_state(pAdapter,
13816 eConnectionState_Disconnecting);
13817 /* Issue disconnect to CSR */
13818 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013819
13820 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13821 pAdapter->sessionId,
13822 eCSR_DISCONNECT_REASON_UNSPECIFIED);
13823 /*
13824 * Wait here instead of returning directly, this will block the
13825 * next connect command and allow processing of the scan for
13826 * ssid and the previous connect command in CSR. Else we might
13827 * hit some race conditions leading to SME and HDD out of sync.
13828 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013829 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013830 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
13831 } else if (0 != status) {
13832 hdd_err("csrRoamDisconnect failure, returned %d",
13833 (int)status);
13834 pHddStaCtx->staDebugState = status;
13835 result = -EINVAL;
13836 goto disconnected;
13837 }
13838
13839 rc = wait_for_completion_timeout(
13840 &pAdapter->disconnect_comp_var,
13841 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013842 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013843 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
13844 pAdapter->sessionId, pHddStaCtx->staDebugState);
13845 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013846 }
13847 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013848 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013849 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013850 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013851 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013852 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013853 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013854 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013855 }
13856 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013857disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013858 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13859 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013860}
13861
13862/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013863 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
13864 * @adapter: Pointer to the HDD adapter
13865 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070013866 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013867 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013868 * This function will start reassociation if prev_bssid is set and bssid/
13869 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013870 *
Naveen Rawat07332902016-07-27 09:13:17 -070013871 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013872 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053013873#if defined(CFG80211_CONNECT_PREV_BSSID) || \
13874 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070013875static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13876 struct cfg80211_connect_params *req,
13877 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013878{
Naveen Rawat07332902016-07-27 09:13:17 -070013879 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013880 const uint8_t *bssid = NULL;
13881 uint16_t channel = 0;
13882
13883 if (req->bssid)
13884 bssid = req->bssid;
13885 else if (req->bssid_hint)
13886 bssid = req->bssid_hint;
13887
13888 if (req->channel)
13889 channel = req->channel->hw_value;
13890 else if (req->channel_hint)
13891 channel = req->channel_hint->hw_value;
13892
13893 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070013894 reassoc = true;
13895 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053013896 channel, MAC_ADDR_ARRAY(bssid));
13897 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013898 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070013899 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013900 }
Naveen Rawat07332902016-07-27 09:13:17 -070013901 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013902}
13903#else
Naveen Rawat07332902016-07-27 09:13:17 -070013904static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
13905 struct cfg80211_connect_params *req,
13906 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013907{
Naveen Rawat07332902016-07-27 09:13:17 -070013908 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013909}
13910#endif
13911
13912/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013913 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
13914 * @wiphy: Pointer to wiphy
13915 * @dev: Pointer to network device
13916 * @req: Pointer to cfg80211 connect request
13917 *
13918 * This function is used to start the association process
13919 *
13920 * Return: 0 for success, non-zero for failure
13921 */
13922static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13923 struct net_device *ndev,
13924 struct cfg80211_connect_params *req)
13925{
13926 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013927 u16 channel;
13928#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
13929 const u8 *bssid_hint = req->bssid_hint;
13930#else
13931 const u8 *bssid_hint = NULL;
13932#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013933 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
13934 hdd_context_t *pHddCtx;
13935
13936 ENTER();
13937
Anurag Chouhan6d760662016-02-20 16:05:43 +053013938 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013939 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013940 return -EINVAL;
13941 }
13942
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013943 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13944 hdd_err("invalid session id: %d", pAdapter->sessionId);
13945 return -EINVAL;
13946 }
13947
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013948 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013949 TRACE_CODE_HDD_CFG80211_CONNECT,
13950 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013951 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013952 hdd_device_mode_to_string(pAdapter->device_mode),
13953 pAdapter->device_mode);
13954
Krunal Sonib4326f22016-03-10 13:05:51 -080013955 if (pAdapter->device_mode != QDF_STA_MODE &&
13956 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013957 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013958 hdd_device_mode_to_string(pAdapter->device_mode),
13959 pAdapter->device_mode);
13960 return -EINVAL;
13961 }
13962
13963 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13964 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013965 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013966 return -EINVAL;
13967 }
13968
13969 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013970 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013971 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013972
Naveen Rawat07332902016-07-27 09:13:17 -070013973 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013974 return status;
13975
Agrawal Ashishf156e942016-08-04 14:54:47 +053013976 /* Try disconnecting if already in connected state */
13977 status = wlan_hdd_try_disconnect(pAdapter);
13978 if (0 > status) {
13979 hdd_err("Failed to disconnect the existing connection");
13980 return -EALREADY;
13981 }
13982
13983 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013984 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013985 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080013986 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013987 pAdapter->device_mode),
13988 req->channel->hw_value, HW_MODE_20_MHZ)) {
13989 hdd_err("This concurrency combination is not allowed");
13990 return -ECONNREFUSED;
13991 }
13992 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013993 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080013994 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013995 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
13996 hdd_err("This concurrency combination is not allowed");
13997 return -ECONNREFUSED;
13998 }
13999 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014000
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014001 /*initialise security parameters */
14002 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14003
14004 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014005 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014006 return status;
14007 }
14008
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014009 if (req->channel)
14010 channel = req->channel->hw_value;
14011 else
14012 channel = 0;
14013 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14014 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014015 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014016 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014017 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014018 return status;
14019 }
14020 EXIT();
14021 return status;
14022}
14023
14024/**
14025 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14026 * @wiphy: Pointer to wiphy
14027 * @dev: Pointer to network device
14028 * @req: Pointer to cfg80211 connect request
14029 *
14030 * Return: 0 for success, non-zero for failure
14031 */
14032static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14033 struct net_device *ndev,
14034 struct cfg80211_connect_params *req)
14035{
14036 int ret;
14037 cds_ssr_protect(__func__);
14038 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14039 cds_ssr_unprotect(__func__);
14040
14041 return ret;
14042}
14043
14044/**
14045 * wlan_hdd_disconnect() - hdd disconnect api
14046 * @pAdapter: Pointer to adapter
14047 * @reason: Disconnect reason code
14048 *
14049 * This function is used to issue a disconnect request to SME
14050 *
14051 * Return: 0 for success, non-zero for failure
14052 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014053static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014054{
14055 int status, result = 0;
14056 unsigned long rc;
14057 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14058 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14059
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014060 ENTER();
14061
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014062 status = wlan_hdd_validate_context(pHddCtx);
14063
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014064 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014065 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014066
14067 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014068 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014069 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
14070 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014071 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014072 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14073 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14074
14075 /*issue disconnect */
14076
14077 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14078 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053014079 /*
14080 * Wait here instead of returning directly, this will block the next
14081 * connect command and allow processing of the scan for ssid and
14082 * the previous connect command in CSR. Else we might hit some
14083 * race conditions leading to SME and HDD out of sync.
14084 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014085 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014086 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014087 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014088 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014089 (int)status);
14090 pHddStaCtx->staDebugState = status;
14091 result = -EINVAL;
14092 goto disconnected;
14093 }
14094 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14095 msecs_to_jiffies
14096 (WLAN_WAIT_TIME_DISCONNECT));
14097
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014098 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014099 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014100 result = -ETIMEDOUT;
14101 }
14102disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014103 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14104#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14105 /* Sending disconnect event to userspace for kernel version < 3.11
14106 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14107 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014108 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014109 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14110 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014111#endif
14112
14113 return result;
14114}
14115
14116/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014117 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14118 * @reason: ieee80211 reason code.
14119 *
14120 * This utility function helps log string conversion of reason code.
14121 *
14122 * Return: string conversion of reason code, if match found;
14123 * "Unknown" otherwise.
14124 */
14125static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14126{
14127 switch (reason) {
14128 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14129 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14130 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14131 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14132 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14133 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14134 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14135 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14136 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14137 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14138 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14139 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14140 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14141 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14142 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14143 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14144 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14145 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14146 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14147 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14148 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14149 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14150 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14151 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14152 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14153 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14154 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14155 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14156 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14157 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14158 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14159 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14160 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14161 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14162 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14163 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14164 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14165 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14166 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14167 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14168 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14169 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14170 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14171 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14172 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14173 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14174 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14175 default:
14176 return "Unknown";
14177 }
14178}
14179
14180/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014181 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14182 * @wiphy: Pointer to wiphy
14183 * @dev: Pointer to network device
14184 * @reason: Disconnect reason code
14185 *
14186 * This function is used to issue a disconnect request to SME
14187 *
14188 * Return: 0 for success, non-zero for failure
14189 */
14190static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14191 struct net_device *dev, u16 reason)
14192{
14193 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14194 int status;
14195 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14196 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14197#ifdef FEATURE_WLAN_TDLS
14198 uint8_t staIdx;
14199#endif
14200
14201 ENTER();
14202
Anurag Chouhan6d760662016-02-20 16:05:43 +053014203 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014204 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014205 return -EINVAL;
14206 }
14207
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014208 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14209 hdd_err("invalid session id: %d", pAdapter->sessionId);
14210 return -EINVAL;
14211 }
14212
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014213 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014214 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14215 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014216 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014217 hdd_device_mode_to_string(pAdapter->device_mode),
14218 pAdapter->device_mode, reason);
14219
14220 status = wlan_hdd_validate_context(pHddCtx);
14221
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080014222 if (hdd_is_roaming_in_progress()) {
14223 hdd_err("Roaming In Progress. Ignore!!!");
14224 return -EAGAIN;
14225 }
14226
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014227 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014228 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014229
14230 /* Issue disconnect request to SME, if station is in connected state */
14231 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14232 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14233 eCsrRoamDisconnectReason reasonCode =
14234 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14235 hdd_scaninfo_t *pScanInfo;
14236
14237 switch (reason) {
14238 case WLAN_REASON_MIC_FAILURE:
14239 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14240 break;
14241
14242 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14243 case WLAN_REASON_DISASSOC_AP_BUSY:
14244 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14245 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14246 break;
14247
14248 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14249 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14250 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14251 break;
14252
14253 case WLAN_REASON_DEAUTH_LEAVING:
14254 reasonCode =
14255 pHddCtx->config->
14256 gEnableDeauthToDisassocMap ?
14257 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14258 eCSR_DISCONNECT_REASON_DEAUTH;
14259 break;
14260 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14261 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14262 break;
14263 default:
14264 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14265 break;
14266 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014267 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014268 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014269 pScanInfo = &pAdapter->scan_info;
14270 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014271 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014272 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014273 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014274 eCSR_SCAN_ABORT_DEFAULT);
14275 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014276 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014277#ifdef FEATURE_WLAN_TDLS
14278 /* First clean up the tdls peers if any */
14279 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14280 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14281 pAdapter->sessionId)
14282 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14283 uint8_t *mac;
14284 mac =
14285 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014286 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
14287 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014288 pHddCtx->tdlsConnInfo[staIdx].staId,
14289 pAdapter->sessionId,
14290 MAC_ADDR_ARRAY(mac));
14291 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14292 (pAdapter),
14293 pAdapter->sessionId, mac);
14294 }
14295 }
14296#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014297 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014298 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014299 hdd_info("Disconnect request from user space with reason: %s",
14300 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014301 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14302 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014303 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014304 return -EINVAL;
14305 }
14306 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014307 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014308 pHddStaCtx->conn_info.connState);
14309 }
14310
14311 return status;
14312}
14313
14314/**
14315 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14316 * @wiphy: Pointer to wiphy
14317 * @dev: Pointer to network device
14318 * @reason: Disconnect reason code
14319 *
14320 * Return: 0 for success, non-zero for failure
14321 */
14322static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14323 struct net_device *dev, u16 reason)
14324{
14325 int ret;
14326 cds_ssr_protect(__func__);
14327 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14328 cds_ssr_unprotect(__func__);
14329
14330 return ret;
14331}
14332
14333/**
14334 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14335 * @pAdapter: Pointer to adapter
14336 * @param: Pointer to IBSS parameters
14337 *
14338 * This function is used to initialize the security settings in IBSS mode
14339 *
14340 * Return: 0 for success, non-zero for failure
14341 */
14342static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14343 struct cfg80211_ibss_params
14344 *params)
14345{
14346 int status = 0;
14347 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14348 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14349 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14350
14351 ENTER();
14352
14353 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014354 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014355 pHddStaCtx->ibss_enc_key_installed = 0;
14356
14357 if (params->ie_len && (NULL != params->ie)) {
14358 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14359 params->ie_len, WLAN_EID_RSN)) {
14360 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14361 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14362 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14363 tDot11fIEWPA dot11WPAIE;
14364 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14365 u8 *ie;
14366
14367 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14368 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14369 params->ie_len,
14370 DOT11F_EID_WPA);
14371 if (NULL != ie) {
14372 pWextState->wpaVersion =
14373 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014374 /* Unpack the WPA IE
14375 * Skip past the EID byte and length byte
14376 * and four byte WiFi OUI
14377 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014378 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14379 &ie[2 + 4],
14380 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014381 /* Extract the multicast cipher, the
14382 * encType for unicast cipher for
14383 * wpa-none is none
14384 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014385 encryptionType =
14386 hdd_translate_wpa_to_csr_encryption_type
14387 (dot11WPAIE.multicast_cipher);
14388 }
14389 }
14390
14391 status =
14392 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14393 params->ie_len);
14394
14395 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014396 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014397 return status;
14398 }
14399 }
14400
14401 pWextState->roamProfile.AuthType.authType[0] =
14402 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14403
14404 if (params->privacy) {
14405 /* Security enabled IBSS, At this time there is no information
14406 * available about the security paramters, so initialise the
14407 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14408 * The correct security parameters will be updated later in
14409 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14410 * set inorder enable privacy bit in beacons
14411 */
14412
14413 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14414 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014415 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014416 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14417 pWextState->roamProfile.EncryptionType.numEntries = 1;
14418 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14419 encryptionType;
14420 return status;
14421}
14422
14423/**
14424 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14425 * @wiphy: Pointer to wiphy
14426 * @dev: Pointer to network device
14427 * @param: Pointer to IBSS join parameters
14428 *
14429 * This function is used to create/join an IBSS network
14430 *
14431 * Return: 0 for success, non-zero for failure
14432 */
14433static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14434 struct net_device *dev,
14435 struct cfg80211_ibss_params *params)
14436{
14437 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14438 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14439 tCsrRoamProfile *pRoamProfile;
14440 int status;
14441 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14442 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014443 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014444 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014445
14446 ENTER();
14447
Anurag Chouhan6d760662016-02-20 16:05:43 +053014448 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014449 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014450 return -EINVAL;
14451 }
14452
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014453 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14454 hdd_err("invalid session id: %d", pAdapter->sessionId);
14455 return -EINVAL;
14456 }
14457
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014458 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014459 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14460 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014461 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014462 hdd_device_mode_to_string(pAdapter->device_mode),
14463 pAdapter->device_mode);
14464
14465 status = wlan_hdd_validate_context(pHddCtx);
14466
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014467 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014468 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014469
14470 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014471 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014472 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14473 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14474 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14475 int indx;
14476
14477 /* Get channel number */
14478 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014479 params->
14480 chandef.
14481 chan->
14482 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014483
14484 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14485 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014486 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014487 return -EOPNOTSUPP;
14488 }
14489
14490 for (indx = 0; indx < numChans; indx++) {
14491 if (channelNum == validChan[indx]) {
14492 break;
14493 }
14494 }
14495 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014496 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014497 return -EINVAL;
14498 }
14499 }
14500
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080014501 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014502 HW_MODE_20_MHZ)) {
14503 hdd_err("This concurrency combination is not allowed");
14504 return -ECONNREFUSED;
14505 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014506
Krunal Soni3091bcc2016-06-23 12:28:21 -070014507 status = qdf_reset_connection_update();
14508 if (!QDF_IS_STATUS_SUCCESS(status))
14509 hdd_err("ERR: clear event failed");
14510
14511 status = cds_current_connections_update(pAdapter->sessionId,
14512 channelNum,
14513 SIR_UPDATE_REASON_JOIN_IBSS);
14514 if (QDF_STATUS_E_FAILURE == status) {
14515 hdd_err("ERROR: connections update failed!!");
14516 return -EINVAL;
14517 }
14518
14519 if (QDF_STATUS_SUCCESS == status) {
14520 status = qdf_wait_for_connection_update();
14521 if (!QDF_IS_STATUS_SUCCESS(status)) {
14522 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014523 return -EINVAL;
14524 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014525 }
14526
14527 /*Try disconnecting if already in connected state */
14528 status = wlan_hdd_try_disconnect(pAdapter);
14529 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014530 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014531 return -EALREADY;
14532 }
14533
14534 pRoamProfile = &pWextState->roamProfile;
14535
14536 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014537 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014538 return -EINVAL;
14539 }
14540
14541 /* enable selected protection checks in IBSS mode */
14542 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14543
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014544 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014545 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14546 pHddCtx->config->
14547 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014548 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014549 }
14550
14551 /* BSSID is provided by upper layers hence no need to AUTO generate */
14552 if (NULL != params->bssid) {
14553 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014554 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014555 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014556 return -EIO;
14557 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014558 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014559 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14560 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014561 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014562 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014563 return -EIO;
14564 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014565 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014566 }
14567 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14568 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14569 pRoamProfile->beaconInterval = params->beacon_interval;
14570 else {
14571 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014572 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014573 params->beacon_interval, pRoamProfile->beaconInterval);
14574 }
14575
14576 /* Set Channel */
14577 if (channelNum) {
14578 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014579 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014580 pRoamProfile->ChannelInfo.numOfChannels = 1;
14581 pHddStaCtx->conn_info.operationChannel = channelNum;
14582 pRoamProfile->ChannelInfo.ChannelList =
14583 &pHddStaCtx->conn_info.operationChannel;
14584 }
14585
14586 /* Initialize security parameters */
14587 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14588 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014589 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014590 return status;
14591 }
14592
14593 /* Issue connect start */
14594 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14595 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014596 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014597 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014598 operationChannel,
14599 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014600
14601 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014602 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014603 return status;
14604 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014605 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014606 return 0;
14607}
14608
14609/**
14610 * wlan_hdd_cfg80211_join_ibss() - join ibss
14611 * @wiphy: Pointer to wiphy
14612 * @dev: Pointer to network device
14613 * @param: Pointer to IBSS join parameters
14614 *
14615 * This function is used to create/join an IBSS network
14616 *
14617 * Return: 0 for success, non-zero for failure
14618 */
14619static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14620 struct net_device *dev,
14621 struct cfg80211_ibss_params *params)
14622{
14623 int ret = 0;
14624
14625 cds_ssr_protect(__func__);
14626 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14627 cds_ssr_unprotect(__func__);
14628
14629 return ret;
14630}
14631
14632/**
14633 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14634 * @wiphy: Pointer to wiphy
14635 * @dev: Pointer to network device
14636 *
14637 * This function is used to leave an IBSS network
14638 *
14639 * Return: 0 for success, non-zero for failure
14640 */
14641static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14642 struct net_device *dev)
14643{
14644 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14645 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14646 tCsrRoamProfile *pRoamProfile;
14647 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14648 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014649 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014650 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014651 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014652
14653 ENTER();
14654
Anurag Chouhan6d760662016-02-20 16:05:43 +053014655 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014656 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014657 return -EINVAL;
14658 }
14659
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014660 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14661 hdd_err("invalid session id: %d", pAdapter->sessionId);
14662 return -EINVAL;
14663 }
14664
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014665 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014666 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14667 pAdapter->sessionId,
14668 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14669 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014670 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014671 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014672
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014673 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014674 hdd_device_mode_to_string(pAdapter->device_mode),
14675 pAdapter->device_mode);
14676 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014677 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014678 return -EIO;
14679 }
14680
14681 pRoamProfile = &pWextState->roamProfile;
14682
14683 /* Issue disconnect only if interface type is set to IBSS */
14684 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014685 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014686 return -EINVAL;
14687 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014688 /* Clearing add IE of beacon */
14689 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14690 sizeof(tSirMacAddr));
14691 updateIE.smeSessionId = pAdapter->sessionId;
14692 updateIE.ieBufferlength = 0;
14693 updateIE.pAdditionIEBuffer = NULL;
14694 updateIE.append = true;
14695 updateIE.notify = true;
14696 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14697 &updateIE,
14698 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014699 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014700 }
14701
14702 /* Reset WNI_CFG_PROBE_RSP Flags */
14703 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014704
14705 /* Issue Disconnect request */
14706 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14707 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14708 pAdapter->sessionId,
14709 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014710 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014711 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014712 hal_status);
14713 return -EAGAIN;
14714 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014715
14716 /* wait for mc thread to cleanup and then return to upper stack
14717 * so by the time upper layer calls the change interface, we are
14718 * all set to proceed further
14719 */
14720 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14721 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14722 if (!rc) {
14723 hdd_err("Failed to disconnect, timed out");
14724 return -ETIMEDOUT;
14725 }
14726
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014727 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014728 return 0;
14729}
14730
14731/**
14732 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14733 * @wiphy: Pointer to wiphy
14734 * @dev: Pointer to network device
14735 *
14736 * This function is used to leave an IBSS network
14737 *
14738 * Return: 0 for success, non-zero for failure
14739 */
14740static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14741 struct net_device *dev)
14742{
14743 int ret = 0;
14744
14745 cds_ssr_protect(__func__);
14746 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14747 cds_ssr_unprotect(__func__);
14748
14749 return ret;
14750}
14751
14752/**
14753 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14754 * @wiphy: Pointer to wiphy
14755 * @changed: Parameters changed
14756 *
14757 * This function is used to set the phy parameters. RTS Threshold/FRAG
14758 * Threshold/Retry Count etc.
14759 *
14760 * Return: 0 for success, non-zero for failure
14761 */
14762static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
14763 u32 changed)
14764{
14765 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14766 tHalHandle hHal = pHddCtx->hHal;
14767 int status;
14768
14769 ENTER();
14770
Anurag Chouhan6d760662016-02-20 16:05:43 +053014771 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014772 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014773 return -EINVAL;
14774 }
14775
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014776 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014777 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
14778 NO_SESSION, wiphy->rts_threshold));
14779 status = wlan_hdd_validate_context(pHddCtx);
14780
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014781 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014782 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014783
14784 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
14785 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
14786 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
14787
14788 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
14789 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014790 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014791 rts_threshold);
14792 return -EINVAL;
14793 }
14794
14795 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
14796 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014797 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014798 rts_threshold);
14799 return -EIO;
14800 }
14801
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014802 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014803 }
14804
14805 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
14806 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
14807 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
14808 wiphy->frag_threshold;
14809
14810 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
14811 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014812 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014813 frag_threshold);
14814 return -EINVAL;
14815 }
14816
14817 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
14818 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014819 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014820 frag_threshold);
14821 return -EIO;
14822 }
14823
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014824 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014825 }
14826
14827 if ((changed & WIPHY_PARAM_RETRY_SHORT)
14828 || (changed & WIPHY_PARAM_RETRY_LONG)) {
14829 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
14830 wiphy->retry_short : wiphy->retry_long;
14831
14832 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
14833 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014834 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014835 return -EINVAL;
14836 }
14837
14838 if (changed & WIPHY_PARAM_RETRY_SHORT) {
14839 if (0 != sme_cfg_set_int(hHal,
14840 WNI_CFG_LONG_RETRY_LIMIT,
14841 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014842 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014843 retry_value);
14844 return -EIO;
14845 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014846 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014847 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
14848 if (0 != sme_cfg_set_int(hHal,
14849 WNI_CFG_SHORT_RETRY_LIMIT,
14850 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014851 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014852 retry_value);
14853 return -EIO;
14854 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014855 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014856 }
14857 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014858 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014859 return 0;
14860}
14861
14862/**
14863 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14864 * @wiphy: Pointer to wiphy
14865 * @changed: Parameters changed
14866 *
14867 * Return: 0 for success, non-zero for failure
14868 */
14869static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
14870{
14871 int ret;
14872
14873 cds_ssr_protect(__func__);
14874 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
14875 cds_ssr_unprotect(__func__);
14876
14877 return ret;
14878}
14879
14880/**
14881 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
14882 * key
14883 * @wiphy: Pointer to wiphy
14884 * @dev: Pointer to network device
14885 * @key_index: Key index
14886 *
14887 * Return: 0
14888 */
14889static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14890 struct net_device *netdev,
14891 u8 key_index)
14892{
14893 ENTER();
14894 return 0;
14895}
14896
14897/**
14898 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
14899 * wlan_hdd_set_default_mgmt_key
14900 * @wiphy: pointer to wiphy
14901 * @netdev: pointer to net_device structure
14902 * @key_index: key index
14903 *
14904 * Return: 0 on success, error number on failure
14905 */
14906static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
14907 struct net_device *netdev,
14908 u8 key_index)
14909{
14910 int ret;
14911
14912 cds_ssr_protect(__func__);
14913 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
14914 cds_ssr_unprotect(__func__);
14915
14916 return ret;
14917}
14918
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014919/**
14920 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
14921 * @wiphy: Pointer to wiphy
14922 * @dev: Pointer to network device
14923 * @params: Pointer to tx queue parameters
14924 *
14925 * Return: 0
14926 */
14927static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
14928 struct net_device *dev,
14929 struct ieee80211_txq_params *params)
14930{
14931 ENTER();
14932 return 0;
14933}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014934
14935/**
14936 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
14937 * @wiphy: pointer to wiphy
14938 * @netdev: pointer to net_device structure
14939 * @params: pointer to ieee80211_txq_params
14940 *
14941 * Return: 0 on success, error number on failure
14942 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014943static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
14944 struct net_device *dev,
14945 struct ieee80211_txq_params *params)
14946{
14947 int ret;
14948
14949 cds_ssr_protect(__func__);
14950 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
14951 cds_ssr_unprotect(__func__);
14952
14953 return ret;
14954}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014955
14956/**
14957 * __wlan_hdd_cfg80211_del_station() - delete station v2
14958 * @wiphy: Pointer to wiphy
14959 * @param: Pointer to delete station parameter
14960 *
14961 * Return: 0 for success, non-zero for failure
14962 */
14963static
14964int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14965 struct net_device *dev,
14966 struct tagCsrDelStaParams *pDelStaParams)
14967{
14968 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14969 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053014970 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014971 hdd_hostapd_state_t *hapd_state;
14972 int status;
14973 uint8_t staId;
14974 uint8_t *mac;
14975
14976 ENTER();
14977
Anurag Chouhan6d760662016-02-20 16:05:43 +053014978 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014979 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014980 return -EINVAL;
14981 }
14982
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014983 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14984 hdd_err("invalid session id: %d", pAdapter->sessionId);
14985 return -EINVAL;
14986 }
14987
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014988 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014989 TRACE_CODE_HDD_CFG80211_DEL_STA,
14990 pAdapter->sessionId, pAdapter->device_mode));
14991
14992 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14993 status = wlan_hdd_validate_context(pHddCtx);
14994
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014995 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014996 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014997
14998 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
14999
Krunal Sonib4326f22016-03-10 13:05:51 -080015000 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15001 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015002
15003 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15004 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015005 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015006 return 0;
15007 }
15008
Anurag Chouhanc5548422016-02-24 18:33:27 +053015009 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015010 uint16_t i;
15011 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15012 if ((pAdapter->aStaInfo[i].isUsed) &&
15013 (!pAdapter->aStaInfo[i].
15014 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015015 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015016 mac,
15017 pAdapter->aStaInfo[i].
15018 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015019 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015020 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15021 hdd_ipa_wlan_evt(pAdapter,
15022 pAdapter->
15023 aStaInfo[i].
15024 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015025 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015026 mac);
15027 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015028 hdd_notice("Delete STA with MAC::"
15029 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015030 MAC_ADDR_ARRAY(mac));
15031
15032 if (pHddCtx->dev_dfs_cac_status ==
15033 DFS_CAC_IN_PROGRESS)
15034 goto fn_end;
15035
Wei Song2f76f642016-11-18 16:32:53 +080015036 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015037 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015038 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015039 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015040 hdd_softap_sta_deauth(pAdapter,
15041 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015042 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015043 pAdapter->aStaInfo[i].
15044 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015045 qdf_status =
15046 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015047 &hapd_state->
15048 qdf_sta_disassoc_event,
15049 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015050 if (!QDF_IS_STATUS_SUCCESS(
15051 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015052 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015053 }
15054 }
15055 }
15056 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015057 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015058 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015059 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015060 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015061 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015062 hdd_notice("Skip DEL STA as this is not used::"
15063 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015064 MAC_ADDR_ARRAY(mac));
15065 return -ENOENT;
15066 }
15067
15068 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15069 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015070 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015071 }
15072
15073 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15074 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015075 hdd_notice("Skip DEL STA as deauth is in progress::"
15076 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015077 MAC_ADDR_ARRAY(mac));
15078 return -ENOENT;
15079 }
15080
15081 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15082
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015083 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015084 MAC_ADDR_ARRAY(mac));
15085
15086 /* Case: SAP in ACS selected DFS ch and client connected
15087 * Now Radar detected. Then if random channel is another
15088 * DFS ch then new CAC is initiated and no TX allowed.
15089 * So do not send any mgmt frames as it will timeout
15090 * during CAC.
15091 */
15092
15093 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15094 goto fn_end;
15095
Wei Song2f76f642016-11-18 16:32:53 +080015096 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015097 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15098 (pAdapter), pAdapter->sessionId,
15099 (uint8_t *)&pDelStaParams->peerMacAddr,
15100 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015101 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015102 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015103 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015104 pAdapter->aStaInfo[staId].isDeauthInProgress =
15105 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015106 hdd_notice("STA removal failed for ::"
15107 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015108 MAC_ADDR_ARRAY(mac));
15109 return -ENOENT;
15110 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015111 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015112 &hapd_state->
15113 qdf_sta_disassoc_event,
15114 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015115 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015116 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015117 }
15118 }
15119 }
15120
15121fn_end:
15122 EXIT();
15123 return 0;
15124}
15125
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015126#if defined(USE_CFG80211_DEL_STA_V2)
15127/**
15128 * wlan_hdd_del_station() - delete station wrapper
15129 * @adapter: pointer to the hdd adapter
15130 *
15131 * Return: None
15132 */
15133void wlan_hdd_del_station(hdd_adapter_t *adapter)
15134{
15135 struct station_del_parameters del_sta;
15136 del_sta.mac = NULL;
15137 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15138 del_sta.reason_code = eCsrForcedDeauthSta;
15139
15140 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15141 &del_sta);
15142}
15143#else
15144void wlan_hdd_del_station(hdd_adapter_t *adapter)
15145{
15146 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15147}
15148#endif
15149
15150#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015151/**
15152 * wlan_hdd_cfg80211_del_station() - delete station v2
15153 * @wiphy: Pointer to wiphy
15154 * @param: Pointer to delete station parameter
15155 *
15156 * Return: 0 for success, non-zero for failure
15157 */
15158int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15159 struct net_device *dev,
15160 struct station_del_parameters *param)
15161#else
15162/**
15163 * wlan_hdd_cfg80211_del_station() - delete station
15164 * @wiphy: Pointer to wiphy
15165 * @mac: Pointer to station mac address
15166 *
15167 * Return: 0 for success, non-zero for failure
15168 */
15169#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15170int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15171 struct net_device *dev,
15172 const uint8_t *mac)
15173#else
15174int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15175 struct net_device *dev,
15176 uint8_t *mac)
15177#endif
15178#endif
15179{
15180 int ret;
15181 struct tagCsrDelStaParams delStaParams;
15182
15183 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015184#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015185 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015186 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015187 return -EINVAL;
15188 }
15189 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15190 param->subtype, &delStaParams);
15191#else
15192 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15193 (SIR_MAC_MGMT_DEAUTH >> 4),
15194 &delStaParams);
15195#endif
15196 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15197 cds_ssr_unprotect(__func__);
15198
15199 return ret;
15200}
15201
15202/**
15203 * __wlan_hdd_cfg80211_add_station() - add station
15204 * @wiphy: Pointer to wiphy
15205 * @mac: Pointer to station mac address
15206 * @pmksa: Pointer to add station parameter
15207 *
15208 * Return: 0 for success, non-zero for failure
15209 */
15210static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15211 struct net_device *dev,
15212 const uint8_t *mac,
15213 struct station_parameters *params)
15214{
15215 int status = -EPERM;
15216#ifdef FEATURE_WLAN_TDLS
15217 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15218 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15219 u32 mask, set;
15220
15221 ENTER();
15222
Anurag Chouhan6d760662016-02-20 16:05:43 +053015223 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015224 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015225 return -EINVAL;
15226 }
15227
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015228 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15229 hdd_err("invalid session id: %d", pAdapter->sessionId);
15230 return -EINVAL;
15231 }
15232
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015233 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015234 TRACE_CODE_HDD_CFG80211_ADD_STA,
15235 pAdapter->sessionId, params->listen_interval));
15236
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015237 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015238 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015239
15240 mask = params->sta_flags_mask;
15241
15242 set = params->sta_flags_set;
15243
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015244 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015245 MAC_ADDR_ARRAY(mac));
15246
15247 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15248 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15249 status =
15250 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15251 }
15252 }
15253#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015254 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015255 return status;
15256}
15257
15258/**
15259 * wlan_hdd_cfg80211_add_station() - add station
15260 * @wiphy: Pointer to wiphy
15261 * @mac: Pointer to station mac address
15262 * @pmksa: Pointer to add station parameter
15263 *
15264 * Return: 0 for success, non-zero for failure
15265 */
15266#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15267static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15268 struct net_device *dev,
15269 const uint8_t *mac,
15270 struct station_parameters *params)
15271#else
15272static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15273 struct net_device *dev, uint8_t *mac,
15274 struct station_parameters *params)
15275#endif
15276{
15277 int ret;
15278
15279 cds_ssr_protect(__func__);
15280 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15281 cds_ssr_unprotect(__func__);
15282
15283 return ret;
15284}
15285
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015286/**
15287 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15288 * @wiphy: Pointer to wiphy
15289 * @dev: Pointer to network device
15290 * @pmksa: Pointer to set pmksa parameter
15291 *
15292 * Return: 0 for success, non-zero for failure
15293 */
15294static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15295 struct net_device *dev,
15296 struct cfg80211_pmksa *pmksa)
15297{
15298 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15299 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15300 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015301 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015302 int status;
15303 tPmkidCacheInfo pmk_id;
15304
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015305 ENTER();
15306
Anurag Chouhan6d760662016-02-20 16:05:43 +053015307 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015308 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015309 return -EINVAL;
15310 }
15311
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015312 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15313 hdd_err("invalid session id: %d", pAdapter->sessionId);
15314 return -EINVAL;
15315 }
15316
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015317 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015318 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015319 return -EINVAL;
15320 }
15321
15322 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015323 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015324 pmksa->bssid, pmksa->pmkid);
15325 return -EINVAL;
15326 }
15327
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015328 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015329 MAC_ADDR_ARRAY(pmksa->bssid));
15330
15331 status = wlan_hdd_validate_context(pHddCtx);
15332
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015333 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015334 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015335
15336 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15337
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015338 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15339 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015340
15341 /* Add to the PMKSA ID Cache in CSR */
15342 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15343 &pmk_id, 1, false);
15344
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015345 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015346 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15347 pAdapter->sessionId, result));
15348
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015349 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015350 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015351}
15352
15353/**
15354 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15355 * @wiphy: Pointer to wiphy
15356 * @dev: Pointer to network device
15357 * @pmksa: Pointer to set pmksa parameter
15358 *
15359 * Return: 0 for success, non-zero for failure
15360 */
15361static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15362 struct net_device *dev,
15363 struct cfg80211_pmksa *pmksa)
15364{
15365 int ret;
15366
15367 cds_ssr_protect(__func__);
15368 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15369 cds_ssr_unprotect(__func__);
15370
15371 return ret;
15372}
15373
15374/**
15375 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15376 * @wiphy: Pointer to wiphy
15377 * @dev: Pointer to network device
15378 * @pmksa: Pointer to pmksa parameter
15379 *
15380 * Return: 0 for success, non-zero for failure
15381 */
15382static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15383 struct net_device *dev,
15384 struct cfg80211_pmksa *pmksa)
15385{
15386 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15387 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15388 tHalHandle halHandle;
15389 int status = 0;
15390
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015391 ENTER();
15392
Anurag Chouhan6d760662016-02-20 16:05:43 +053015393 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015394 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015395 return -EINVAL;
15396 }
15397
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015398 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15399 hdd_err("invalid session id: %d", pAdapter->sessionId);
15400 return -EINVAL;
15401 }
15402
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015403 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015404 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015405 return -EINVAL;
15406 }
15407
15408 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015409 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015410 return -EINVAL;
15411 }
15412
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015413 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015414 MAC_ADDR_ARRAY(pmksa->bssid));
15415
15416 status = wlan_hdd_validate_context(pHddCtx);
15417
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015418 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015419 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015420
15421 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15422
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015423 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015424 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15425 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015426 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015427 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015428 sme_roam_del_pmkid_from_cache(halHandle,
15429 pAdapter->sessionId, pmksa->bssid,
15430 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015431 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015432 MAC_ADDR_ARRAY(pmksa->bssid));
15433 status = -EINVAL;
15434 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015435 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015436 return status;
15437}
15438
15439/**
15440 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15441 * @wiphy: Pointer to wiphy
15442 * @dev: Pointer to network device
15443 * @pmksa: Pointer to pmksa parameter
15444 *
15445 * Return: 0 for success, non-zero for failure
15446 */
15447static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15448 struct net_device *dev,
15449 struct cfg80211_pmksa *pmksa)
15450{
15451 int ret;
15452
15453 cds_ssr_protect(__func__);
15454 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15455 cds_ssr_unprotect(__func__);
15456
15457 return ret;
15458
15459}
15460
15461/**
15462 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15463 * @wiphy: Pointer to wiphy
15464 * @dev: Pointer to network device
15465 *
15466 * Return: 0 for success, non-zero for failure
15467 */
15468static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15469 struct net_device *dev)
15470{
15471 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15472 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15473 tHalHandle halHandle;
15474 int status = 0;
15475
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015476 ENTER();
15477
Anurag Chouhan6d760662016-02-20 16:05:43 +053015478 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015479 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015480 return -EINVAL;
15481 }
15482
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015483 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15484 hdd_err("invalid session id: %d", pAdapter->sessionId);
15485 return -EINVAL;
15486 }
15487
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015488 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015489
15490 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15491 status = wlan_hdd_validate_context(pHddCtx);
15492
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015493 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015494 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015495
15496 /* Retrieve halHandle */
15497 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15498
15499 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015500 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015501 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15502 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015503 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015504 status = -EINVAL;
15505 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015506 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015507 return status;
15508}
15509
15510/**
15511 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15512 * @wiphy: Pointer to wiphy
15513 * @dev: Pointer to network device
15514 *
15515 * Return: 0 for success, non-zero for failure
15516 */
15517static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15518 struct net_device *dev)
15519{
15520 int ret;
15521
15522 cds_ssr_protect(__func__);
15523 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15524 cds_ssr_unprotect(__func__);
15525
15526 return ret;
15527}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015528
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015529#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015530/**
15531 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15532 * @wiphy: Pointer to wiphy
15533 * @dev: Pointer to network device
15534 * @ftie: Pointer to fast transition ie parameter
15535 *
15536 * Return: 0 for success, non-zero for failure
15537 */
15538static int
15539__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15540 struct net_device *dev,
15541 struct cfg80211_update_ft_ies_params *ftie)
15542{
15543 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15544 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15545 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15546 int status;
15547
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015548 ENTER();
15549
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015550 status = wlan_hdd_validate_context(hdd_ctx);
15551 if (status)
15552 return status;
15553
Anurag Chouhan6d760662016-02-20 16:05:43 +053015554 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015555 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015556 return -EINVAL;
15557 }
15558
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015559 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15560 hdd_err("invalid session id: %d", pAdapter->sessionId);
15561 return -EINVAL;
15562 }
15563
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015564 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015565 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15566 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15567 /* Added for debug on reception of Re-assoc Req. */
15568 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015569 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015570 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015571 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015572 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015573 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015574 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015575
15576 /* Pass the received FT IEs to SME */
15577 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15578 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015579 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015580 return 0;
15581}
15582
15583/**
15584 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15585 * @wiphy: Pointer to wiphy
15586 * @dev: Pointer to network device
15587 * @ftie: Pointer to fast transition ie parameter
15588 *
15589 * Return: 0 for success, non-zero for failure
15590 */
15591static int
15592wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15593 struct net_device *dev,
15594 struct cfg80211_update_ft_ies_params *ftie)
15595{
15596 int ret;
15597
15598 cds_ssr_protect(__func__);
15599 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15600 cds_ssr_unprotect(__func__);
15601
15602 return ret;
15603}
15604#endif
15605
15606#ifdef WLAN_FEATURE_GTK_OFFLOAD
15607/**
15608 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
15609 * @callbackContext: Callback context
15610 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
15611 *
15612 * Callback rountine called upon receiving response for get offload info
15613 *
15614 * Return: none
15615 */
15616void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
15617 tpSirGtkOffloadGetInfoRspParams
15618 pGtkOffloadGetInfoRsp)
15619{
15620 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
15621 uint8_t tempReplayCounter[8];
15622 hdd_station_ctx_t *pHddStaCtx;
15623
15624 ENTER();
15625
15626 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015627 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015628 return;
15629 }
15630
15631 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015632 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015633 return;
15634 }
15635
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015636 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015637 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015638 return;
15639 }
15640
15641 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15642 /* Update replay counter */
15643 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
15644 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
15645
15646 {
15647 /* changing from little to big endian since supplicant
15648 * works on big endian format
15649 */
15650 int i;
15651 uint8_t *p =
15652 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
15653
15654 for (i = 0; i < 8; i++) {
15655 tempReplayCounter[7 - i] = (uint8_t) p[i];
15656 }
15657 }
15658
15659 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015660 cfg80211_gtk_rekey_notify(pAdapter->dev,
15661 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015662 tempReplayCounter, GFP_KERNEL);
15663}
15664
15665/**
15666 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15667 * @wiphy: Pointer to wiphy
15668 * @dev: Pointer to network device
15669 * @data: Pointer to rekey data
15670 *
15671 * This function is used to offload GTK rekeying job to the firmware.
15672 *
15673 * Return: 0 for success, non-zero for failure
15674 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015675static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015676int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15677 struct net_device *dev,
15678 struct cfg80211_gtk_rekey_data *data)
15679{
15680 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15681 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15682 hdd_station_ctx_t *pHddStaCtx;
15683 tHalHandle hHal;
15684 int result;
15685 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015686 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015687
15688 ENTER();
15689
Anurag Chouhan6d760662016-02-20 16:05:43 +053015690 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015691 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015692 return -EINVAL;
15693 }
15694
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015695 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15696 hdd_err("invalid session id: %d", pAdapter->sessionId);
15697 return -EINVAL;
15698 }
15699
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015700 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015701 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15702 pAdapter->sessionId, pAdapter->device_mode));
15703
15704 result = wlan_hdd_validate_context(pHddCtx);
15705
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015706 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015707 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015708
15709 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15710 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
15711 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015712 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015713 return -EAGAIN;
15714 }
15715
15716 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
15717 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
15718 NL80211_KCK_LEN);
15719 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
15720 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053015721 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015722 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015723 {
15724 /* changing from big to little endian since driver
15725 * works on little endian format
15726 */
15727 uint8_t *p =
15728 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
15729 ullKeyReplayCounter;
15730 int i;
15731
15732 for (i = 0; i < 8; i++) {
15733 p[7 - i] = data->replay_ctr[i];
15734 }
15735 }
15736
15737 if (true == pHddCtx->hdd_wlan_suspended) {
15738 /* if wlan is suspended, enable GTK offload directly from here */
15739 memcpy(&hddGtkOffloadReqParams,
15740 &pHddStaCtx->gtkOffloadReqParams,
15741 sizeof(tSirGtkOffloadParams));
15742 status =
15743 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
15744 pAdapter->sessionId);
15745
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015746 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015747 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015748 status);
15749 return -EINVAL;
15750 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015751 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015752 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015753 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015754 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015755 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015756 return result;
15757}
15758
15759/**
15760 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15761 * @wiphy: Pointer to wiphy
15762 * @dev: Pointer to network device
15763 * @data: Pointer to rekey data
15764 *
15765 * This function is used to offload GTK rekeying job to the firmware.
15766 *
15767 * Return: 0 for success, non-zero for failure
15768 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015769static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015770int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15771 struct net_device *dev,
15772 struct cfg80211_gtk_rekey_data *data)
15773{
15774 int ret;
15775
15776 cds_ssr_protect(__func__);
15777 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15778 cds_ssr_unprotect(__func__);
15779
15780 return ret;
15781}
15782#endif /*WLAN_FEATURE_GTK_OFFLOAD */
15783
15784/**
15785 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15786 * @wiphy: Pointer to wiphy
15787 * @dev: Pointer to network device
15788 * @param: Pointer to access control parameter
15789 *
15790 * Return: 0 for success, non-zero for failure
15791 */
15792static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15793 struct net_device *dev,
15794 const struct cfg80211_acl_data *params)
15795{
15796 int i;
15797 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15798 hdd_hostapd_state_t *pHostapdState;
15799 tsap_Config_t *pConfig;
15800 v_CONTEXT_t p_cds_context = NULL;
15801 hdd_context_t *pHddCtx;
15802 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015803 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015804
15805 ENTER();
15806
Anurag Chouhan6d760662016-02-20 16:05:43 +053015807 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015808 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015809 return -EINVAL;
15810 }
15811
15812 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015813 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015814 return -EINVAL;
15815 }
15816
15817 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15818 status = wlan_hdd_validate_context(pHddCtx);
15819
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015820 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015821 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015822
15823 p_cds_context = pHddCtx->pcds_context;
15824 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15825
15826 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015827 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015828 return -EINVAL;
15829 }
15830
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015831 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015832 params->n_acl_entries);
15833
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015834 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015835 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
15836 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080015837 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015838 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
15839
15840 /* default value */
15841 pConfig->num_accept_mac = 0;
15842 pConfig->num_deny_mac = 0;
15843
15844 /**
15845 * access control policy
15846 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
15847 * listed in hostapd.deny file.
15848 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
15849 * listed in hostapd.accept file.
15850 */
15851 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
15852 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
15853 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
15854 params->acl_policy) {
15855 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
15856 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015857 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015858 params->acl_policy);
15859 return -ENOTSUPP;
15860 }
15861
15862 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
15863 pConfig->num_accept_mac = params->n_acl_entries;
15864 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015865 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
15866 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015867 MAC_ADDR_ARRAY(
15868 params->mac_addrs[i].addr));
15869
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015870 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015871 params->mac_addrs[i].addr,
15872 sizeof(qcmacaddr));
15873 }
15874 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
15875 pConfig->num_deny_mac = params->n_acl_entries;
15876 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015877 hdd_notice("** Add ACL MAC entry %i in BlackList :"
15878 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015879 MAC_ADDR_ARRAY(
15880 params->mac_addrs[i].addr));
15881
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015882 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015883 params->mac_addrs[i].addr,
15884 sizeof(qcmacaddr));
15885 }
15886 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070015887 qdf_status = wlansap_set_mac_acl(
15888 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015889 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015890 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015891 return -EINVAL;
15892 }
15893 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015894 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015895 hdd_device_mode_to_string(pAdapter->device_mode),
15896 pAdapter->device_mode);
15897 return -EINVAL;
15898 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015899 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015900 return 0;
15901}
15902
15903/**
15904 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
15905 * __wlan_hdd_cfg80211_set_mac_acl
15906 * @wiphy: pointer to wiphy structure
15907 * @dev: pointer to net_device
15908 * @params: pointer to cfg80211_acl_data
15909 *
15910 * Return; 0 on success, error number otherwise
15911 */
15912static int
15913wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15914 struct net_device *dev,
15915 const struct cfg80211_acl_data *params)
15916{
15917 int ret;
15918
15919 cds_ssr_protect(__func__);
15920 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
15921 cds_ssr_unprotect(__func__);
15922
15923 return ret;
15924}
15925
15926#ifdef WLAN_NL80211_TESTMODE
15927#ifdef FEATURE_WLAN_LPHB
15928/**
15929 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
15930 * @pHddCtx: Pointer to hdd context
15931 * @lphbInd: Pointer to low power heart beat indication parameter
15932 *
15933 * Return: none
15934 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015935static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
15936 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015937{
15938 struct sk_buff *skb;
15939
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015940 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015941
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015942 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015943 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015944
15945 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015946 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015947 return;
15948 }
15949
15950 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
15951 wiphy, sizeof(tSirLPHBInd),
15952 GFP_ATOMIC);
15953 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015954 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015955 return;
15956 }
15957
15958 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015959 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015960 goto nla_put_failure;
15961 }
15962 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015963 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015964 goto nla_put_failure;
15965 }
15966 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015967 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015968 goto nla_put_failure;
15969 }
15970 cfg80211_testmode_event(skb, GFP_ATOMIC);
15971 return;
15972
15973nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015974 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015975 kfree_skb(skb);
15976
15977 return;
15978}
15979#endif /* FEATURE_WLAN_LPHB */
15980
15981/**
15982 * __wlan_hdd_cfg80211_testmode() - test mode
15983 * @wiphy: Pointer to wiphy
15984 * @data: Data pointer
15985 * @len: Data length
15986 *
15987 * Return: 0 for success, non-zero for failure
15988 */
15989static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
15990 void *data, int len)
15991{
15992 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
15993 int err;
15994 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15995
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015996 ENTER();
15997
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015998 err = wlan_hdd_validate_context(pHddCtx);
15999 if (err)
16000 return err;
16001
16002 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16003 len, wlan_hdd_tm_policy);
16004 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016005 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016006 return err;
16007 }
16008
16009 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016010 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016011 return -EINVAL;
16012 }
16013
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016014 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016015 TRACE_CODE_HDD_CFG80211_TESTMODE,
16016 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016017 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16018#ifdef FEATURE_WLAN_LPHB
16019 /* Low Power Heartbeat configuration request */
16020 case WLAN_HDD_TM_CMD_WLAN_HB:
16021 {
16022 int buf_len;
16023 void *buf;
16024 tSirLPHBReq *hb_params = NULL;
16025 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016026 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016027
16028 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016029 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016030 return -EINVAL;
16031 }
16032
16033 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16034 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16035
16036 hb_params_temp = (tSirLPHBReq *) buf;
16037 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
16038 && (hb_params_temp->params.lphbTcpParamReq.
16039 timePeriodSec == 0))
16040 return -EINVAL;
16041
16042 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016043 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016044 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016045 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016046 return -ENOMEM;
16047 }
16048
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016049 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016050 smeStatus =
16051 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
16052 hb_params,
16053 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016054 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016055 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016056 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016057 }
16058 return 0;
16059 }
16060#endif /* FEATURE_WLAN_LPHB */
16061
16062#if defined(QCA_WIFI_FTM)
16063 case WLAN_HDD_TM_CMD_WLAN_FTM:
16064 {
16065 int buf_len;
16066 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016067 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016068 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016069 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016070 return -EINVAL;
16071 }
16072
16073 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16074 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16075
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016076 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016077
16078 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16079
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016080 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016081 err = -EBUSY;
16082 break;
16083 }
16084#endif
16085
16086 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016087 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016088 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16089 return -EOPNOTSUPP;
16090 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016091 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016092 return err;
16093}
16094
16095/**
16096 * wlan_hdd_cfg80211_testmode() - test mode
16097 * @wiphy: Pointer to wiphy
16098 * @dev: Pointer to network device
16099 * @data: Data pointer
16100 * @len: Data length
16101 *
16102 * Return: 0 for success, non-zero for failure
16103 */
16104static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16105#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16106 struct wireless_dev *wdev,
16107#endif
16108 void *data, int len)
16109{
16110 int ret;
16111
16112 cds_ssr_protect(__func__);
16113 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16114 cds_ssr_unprotect(__func__);
16115
16116 return ret;
16117}
16118
16119#if defined(QCA_WIFI_FTM)
16120/**
16121 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16122 * @buf: Pointer to buffer
16123 * @buf_len: Buffer length
16124 *
16125 * Return: none
16126 */
16127void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16128{
16129 struct sk_buff *skb;
16130 hdd_context_t *hdd_ctx;
16131
16132 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016133 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016134 return;
16135 }
16136
Anurag Chouhan6d760662016-02-20 16:05:43 +053016137 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016138 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016139 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016140 return;
16141 }
16142
16143 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16144 buf_len, GFP_KERNEL);
16145 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016146 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016147 return;
16148 }
16149
16150 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16151 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16152 goto nla_put_failure;
16153
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016154 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016155
16156 cfg80211_testmode_event(skb, GFP_KERNEL);
16157 return;
16158
16159nla_put_failure:
16160 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016161 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016162}
16163#endif
16164#endif /* CONFIG_NL80211_TESTMODE */
16165
16166#ifdef QCA_HT_2040_COEX
16167/**
16168 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16169 * @wiphy: Pointer to wiphy
16170 * @dev: Pointer to network device
16171 * @chandef: Pointer to channel definition parameter
16172 *
16173 * Return: 0 for success, non-zero for failure
16174 */
16175static int
16176__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16177 struct net_device *dev,
16178 struct cfg80211_chan_def *chandef)
16179{
16180 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16181 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016182 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016183 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016184 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016185
Anurag Chouhan6d760662016-02-20 16:05:43 +053016186 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016187 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016188 return -EINVAL;
16189 }
16190
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016191 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16192 hdd_err("invalid session id: %d", pAdapter->sessionId);
16193 return -EINVAL;
16194 }
16195
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016196 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16197 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016198 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016199 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016200
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016201 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016202 sme_get_config_param(pHddCtx->hHal, &sme_config);
16203 switch (chandef->width) {
16204 case NL80211_CHAN_WIDTH_20:
16205 if (sme_config.csrConfig.channelBondingMode24GHz !=
16206 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16207 sme_config.csrConfig.channelBondingMode24GHz =
16208 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16209 sme_update_config(pHddCtx->hHal, &sme_config);
16210 cbModeChange = true;
16211 }
16212 break;
16213
16214 case NL80211_CHAN_WIDTH_40:
16215 if (sme_config.csrConfig.channelBondingMode24GHz ==
16216 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16217 if (NL80211_CHAN_HT40MINUS ==
16218 cfg80211_get_chandef_type(chandef))
16219 sme_config.csrConfig.channelBondingMode24GHz =
16220 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16221 else
16222 sme_config.csrConfig.channelBondingMode24GHz =
16223 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16224 sme_update_config(pHddCtx->hHal, &sme_config);
16225 cbModeChange = true;
16226 }
16227 break;
16228
16229 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016230 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016231 return -EINVAL;
16232 }
16233
16234 if (!cbModeChange)
16235 return 0;
16236
Krunal Sonib4326f22016-03-10 13:05:51 -080016237 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016238 return 0;
16239
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016240 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016241 sme_config.csrConfig.channelBondingMode24GHz);
16242
16243 /* Change SAP ht2040 mode */
16244 status = hdd_set_sap_ht2040_mode(pAdapter,
16245 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016246 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016247 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016248 return -EINVAL;
16249 }
16250
16251 return 0;
16252}
16253
16254/**
16255 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16256 * @wiphy: Pointer to wiphy
16257 * @dev: Pointer to network device
16258 * @chandef: Pointer to channel definition parameter
16259 *
16260 * Return: 0 for success, non-zero for failure
16261 */
16262static int
16263wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16264 struct net_device *dev,
16265 struct cfg80211_chan_def *chandef)
16266{
16267 int ret;
16268
16269 cds_ssr_protect(__func__);
16270 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16271 cds_ssr_unprotect(__func__);
16272
16273 return ret;
16274}
16275#endif
16276
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016277#ifdef CHANNEL_SWITCH_SUPPORTED
16278/**
16279 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16280 * channel in SAP/GO
16281 * @wiphy: wiphy pointer
16282 * @dev: dev pointer.
16283 * @csa_params: Change channel params
16284 *
16285 * This function is called to switch channel in SAP/GO
16286 *
16287 * Return: 0 if success else return non zero
16288 */
16289static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16290 struct net_device *dev,
16291 struct cfg80211_csa_settings *csa_params)
16292{
16293 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16294 hdd_context_t *hdd_ctx;
16295 uint8_t channel;
16296 uint16_t freq;
16297 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016298 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016299
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016300 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016301 csa_params->chandef.chan->center_freq);
16302
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016303 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16304 hdd_err("invalid session id: %d", adapter->sessionId);
16305 return -EINVAL;
16306 }
16307
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016308 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16309 ret = wlan_hdd_validate_context(hdd_ctx);
16310
16311 if (0 != ret)
16312 return ret;
16313
Krunal Sonib4326f22016-03-10 13:05:51 -080016314 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16315 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016316 return -ENOTSUPP;
16317
16318 freq = csa_params->chandef.chan->center_freq;
16319 channel = cds_freq_to_chan(freq);
16320
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016321 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16322
16323 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016324 return ret;
16325}
16326
16327/**
16328 * wlan_hdd_cfg80211_channel_switch()- function to switch
16329 * channel in SAP/GO
16330 * @wiphy: wiphy pointer
16331 * @dev: dev pointer.
16332 * @csa_params: Change channel params
16333 *
16334 * This function is called to switch channel in SAP/GO
16335 *
16336 * Return: 0 if success else return non zero
16337 */
16338static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16339 struct net_device *dev,
16340 struct cfg80211_csa_settings *csa_params)
16341{
16342 int ret;
16343
16344 cds_ssr_protect(__func__);
16345 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16346 cds_ssr_unprotect(__func__);
16347 return ret;
16348}
16349#endif
16350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016351/**
16352 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16353 * translation from NL to policy manager type
16354 * @type: Generic connection mode type defined in NL
16355 *
16356 *
16357 * This function provides the type translation
16358 *
16359 * Return: cds_con_mode enum
16360 */
16361enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
16362 enum nl80211_iftype type)
16363{
16364 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
16365 switch (type) {
16366 case NL80211_IFTYPE_STATION:
16367 mode = CDS_STA_MODE;
16368 break;
16369 case NL80211_IFTYPE_P2P_CLIENT:
16370 mode = CDS_P2P_CLIENT_MODE;
16371 break;
16372 case NL80211_IFTYPE_P2P_GO:
16373 mode = CDS_P2P_GO_MODE;
16374 break;
16375 case NL80211_IFTYPE_AP:
16376 mode = CDS_SAP_MODE;
16377 break;
16378 case NL80211_IFTYPE_ADHOC:
16379 mode = CDS_IBSS_MODE;
16380 break;
16381 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016382 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016383 type);
16384 }
16385 return mode;
16386}
16387
16388/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016389 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16390 * @wiphy: Handle to struct wiphy to get handle to module context.
16391 * @chandef: Contains information about the capture channel to be set.
16392 *
16393 * This interface is called if and only if monitor mode interface alone is
16394 * active.
16395 *
16396 * Return: 0 success or error code on failure.
16397 */
16398static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16399 struct cfg80211_chan_def *chandef)
16400{
16401 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16402 hdd_adapter_t *adapter;
16403 hdd_station_ctx_t *sta_ctx;
16404 struct hdd_mon_set_ch_info *ch_info;
16405 QDF_STATUS status;
16406 tHalHandle hal_hdl;
16407 struct qdf_mac_addr bssid;
16408 tCsrRoamProfile roam_profile;
16409 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016410 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016411 int ret;
16412 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16413
16414 ENTER();
16415
16416 ret = wlan_hdd_validate_context(hdd_ctx);
16417 if (ret)
16418 return ret;
16419
16420 hal_hdl = hdd_ctx->hHal;
16421
16422 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16423 if (!adapter)
16424 return -EIO;
16425
16426 hdd_info("%s: set monitor mode Channel %d and freq %d",
16427 adapter->dev->name, chan_num, chandef->chan->center_freq);
16428
16429 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16430 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016431 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16432 roam_profile.ChannelInfo.numOfChannels = 1;
16433 roam_profile.phyMode = ch_info->phy_mode;
16434 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016435 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016436
16437 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16438 QDF_MAC_ADDR_SIZE);
16439
16440 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016441 /*
16442 * CDS api expects secondary channel for calculating
16443 * the channel params
16444 */
16445 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16446 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16447 if (chan_num >= 1 && chan_num <= 5)
16448 sec_ch = chan_num + 4;
16449 else if (chan_num >= 6 && chan_num <= 13)
16450 sec_ch = chan_num - 4;
16451 }
16452 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016453 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16454 &roam_profile);
16455 if (status) {
16456 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
16457 status);
16458 ret = qdf_status_to_os_return(status);
16459 return ret;
16460 }
16461 EXIT();
16462 return 0;
16463}
16464
16465/**
16466 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16467 * @wiphy: Handle to struct wiphy to get handle to module context.
16468 * @chandef: Contains information about the capture channel to be set.
16469 *
16470 * This interface is called if and only if monitor mode interface alone is
16471 * active.
16472 *
16473 * Return: 0 success or error code on failure.
16474 */
16475static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16476 struct cfg80211_chan_def *chandef)
16477{
16478 int ret;
16479
16480 cds_ssr_protect(__func__);
16481 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16482 cds_ssr_unprotect(__func__);
16483 return ret;
16484}
16485
16486/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016487 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16488 * @adapter: pointer to adapter
16489 *
16490 * Wrapper function to clear link layer stats.
16491 * return - void
16492 */
16493void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16494{
16495 tSirLLStatsClearReq link_layer_stats_clear_req;
16496 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16497
Mukul Sharma491021c2016-09-29 21:39:19 +053016498 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16499 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016500 link_layer_stats_clear_req.stopReq = 0;
16501 link_layer_stats_clear_req.reqId = 1;
16502 link_layer_stats_clear_req.staId = adapter->sessionId;
16503 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16504
16505 return;
16506}
16507
16508/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016509 * struct cfg80211_ops - cfg80211_ops
16510 *
16511 * @add_virtual_intf: Add virtual interface
16512 * @del_virtual_intf: Delete virtual interface
16513 * @change_virtual_intf: Change virtual interface
16514 * @change_station: Change station
16515 * @add_beacon: Add beacon in sap mode
16516 * @del_beacon: Delete beacon in sap mode
16517 * @set_beacon: Set beacon in sap mode
16518 * @start_ap: Start ap
16519 * @change_beacon: Change beacon
16520 * @stop_ap: Stop ap
16521 * @change_bss: Change bss
16522 * @add_key: Add key
16523 * @get_key: Get key
16524 * @del_key: Delete key
16525 * @set_default_key: Set default key
16526 * @set_channel: Set channel
16527 * @scan: Scan
16528 * @connect: Connect
16529 * @disconnect: Disconnect
16530 * @join_ibss = Join ibss
16531 * @leave_ibss = Leave ibss
16532 * @set_wiphy_params = Set wiphy params
16533 * @set_tx_power = Set tx power
16534 * @get_tx_power = get tx power
16535 * @remain_on_channel = Remain on channel
16536 * @cancel_remain_on_channel = Cancel remain on channel
16537 * @mgmt_tx = Tx management frame
16538 * @mgmt_tx_cancel_wait = Cancel management tx wait
16539 * @set_default_mgmt_key = Set default management key
16540 * @set_txq_params = Set tx queue parameters
16541 * @get_station = Get station
16542 * @set_power_mgmt = Set power management
16543 * @del_station = Delete station
16544 * @add_station = Add station
16545 * @set_pmksa = Set pmksa
16546 * @del_pmksa = Delete pmksa
16547 * @flush_pmksa = Flush pmksa
16548 * @update_ft_ies = Update FT IEs
16549 * @tdls_mgmt = Tdls management
16550 * @tdls_oper = Tdls operation
16551 * @set_rekey_data = Set rekey data
16552 * @sched_scan_start = Scheduled scan start
16553 * @sched_scan_stop = Scheduled scan stop
16554 * @resume = Resume wlan
16555 * @suspend = Suspend wlan
16556 * @set_mac_acl = Set mac acl
16557 * @testmode_cmd = Test mode command
16558 * @set_ap_chanwidth = Set AP channel bandwidth
16559 * @dump_survey = Dump survey
16560 * @key_mgmt_set_pmk = Set pmk key management
16561 */
16562static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16563 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16564 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16565 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16566 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016567 .start_ap = wlan_hdd_cfg80211_start_ap,
16568 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16569 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016570 .change_bss = wlan_hdd_cfg80211_change_bss,
16571 .add_key = wlan_hdd_cfg80211_add_key,
16572 .get_key = wlan_hdd_cfg80211_get_key,
16573 .del_key = wlan_hdd_cfg80211_del_key,
16574 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16575 .scan = wlan_hdd_cfg80211_scan,
16576 .connect = wlan_hdd_cfg80211_connect,
16577 .disconnect = wlan_hdd_cfg80211_disconnect,
16578 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16579 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16580 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16581 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16582 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16583 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16584 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16585 .mgmt_tx = wlan_hdd_mgmt_tx,
16586 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16587 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16588 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016589 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016590 .get_station = wlan_hdd_cfg80211_get_station,
16591 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16592 .del_station = wlan_hdd_cfg80211_del_station,
16593 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016594 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16595 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16596 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016597#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016598 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16599#endif
16600#ifdef FEATURE_WLAN_TDLS
16601 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16602 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16603#endif
16604#ifdef WLAN_FEATURE_GTK_OFFLOAD
16605 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16606#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16607#ifdef FEATURE_WLAN_SCAN_PNO
16608 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16609 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16610#endif /*FEATURE_WLAN_SCAN_PNO */
16611 .resume = wlan_hdd_cfg80211_resume_wlan,
16612 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16613 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16614#ifdef WLAN_NL80211_TESTMODE
16615 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16616#endif
16617#ifdef QCA_HT_2040_COEX
16618 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16619#endif
16620 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016621#ifdef CHANNEL_SWITCH_SUPPORTED
16622 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16623#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016624 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016625#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16626 defined(CFG80211_ABORT_SCAN)
16627 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16628#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016629};