blob: 241d7b6819904a6d4081565b491f591af56321e0 [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 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001104#ifdef WLAN_UMAC_CONVERGENCE
1105 COMMON_VENDOR_EVENTS
1106#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001107};
1108
1109/**
1110 * __is_driver_dfs_capable() - get driver DFS capability
1111 * @wiphy: pointer to wireless wiphy structure.
1112 * @wdev: pointer to wireless_dev structure.
1113 * @data: Pointer to the data to be passed via vendor interface
1114 * @data_len:Length of the data to be passed
1115 *
1116 * This function is called by userspace to indicate whether or not
1117 * the driver supports DFS offload.
1118 *
1119 * Return: 0 on success, negative errno on failure
1120 */
1121static int __is_driver_dfs_capable(struct wiphy *wiphy,
1122 struct wireless_dev *wdev,
1123 const void *data,
1124 int data_len)
1125{
1126 u32 dfs_capability = 0;
1127 struct sk_buff *temp_skbuff;
1128 int ret_val;
1129 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1130
Jeff Johnson1f61b612016-02-12 16:28:33 -08001131 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132
1133 ret_val = wlan_hdd_validate_context(hdd_ctx);
1134 if (ret_val)
1135 return ret_val;
1136
Anurag Chouhan6d760662016-02-20 16:05:43 +05301137 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001138 hdd_err("Command not allowed in FTM mode");
1139 return -EPERM;
1140 }
1141
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001143
1144 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1145 NLMSG_HDRLEN);
1146
1147 if (temp_skbuff != NULL) {
1148 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1149 dfs_capability);
1150 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001151 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001152 kfree_skb(temp_skbuff);
1153
1154 return ret_val;
1155 }
1156
1157 return cfg80211_vendor_cmd_reply(temp_skbuff);
1158 }
1159
Jeff Johnson020db452016-06-29 14:37:26 -07001160 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001161 return -ENOMEM;
1162}
1163
1164/**
1165 * is_driver_dfs_capable() - get driver DFS capability
1166 * @wiphy: pointer to wireless wiphy structure.
1167 * @wdev: pointer to wireless_dev structure.
1168 * @data: Pointer to the data to be passed via vendor interface
1169 * @data_len:Length of the data to be passed
1170 *
1171 * This function is called by userspace to indicate whether or not
1172 * the driver supports DFS offload. This is an SSR-protected
1173 * wrapper function.
1174 *
1175 * Return: 0 on success, negative errno on failure
1176 */
1177static int is_driver_dfs_capable(struct wiphy *wiphy,
1178 struct wireless_dev *wdev,
1179 const void *data,
1180 int data_len)
1181{
1182 int ret;
1183
1184 cds_ssr_protect(__func__);
1185 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1186 cds_ssr_unprotect(__func__);
1187
1188 return ret;
1189}
1190
1191/**
1192 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1193 *
1194 * @adapter: SAP adapter pointer
1195 *
1196 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1197 * radio. So in case of DFS MCC scenario override current SAP given config
1198 * to follow concurrent SAP DFS config
1199 *
1200 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1201 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001202int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1203{
1204 hdd_adapter_t *con_sap_adapter;
1205 tsap_Config_t *sap_config, *con_sap_config;
1206 int con_ch;
1207
1208 /*
1209 * Check if AP+AP case, once primary AP chooses a DFS
1210 * channel secondary AP should always follow primary APs channel
1211 */
1212 if (!cds_concurrent_beaconing_sessions_running())
1213 return 0;
1214
1215 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1216 if (!con_sap_adapter)
1217 return 0;
1218
1219 sap_config = &adapter->sessionCtx.ap.sapConfig;
1220 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1221 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1222
1223 if (!CDS_IS_DFS_CH(con_ch))
1224 return 0;
1225
Jeff Johnson020db452016-06-29 14:37:26 -07001226 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001227 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001228 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001229 sap_config->channel = con_ch;
1230
1231 if (con_sap_config->acs_cfg.acs_mode == true) {
1232 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1233 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001234 hdd_err("Primary AP channel config error");
1235 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001236 con_ch, con_sap_config->acs_cfg.pri_ch,
1237 con_sap_config->acs_cfg.ht_sec_ch);
1238 return -EINVAL;
1239 }
1240 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1241 * MCC restriction. So free ch list allocated in do_acs
1242 * func for Sec AP and realloc for Pri AP ch list size
1243 */
1244 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301245 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301247 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248 &con_sap_config->acs_cfg,
1249 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301250 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001251 sizeof(uint8_t) *
1252 con_sap_config->acs_cfg.ch_list_count);
1253 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001254 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 return -ENOMEM;
1256 }
1257
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301258 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001259 con_sap_config->acs_cfg.ch_list,
1260 con_sap_config->acs_cfg.ch_list_count);
1261
1262 } else {
1263 sap_config->acs_cfg.pri_ch = con_ch;
1264 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1265 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1266 }
1267
1268 return con_ch;
1269}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001270
1271/**
1272 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1273 * @sap_cfg: pointer to SAP config struct
1274 *
1275 * This function sets the default ACS start and end channel for the given band
1276 * and also parses the given ACS channel list.
1277 *
1278 * Return: None
1279 */
1280
1281static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1282 bool vht_enabled)
1283{
1284 int i;
1285 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1286 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001287 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1288 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1290 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
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_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001293 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1294 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001295 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1296 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001297 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001299 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1300 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 }
1302
1303 if (ht_enabled)
1304 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1305
1306 if (vht_enabled)
1307 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1308
1309
1310 /* Parse ACS Chan list from hostapd */
1311 if (!sap_cfg->acs_cfg.ch_list)
1312 return;
1313
1314 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1315 sap_cfg->acs_cfg.end_ch =
1316 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1317 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301318 /* avoid channel as start channel */
1319 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1320 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001321 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1322 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1323 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1324 }
1325}
1326
1327
1328static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1329
1330/**
1331 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1332 * @adapter: pointer to SAP adapter struct
1333 *
1334 * This function starts the ACS procedure if there are no
1335 * constraints like MBSSID DFS restrictions.
1336 *
1337 * Return: Status of ACS Start procedure
1338 */
1339
1340static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1341{
1342
1343 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1344 tsap_Config_t *sap_config;
1345 tpWLAN_SAPEventCB acs_event_callback;
1346 int status;
1347
1348 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301349 if (hdd_ctx->acs_policy.acs_channel)
1350 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1351 else
1352 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001353
1354 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1355 if (status < 0) {
1356 return status;
1357 } else {
1358 if (status > 0) {
1359 /*notify hostapd about channel override */
1360 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1361 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1362 return 0;
1363 }
1364 }
1365 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1366 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001367 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001368 return -EINVAL;
1369 }
1370
1371 acs_event_callback = hdd_hostapd_sap_event_cb;
1372
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301373 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301374 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001375 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001378 acs_event_callback, sap_config, adapter->dev);
1379
1380
1381 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001382 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 return -EINVAL;
1384 }
1385 sap_config->acs_cfg.acs_mode = true;
1386 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1387
1388 return 0;
1389}
1390
1391/**
1392 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1393 * @wiphy: Linux wiphy struct pointer
1394 * @wdev: Linux wireless device struct pointer
1395 * @data: ACS information from hostapd
1396 * @data_len: ACS information length
1397 *
1398 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1399 * and starts ACS procedure.
1400 *
1401 * Return: ACS procedure start status
1402 */
1403
1404static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1405 struct wireless_dev *wdev,
1406 const void *data, int data_len)
1407{
1408 struct net_device *ndev = wdev->netdev;
1409 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1410 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1411 tsap_Config_t *sap_config;
1412 struct sk_buff *temp_skbuff;
1413 int status = -EINVAL, i = 0;
1414 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1415 bool ht_enabled, ht40_enabled, vht_enabled;
1416 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301417 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001418
1419 /* ***Note*** Donot set SME config related to ACS operation here because
1420 * ACS operation is not synchronouse and ACS for Second AP may come when
1421 * ACS operation for first AP is going on. So only do_acs is split to
1422 * seperate start_acs routine. Also SME-PMAC struct that is used to
1423 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1424 * config shall be set only from start_acs.
1425 */
1426
1427 /* nla_policy Policy template. Policy not applied as some attributes are
1428 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1429 *
1430 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1431 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1432 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1433 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1434 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1435 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1436 */
1437
Jeff Johnson1f61b612016-02-12 16:28:33 -08001438 ENTER_DEV(ndev);
1439
Anurag Chouhan6d760662016-02-20 16:05:43 +05301440 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001441 hdd_err("Command not allowed in FTM mode");
1442 return -EPERM;
1443 }
1444
1445 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001446 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001447 return -EPERM;
1448 }
1449
1450 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301451 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001452 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301453
Naveen Rawat64e477e2016-05-20 10:34:56 -07001454 if (cds_is_sub_20_mhz_enabled()) {
1455 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1456 status = -EINVAL;
1457 goto out;
1458 }
1459
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001460 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301461 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462
1463 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1464 NULL);
1465 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001466 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001467 goto out;
1468 }
1469
1470 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001471 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001472 goto out;
1473 }
1474 sap_config->acs_cfg.hw_mode = nla_get_u8(
1475 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1476
1477 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1478 ht_enabled =
1479 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1480 else
1481 ht_enabled = 0;
1482
1483 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1484 ht40_enabled =
1485 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1486 else
1487 ht40_enabled = 0;
1488
1489 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1490 vht_enabled =
1491 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1492 else
1493 vht_enabled = 0;
1494
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301495 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1496 vht_enabled = 0;
1497 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1498 }
1499
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001500 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1501 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1502 } else {
1503 if (ht_enabled && ht40_enabled)
1504 ch_width = 40;
1505 else
1506 ch_width = 20;
1507 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301508
1509 /* this may be possible, when sap_force_11n_for_11ac is set */
1510 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1511 if (ht_enabled && ht40_enabled)
1512 ch_width = 40;
1513 else
1514 ch_width = 20;
1515 }
1516
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001517 if (ch_width == 80)
1518 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1519 else if (ch_width == 40)
1520 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1521 else
1522 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1523
1524 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1525 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1526 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1527 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1528 * since it contains the frequency values of the channels in
1529 * the channel list.
1530 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1531 * is present
1532 */
1533 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1534 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1535 sap_config->acs_cfg.ch_list_count = nla_len(
1536 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1537 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301538 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001539 sizeof(uint8_t) *
1540 sap_config->acs_cfg.ch_list_count);
1541 if (sap_config->acs_cfg.ch_list == NULL)
1542 goto out;
1543
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301544 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545 sap_config->acs_cfg.ch_list_count);
1546 }
1547 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1548 uint32_t *freq =
1549 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1550 sap_config->acs_cfg.ch_list_count = nla_len(
1551 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1552 sizeof(uint32_t);
1553 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301554 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001555 sap_config->acs_cfg.ch_list_count);
1556 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001557 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558 status = -ENOMEM;
1559 goto out;
1560 }
1561
1562 /* convert frequency to channel */
1563 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1564 sap_config->acs_cfg.ch_list[i] =
1565 ieee80211_frequency_to_channel(freq[i]);
1566 }
1567 }
1568
1569 hdd_debug("get pcl for DO_ACS vendor command");
1570
1571 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001572 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301573 sap_config->acs_cfg.pcl_channels,
1574 &sap_config->acs_cfg.pcl_ch_count,
1575 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301576 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001577 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001578
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001579 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301580 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
1581 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07001582 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001583 vht_enabled = 1;
1584 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1585 sap_config->acs_cfg.ch_width =
1586 hdd_ctx->config->vhtChannelWidth;
1587 /* No VHT80 in 2.4G so perform ACS accordingly */
1588 if (sap_config->acs_cfg.end_ch <= 14 &&
1589 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1590 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1591 }
1592
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301593 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1594
Jeff Johnson020db452016-06-29 14:37:26 -07001595 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 -08001596 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1597 ch_width, ht_enabled, vht_enabled,
1598 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1599
1600 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001601 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001602 sap_config->acs_cfg.ch_list_count);
1603 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001604 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001605 }
1606 sap_config->acs_cfg.acs_mode = true;
1607 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001608 /* ***Note*** Completion variable usage is not allowed
1609 * here since ACS scan operation may take max 2.2 sec
1610 * for 5G band:
1611 * 9 Active channel X 40 ms active scan time +
1612 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001613 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1614 * for this long. So we split up the scanning part.
1615 */
1616 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001617 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001618 status = 0;
1619 } else {
1620 status = wlan_hdd_cfg80211_start_acs(adapter);
1621 }
1622
1623out:
1624 if (0 == status) {
1625 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1626 NLMSG_HDRLEN);
1627 if (temp_skbuff != NULL)
1628 return cfg80211_vendor_cmd_reply(temp_skbuff);
1629 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001630 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001631 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1632
1633 return status;
1634}
1635
Jeff Johnsonf3826e12017-01-12 09:49:40 -08001636/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001637 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1638 * @wiphy: Linux wiphy struct pointer
1639 * @wdev: Linux wireless device struct pointer
1640 * @data: ACS information from hostapd
1641 * @data_len: ACS information len
1642 *
1643 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1644 * and starts ACS procedure.
1645 *
1646 * Return: ACS procedure start status
1647 */
1648
1649static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1650 struct wireless_dev *wdev,
1651 const void *data, int data_len)
1652{
1653 int ret;
1654
1655 cds_ssr_protect(__func__);
1656 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1657 cds_ssr_unprotect(__func__);
1658
1659 return ret;
1660}
1661
1662/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001663 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
1664 * @adapter: Pointer to adapter struct
1665 *
1666 * This function handle cleanup of what was done in DO_ACS, including free
1667 * memory.
1668 *
1669 * Return: void
1670 */
1671
1672void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
1673{
1674 if (adapter == NULL)
1675 return;
1676 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
1677 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
1678 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
1679 }
1680}
1681
1682/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001683 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1684 * @work: Linux workqueue struct pointer for ACS work
1685 *
1686 * This function starts the ACS procedure which was marked pending when an ACS
1687 * procedure was in progress for a concurrent SAP interface.
1688 *
1689 * Return: None
1690 */
1691
1692static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1693{
1694 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1695 acs_pending_work.work);
1696 wlan_hdd_cfg80211_start_acs(adapter);
1697}
1698
1699/**
1700 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1701 * @adapter: Pointer to SAP adapter struct
1702 * @pri_channel: SAP ACS procedure selected Primary channel
1703 * @sec_channel: SAP ACS procedure selected secondary channel
1704 *
1705 * This is a callback function from SAP module on ACS procedure is completed.
1706 * This function send the ACS selected channel information to hostapd
1707 *
1708 * Return: None
1709 */
1710
1711void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1712{
1713 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1714 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1715 struct sk_buff *vendor_event;
1716 int ret_val;
1717 hdd_adapter_t *con_sap_adapter;
1718 uint16_t ch_width;
1719
1720 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001721 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001722 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1723 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1724 GFP_KERNEL);
1725
1726 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001727 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728 return;
1729 }
1730
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001731 ret_val = nla_put_u8(vendor_event,
1732 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1733 sap_cfg->acs_cfg.pri_ch);
1734 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001735 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736 kfree_skb(vendor_event);
1737 return;
1738 }
1739
1740 ret_val = nla_put_u8(vendor_event,
1741 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1742 sap_cfg->acs_cfg.ht_sec_ch);
1743 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001744 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001745 kfree_skb(vendor_event);
1746 return;
1747 }
1748
1749 ret_val = nla_put_u8(vendor_event,
1750 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1751 sap_cfg->acs_cfg.vht_seg0_center_ch);
1752 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001753 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001754 kfree_skb(vendor_event);
1755 return;
1756 }
1757
1758 ret_val = nla_put_u8(vendor_event,
1759 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1760 sap_cfg->acs_cfg.vht_seg1_center_ch);
1761 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001762 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001763 kfree_skb(vendor_event);
1764 return;
1765 }
1766
1767 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1768 ch_width = 80;
1769 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1770 ch_width = 40;
1771 else
1772 ch_width = 20;
1773
1774 ret_val = nla_put_u16(vendor_event,
1775 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1776 ch_width);
1777 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001778 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001779 kfree_skb(vendor_event);
1780 return;
1781 }
1782 if (sap_cfg->acs_cfg.pri_ch > 14)
1783 ret_val = nla_put_u8(vendor_event,
1784 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1785 QCA_ACS_MODE_IEEE80211A);
1786 else
1787 ret_val = nla_put_u8(vendor_event,
1788 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1789 QCA_ACS_MODE_IEEE80211G);
1790
1791 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001792 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001793 kfree_skb(vendor_event);
1794 return;
1795 }
1796
Jeff Johnson46b40792016-06-29 14:03:14 -07001797 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 -08001798 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1799 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1800 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1801
1802 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1803 /* ***Note*** As already mentioned Completion variable usage is not
1804 * allowed here since ACS scan operation may take max 2.2 sec.
1805 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1806 * operation.
1807 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1808 * when Primary AP ACS is complete and secondary AP ACS is started here
1809 * immediately, Primary AP start_bss may come inbetween ACS operation
1810 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1811 * delay. This path and below constraint will be removed on sessionizing
1812 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1813 * As per design constraint user space control application must take
1814 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1815 * this code path. Sec AP hostapd should be started after Primary AP
1816 * start beaconing which can be confirmed by getchannel iwpriv command
1817 */
1818
1819 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1820 if (con_sap_adapter &&
1821 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001822 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1823 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001824 /* Lets give 500ms for OBSS + START_BSS to complete */
1825 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1826 msecs_to_jiffies(500));
1827 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1828 }
1829
1830 return;
1831}
1832
1833static int
1834__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1835 struct wireless_dev *wdev,
1836 const void *data,
1837 int data_len)
1838{
1839 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1840 struct sk_buff *skb = NULL;
1841 uint32_t fset = 0;
1842 int ret;
1843
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001844 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301845
Anurag Chouhan6d760662016-02-20 16:05:43 +05301846 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 hdd_err("Command not allowed in FTM mode");
1848 return -EPERM;
1849 }
1850
1851 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301852 if (ret)
1853 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001854
1855 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001856 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001857 fset |= WIFI_FEATURE_INFRA;
1858 }
1859 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001860 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001861 fset |= WIFI_FEATURE_INFRA_5G;
1862 }
1863#ifdef WLAN_FEATURE_P2P
1864 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1865 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001866 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001867 fset |= WIFI_FEATURE_P2P;
1868 }
1869#endif
1870 fset |= WIFI_FEATURE_SOFT_AP;
1871
1872 /* HOTSPOT is a supplicant feature, enable it by default */
1873 fset |= WIFI_FEATURE_HOTSPOT;
1874
1875#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301876 if (pHddCtx->config->extscan_enabled &&
1877 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001878 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001879 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1880 }
1881#endif
1882 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001883 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001884 fset |= WIFI_FEATURE_NAN;
1885 }
1886 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001887 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888 fset |= WIFI_FEATURE_D2D_RTT;
1889 fset |= WIFI_FEATURE_D2AP_RTT;
1890 }
1891#ifdef FEATURE_WLAN_SCAN_PNO
1892 if (pHddCtx->config->configPNOScanSupport &&
1893 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001894 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001895 fset |= WIFI_FEATURE_PNO;
1896 }
1897#endif
1898 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1899#ifdef FEATURE_WLAN_TDLS
1900 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1901 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001902 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903 fset |= WIFI_FEATURE_TDLS;
1904 }
1905 if (sme_is_feature_supported_by_fw(TDLS) &&
1906 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1907 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001908 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1910 }
1911#endif
1912#ifdef WLAN_AP_STA_CONCURRENCY
1913 fset |= WIFI_FEATURE_AP_STA;
1914#endif
1915 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07001916 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001917
1918 if (hdd_link_layer_stats_supported())
1919 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1920
1921 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1922 NLMSG_HDRLEN);
1923 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001924 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001925 return -EINVAL;
1926 }
Jeff Johnson020db452016-06-29 14:37:26 -07001927 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001928 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001929 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930 goto nla_put_failure;
1931 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301932 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301933 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001934nla_put_failure:
1935 kfree_skb(skb);
1936 return -EINVAL;
1937}
1938
1939/**
1940 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1941 * @wiphy: pointer to wireless wiphy structure.
1942 * @wdev: pointer to wireless_dev structure.
1943 * @data: Pointer to the data to be passed via vendor interface
1944 * @data_len:Length of the data to be passed
1945 *
1946 * Return: Return the Success or Failure code.
1947 */
1948static int
1949wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1950 struct wireless_dev *wdev,
1951 const void *data, int data_len)
1952{
1953 int ret = 0;
1954
1955 cds_ssr_protect(__func__);
1956 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1957 data, data_len);
1958 cds_ssr_unprotect(__func__);
1959
1960 return ret;
1961}
1962
1963/**
1964 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1965 * @wiphy: pointer to wireless wiphy structure.
1966 * @wdev: pointer to wireless_dev structure.
1967 * @data: Pointer to the data to be passed via vendor interface
1968 * @data_len:Length of the data to be passed
1969 *
1970 * Set the MAC address that is to be used for scanning.
1971 *
1972 * Return: Return the Success or Failure code.
1973 */
1974static int
1975__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1976 struct wireless_dev *wdev,
1977 const void *data,
1978 int data_len)
1979{
1980 tpSirScanMacOui pReqMsg = NULL;
1981 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1982 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301983 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 int ret;
1985
Jeff Johnson1f61b612016-02-12 16:28:33 -08001986 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987
Anurag Chouhan6d760662016-02-20 16:05:43 +05301988 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 hdd_err("Command not allowed in FTM mode");
1990 return -EPERM;
1991 }
1992
1993 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301994 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001995 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001996
1997 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001998 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001999 return -ENOTSUPP;
2000 }
2001
2002 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2003 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002004 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005 return -EINVAL;
2006 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302007 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002008 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002009 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010 return -ENOMEM;
2011 }
2012 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002013 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002014 goto fail;
2015 }
2016 nla_memcpy(&pReqMsg->oui[0],
2017 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2018 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002019 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020 pReqMsg->oui[1], pReqMsg->oui[2]);
2021 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302022 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002023 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002024 goto fail;
2025 }
2026 return 0;
2027fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302028 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002029 return -EINVAL;
2030}
2031
2032/**
2033 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2034 * @wiphy: pointer to wireless wiphy structure.
2035 * @wdev: pointer to wireless_dev structure.
2036 * @data: Pointer to the data to be passed via vendor interface
2037 * @data_len:Length of the data to be passed
2038 *
2039 * Set the MAC address that is to be used for scanning. This is an
2040 * SSR-protecting wrapper function.
2041 *
2042 * Return: Return the Success or Failure code.
2043 */
2044static int
2045wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2046 struct wireless_dev *wdev,
2047 const void *data,
2048 int data_len)
2049{
2050 int ret;
2051
2052 cds_ssr_protect(__func__);
2053 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2054 data, data_len);
2055 cds_ssr_unprotect(__func__);
2056
2057 return ret;
2058}
2059
2060/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302061 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2062 * @wiphy: pointer phy adapter
2063 * @wdev: pointer to wireless device structure
2064 * @data: pointer to data buffer
2065 * @data_len: length of data
2066 *
2067 * This routine will give concurrency matrix
2068 *
2069 * Return: int status code
2070 */
2071static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2072 struct wireless_dev *wdev,
2073 const void *data,
2074 int data_len)
2075{
2076 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2077 uint8_t i, feature_sets, max_feature_sets;
2078 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2079 struct sk_buff *reply_skb;
2080 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2081 int ret;
2082
2083 ENTER_DEV(wdev->netdev);
2084
2085 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2086 hdd_err("Command not allowed in FTM mode");
2087 return -EPERM;
2088 }
2089
2090 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302091 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302092 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302093
2094 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2095 data, data_len, NULL)) {
2096 hdd_err("Invalid ATTR");
2097 return -EINVAL;
2098 }
2099
2100 /* Parse and fetch max feature set */
2101 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2102 hdd_err("Attr max feature set size failed");
2103 return -EINVAL;
2104 }
2105 max_feature_sets = nla_get_u32(tb[
2106 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2107 hdd_info("Max feature set size: %d", max_feature_sets);
2108
2109 /* Fill feature combination matrix */
2110 feature_sets = 0;
2111 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002112 WIFI_FEATURE_P2P;
2113 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2114 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302115 /* Add more feature combinations here */
2116
2117 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002118 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302119 hdd_info("Feature set matrix");
2120 for (i = 0; i < feature_sets; i++)
2121 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2122
2123 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2124 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2125 if (!reply_skb) {
2126 hdd_err("Feature set matrix: buffer alloc fail");
2127 return -ENOMEM;
2128 }
2129
2130 if (nla_put_u32(reply_skb,
2131 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2132 feature_sets) ||
2133 nla_put(reply_skb,
2134 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2135 sizeof(u32) * feature_sets,
2136 feature_set_matrix)) {
2137 hdd_err("nla put fail");
2138 kfree_skb(reply_skb);
2139 return -EINVAL;
2140 }
2141 return cfg80211_vendor_cmd_reply(reply_skb);
2142}
2143
2144/**
2145 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2146 * @wiphy: pointer to wireless wiphy structure.
2147 * @wdev: pointer to wireless_dev structure.
2148 * @data: Pointer to the data to be passed via vendor interface
2149 * @data_len:Length of the data to be passed
2150 *
2151 * Retrieves the concurrency feature set matrix
2152 *
2153 * Return: 0 on success, negative errno on failure
2154 */
2155static int
2156wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2157 struct wireless_dev *wdev,
2158 const void *data,
2159 int data_len)
2160{
2161 int ret;
2162
2163 cds_ssr_protect(__func__);
2164 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2165 data, data_len);
2166 cds_ssr_unprotect(__func__);
2167
2168 return ret;
2169}
2170
2171/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002172 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2173 * @feature_flags: pointer to the byte array of features.
2174 * @feature: Feature to be turned ON in the byte array.
2175 *
2176 * Return: None
2177 *
2178 * This is called to turn ON or SET the feature flag for the requested feature.
2179 **/
2180#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002181static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2182 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183{
2184 uint32_t index;
2185 uint8_t bit_mask;
2186
2187 index = feature / NUM_BITS_IN_BYTE;
2188 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2189 feature_flags[index] |= bit_mask;
2190}
2191
2192/**
2193 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2194 * @wiphy: pointer to wireless wiphy structure.
2195 * @wdev: pointer to wireless_dev structure.
2196 * @data: Pointer to the data to be passed via vendor interface
2197 * @data_len:Length of the data to be passed
2198 *
2199 * This is called when wlan driver needs to send supported feature set to
2200 * supplicant upon a request/query from the supplicant.
2201 *
2202 * Return: Return the Success or Failure code.
2203 **/
2204#define MAX_CONCURRENT_CHAN_ON_24G 2
2205#define MAX_CONCURRENT_CHAN_ON_5G 2
2206static int
2207__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2208 struct wireless_dev *wdev,
2209 const void *data, int data_len)
2210{
2211 struct sk_buff *skb = NULL;
2212 uint32_t dbs_capability = 0;
2213 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302214 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002215 int ret_val;
2216
2217 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2218 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2219
Jeff Johnson1f61b612016-02-12 16:28:33 -08002220 ENTER_DEV(wdev->netdev);
2221
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002222 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2223 if (ret_val)
2224 return ret_val;
2225
Anurag Chouhan6d760662016-02-20 16:05:43 +05302226 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002227 hdd_err("Command not allowed in FTM mode");
2228 return -EPERM;
2229 }
2230
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002231 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002232 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002233 wlan_hdd_cfg80211_set_feature(feature_flags,
2234 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2235 }
2236
2237 wlan_hdd_cfg80211_set_feature(feature_flags,
2238 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2239 if (wma_is_scan_simultaneous_capable())
2240 wlan_hdd_cfg80211_set_feature(feature_flags,
2241 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002242
2243 if (wma_is_p2p_lo_capable())
2244 wlan_hdd_cfg80211_set_feature(feature_flags,
2245 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2246
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002247 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2248 NLMSG_HDRLEN);
2249
2250 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002251 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002252 return -ENOMEM;
2253 }
2254
2255 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2256 sizeof(feature_flags), feature_flags))
2257 goto nla_put_failure;
2258
2259 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302260 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002261 if (one_by_one_dbs)
2262 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2263
2264 if (two_by_two_dbs)
2265 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2266
2267 if (!one_by_one_dbs && !two_by_two_dbs)
2268 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2269 } else {
2270 hdd_err("wma_get_dbs_hw_mode failed");
2271 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2272 }
2273
2274 hdd_info("dbs_capability is %d", dbs_capability);
2275
2276 if (nla_put_u32(skb,
2277 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2278 MAX_CONCURRENT_CHAN_ON_24G))
2279 goto nla_put_failure;
2280
2281 if (nla_put_u32(skb,
2282 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2283 MAX_CONCURRENT_CHAN_ON_5G))
2284 goto nla_put_failure;
2285
2286 return cfg80211_vendor_cmd_reply(skb);
2287
2288nla_put_failure:
2289 kfree_skb(skb);
2290 return -EINVAL;
2291}
2292
2293/**
2294 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2295 * @wiphy: pointer to wireless wiphy structure.
2296 * @wdev: pointer to wireless_dev structure.
2297 * @data: Pointer to the data to be passed via vendor interface
2298 * @data_len:Length of the data to be passed
2299 *
2300 * This is called when wlan driver needs to send supported feature set to
2301 * supplicant upon a request/query from the supplicant.
2302 *
2303 * Return: Return the Success or Failure code.
2304 */
2305static int
2306wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2307 struct wireless_dev *wdev,
2308 const void *data, int data_len)
2309{
2310 int ret;
2311
2312 cds_ssr_protect(__func__);
2313 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2314 data, data_len);
2315 cds_ssr_unprotect(__func__);
2316
2317 return ret;
2318}
2319
2320
2321/**
2322 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2323 * @wiphy: The wiphy structure
2324 * @wdev: The wireless device
2325 * @data: Data passed by framework
2326 * @data_len: Parameters to be configured passed as data
2327 *
2328 * The roaming related parameters are configured by the framework
2329 * using this interface.
2330 *
2331 * Return: Return either success or failure code.
2332 */
2333static int
2334__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2335 struct wireless_dev *wdev, const void *data, int data_len)
2336{
2337 struct net_device *dev = wdev->netdev;
2338 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2339 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2340 uint8_t session_id;
2341 struct roam_ext_params roam_params;
2342 uint32_t cmd_type, req_id;
2343 struct nlattr *curr_attr;
2344 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2345 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2346 int rem, i;
2347 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002348 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002349 int ret;
2350
Jeff Johnson1f61b612016-02-12 16:28:33 -08002351 ENTER_DEV(dev);
2352
Anurag Chouhan6d760662016-02-20 16:05:43 +05302353 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002354 hdd_err("Command not allowed in FTM mode");
2355 return -EPERM;
2356 }
2357
2358 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302359 if (ret)
2360 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002361
2362 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2363 data, data_len,
2364 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002365 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002366 return -EINVAL;
2367 }
2368 /* Parse and fetch Command Type*/
2369 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002370 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002371 goto fail;
2372 }
2373 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302374 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002375 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2376 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002377 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 goto fail;
2379 }
2380 req_id = nla_get_u32(
2381 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002382 hdd_debug("Req Id (%d)", req_id);
2383 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002384 switch (cmd_type) {
2385 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2386 i = 0;
2387 nla_for_each_nested(curr_attr,
2388 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2389 rem) {
2390 if (nla_parse(tb2,
2391 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2392 nla_data(curr_attr), nla_len(curr_attr),
2393 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002394 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002395 goto fail;
2396 }
2397 /* Parse and Fetch allowed SSID list*/
2398 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002399 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002400 goto fail;
2401 }
2402 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2403 /*
2404 * Upper Layers include a null termination character.
2405 * Check for the actual permissible length of SSID and
2406 * also ensure not to copy the NULL termination
2407 * character to the driver buffer.
2408 */
2409 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2410 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2411 nla_memcpy(
2412 roam_params.ssid_allowed_list[i].ssId,
2413 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2414 buf_len - 1);
2415 roam_params.ssid_allowed_list[i].length =
2416 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002417 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002418 roam_params.ssid_allowed_list[i].length,
2419 roam_params.ssid_allowed_list[i].ssId,
2420 roam_params.ssid_allowed_list[i].length);
2421 i++;
2422 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002423 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002424 }
2425 }
2426 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002427 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428 roam_params.num_ssid_allowed_list);
2429 sme_update_roam_params(pHddCtx->hHal, session_id,
2430 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2431 break;
2432 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2433 /* Parse and fetch 5G Boost Threshold */
2434 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002435 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002436 goto fail;
2437 }
2438 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2439 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002440 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002441 roam_params.raise_rssi_thresh_5g);
2442 /* Parse and fetch 5G Penalty Threshold */
2443 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002444 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 goto fail;
2446 }
2447 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2448 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002449 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450 roam_params.drop_rssi_thresh_5g);
2451 /* Parse and fetch 5G Boost Factor */
2452 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002453 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 goto fail;
2455 }
2456 roam_params.raise_factor_5g = nla_get_u32(
2457 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002458 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002459 roam_params.raise_factor_5g);
2460 /* Parse and fetch 5G Penalty factor */
2461 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002462 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 goto fail;
2464 }
2465 roam_params.drop_factor_5g = nla_get_u32(
2466 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002467 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002468 roam_params.drop_factor_5g);
2469 /* Parse and fetch 5G Max Boost */
2470 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002471 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002472 goto fail;
2473 }
2474 roam_params.max_raise_rssi_5g = nla_get_u32(
2475 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002476 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002477 roam_params.max_raise_rssi_5g);
2478 /* Parse and fetch Rssi Diff */
2479 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002480 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002481 goto fail;
2482 }
2483 roam_params.rssi_diff = nla_get_s32(
2484 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002485 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002486 roam_params.rssi_diff);
2487 /* Parse and fetch Alert Rssi Threshold */
2488 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002489 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002490 goto fail;
2491 }
2492 roam_params.alert_rssi_threshold = nla_get_u32(
2493 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002494 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002495 roam_params.alert_rssi_threshold);
2496 sme_update_roam_params(pHddCtx->hHal, session_id,
2497 roam_params,
2498 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2499 break;
2500 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2501 /* Parse and fetch Activate Good Rssi Roam */
2502 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002503 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002504 goto fail;
2505 }
2506 roam_params.good_rssi_roam = nla_get_s32(
2507 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002508 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 roam_params.good_rssi_roam);
2510 sme_update_roam_params(pHddCtx->hHal, session_id,
2511 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2512 break;
2513 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2514 /* Parse and fetch number of preferred BSSID */
2515 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002516 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002517 goto fail;
2518 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002519 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002520 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002521 if (count > MAX_BSSID_FAVORED) {
2522 hdd_err("Preferred BSSID count %u exceeds max %u",
2523 count, MAX_BSSID_FAVORED);
2524 goto fail;
2525 }
2526 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002527 i = 0;
2528 nla_for_each_nested(curr_attr,
2529 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2530 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002531
2532 if (i == count) {
2533 hdd_warn("Ignoring excess Preferred BSSID");
2534 break;
2535 }
2536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002537 if (nla_parse(tb2,
2538 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2539 nla_data(curr_attr), nla_len(curr_attr),
2540 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002541 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 goto fail;
2543 }
2544 /* Parse and fetch MAC address */
2545 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002546 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 goto fail;
2548 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002549 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002550 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302551 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002552 hdd_debug(MAC_ADDRESS_STR,
2553 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 /* Parse and fetch preference factor*/
2555 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002556 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 goto fail;
2558 }
2559 roam_params.bssid_favored_factor[i] = nla_get_u32(
2560 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002561 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002562 roam_params.bssid_favored_factor[i]);
2563 i++;
2564 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002565 if (i < count)
2566 hdd_warn("Num Preferred BSSID %u less than expected %u",
2567 i, count);
2568 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569 sme_update_roam_params(pHddCtx->hHal, session_id,
2570 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2571 break;
2572 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2573 /* Parse and fetch number of blacklist BSSID */
2574 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002575 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002576 goto fail;
2577 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002578 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08002580 if (count > MAX_BSSID_AVOID_LIST) {
2581 hdd_err("Blacklist BSSID count %u exceeds max %u",
2582 count, MAX_BSSID_AVOID_LIST);
2583 goto fail;
2584 }
2585 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002586 i = 0;
2587 nla_for_each_nested(curr_attr,
2588 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2589 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08002590
2591 if (i == count) {
2592 hdd_warn("Ignoring excess Blacklist BSSID");
2593 break;
2594 }
2595
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002596 if (nla_parse(tb2,
2597 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2598 nla_data(curr_attr), nla_len(curr_attr),
2599 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002600 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002601 goto fail;
2602 }
2603 /* Parse and fetch MAC address */
2604 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002605 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002606 goto fail;
2607 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002608 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302610 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002611 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002613 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002614 i++;
2615 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08002616 if (i < count)
2617 hdd_warn("Num Blacklist BSSID %u less than expected %u",
2618 i, count);
2619 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620 sme_update_roam_params(pHddCtx->hHal, session_id,
2621 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2622 break;
2623 }
2624 return 0;
2625fail:
2626 return -EINVAL;
2627}
2628
2629/**
2630 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2631 * @wiphy: pointer to wireless wiphy structure.
2632 * @wdev: pointer to wireless_dev structure.
2633 * @data: Pointer to the data to be passed via vendor interface
2634 * @data_len:Length of the data to be passed
2635 *
2636 * Return: Return the Success or Failure code.
2637 */
2638static int
2639wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2640 struct wireless_dev *wdev,
2641 const void *data,
2642 int data_len)
2643{
2644 int ret;
2645
2646 cds_ssr_protect(__func__);
2647 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2648 data, data_len);
2649 cds_ssr_unprotect(__func__);
2650
2651 return ret;
2652}
2653
2654static const struct nla_policy
2655wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2656 +1] = {
2657 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2658};
2659
2660/**
2661 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2662 * @hdd_ctx: HDD context
2663 * @device_mode: device mode
2664 * Return: bool
2665 */
2666static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002667 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002668{
2669 hdd_adapter_t *adapter;
2670 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2671 hdd_ap_ctx_t *ap_ctx;
2672 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302673 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002674
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302675 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676 &adapter_node);
2677
2678 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302679 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680 adapter = adapter_node->pAdapter;
2681
2682 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002683 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684 ap_ctx =
2685 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2686
2687 /*
2688 * if there is SAP already running on DFS channel,
2689 * do not disable scan on dfs channels. Note that
2690 * with SAP on DFS, there cannot be conurrency on
2691 * single radio. But then we can have multiple
2692 * radios !!
2693 */
2694 if (CHANNEL_STATE_DFS ==
2695 cds_get_channel_state(
2696 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002697 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002698 return true;
2699 }
2700 }
2701
2702 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002703 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002704 sta_ctx =
2705 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2706
2707 /*
2708 * if STA is already connected on DFS channel,
2709 * do not disable scan on dfs channels
2710 */
2711 if (hdd_conn_is_connected(sta_ctx) &&
2712 (CHANNEL_STATE_DFS ==
2713 cds_get_channel_state(
2714 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002715 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002716 return true;
2717 }
2718 }
2719
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302720 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002721 adapter_node,
2722 &next);
2723 adapter_node = next;
2724 }
2725
2726 return false;
2727}
2728
2729/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002730 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2731 * @hdd_ctx: HDD context within host driver
2732 * @adapter: Adapter pointer
2733 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2734 *
2735 * Loops through devices to see who is operating on DFS channels
2736 * and then disables/enables DFS channels by calling SME API.
2737 * Fails the disable request if any device is active on a DFS channel.
2738 *
2739 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002741
2742int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2743 hdd_adapter_t *adapter,
2744 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002745{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002746 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302747 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002748 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002749
2750 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2751 if (no_dfs_flag) {
2752 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002753 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002754
2755 if (true == status)
2756 return -EOPNOTSUPP;
2757
2758 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002759 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002760
2761 if (true == status)
2762 return -EOPNOTSUPP;
2763 }
2764
2765 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2766
2767 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2768
2769 /*
2770 * call the SME API to tunnel down the new channel list
2771 * to the firmware
2772 */
2773 status = sme_handle_dfs_chan_scan(
2774 h_hal, hdd_ctx->config->enableDFSChnlScan);
2775
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302776 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002777 ret_val = 0;
2778
2779 /*
2780 * Clear the SME scan cache also. Note that the
2781 * clearing of scan results is independent of session;
2782 * so no need to iterate over
2783 * all sessions
2784 */
2785 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302786 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 ret_val = -EPERM;
2788 }
2789
2790 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002791 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002792 ret_val = 0;
2793 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002794 return ret_val;
2795}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002797/**
2798 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2799 * @wiphy: corestack handler
2800 * @wdev: wireless device
2801 * @data: data
2802 * @data_len: data length
2803 * Return: success(0) or reason code for failure
2804 */
2805static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2806 struct wireless_dev *wdev,
2807 const void *data,
2808 int data_len)
2809{
2810 struct net_device *dev = wdev->netdev;
2811 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2812 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2813 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2814 int ret_val;
2815 uint32_t no_dfs_flag = 0;
2816
Jeff Johnson1f61b612016-02-12 16:28:33 -08002817 ENTER_DEV(dev);
2818
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002819 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302820 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002821 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002822
2823 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2824 data, data_len,
2825 wlan_hdd_set_no_dfs_flag_config_policy)) {
2826 hdd_err("invalid attr");
2827 return -EINVAL;
2828 }
2829
2830 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2831 hdd_err("attr dfs flag failed");
2832 return -EINVAL;
2833 }
2834
2835 no_dfs_flag = nla_get_u32(
2836 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2837
Jeff Johnson020db452016-06-29 14:37:26 -07002838 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002839
2840 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002841 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002842 return -EINVAL;
2843 }
2844
2845 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2846 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002847 return ret_val;
2848}
2849
2850/**
2851 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2852 *
2853 * @wiphy: wiphy device pointer
2854 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002855 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002856 * @data_len: Buffer length
2857 *
2858 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2859 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2860 *
2861 * Return: EOK or other error codes.
2862 */
2863
2864static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2865 struct wireless_dev *wdev,
2866 const void *data,
2867 int data_len)
2868{
2869 int ret;
2870
2871 cds_ssr_protect(__func__);
2872 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2873 data, data_len);
2874 cds_ssr_unprotect(__func__);
2875
2876 return ret;
2877}
2878
Manikandan Mohan80dea792016-04-28 16:36:48 -07002879static const struct nla_policy
2880wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2881 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2882};
2883
2884/**
2885 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2886 * @wiphy: wiphy device pointer
2887 * @wdev: wireless device pointer
2888 * @data: Vendor command data buffer
2889 * @data_len: Buffer length
2890 *
2891 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2892 * setup WISA Mode features.
2893 *
2894 * Return: Success(0) or reason code for failure
2895 */
2896static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2897 struct wireless_dev *wdev, const void *data, int data_len)
2898{
2899 struct net_device *dev = wdev->netdev;
2900 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2901 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2902 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2903 struct sir_wisa_params wisa;
2904 int ret_val;
2905 QDF_STATUS status;
2906 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07002907 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2908 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002909
2910 ENTER_DEV(dev);
2911 ret_val = wlan_hdd_validate_context(hdd_ctx);
2912 if (ret_val)
2913 goto err;
2914
2915 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2916 hdd_err("Command not allowed in FTM mode");
2917 return -EPERM;
2918 }
2919
2920 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2921 wlan_hdd_wisa_cmd_policy)) {
2922 hdd_err("Invalid WISA cmd attributes");
2923 ret_val = -EINVAL;
2924 goto err;
2925 }
2926 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2927 hdd_err("Invalid WISA mode");
2928 ret_val = -EINVAL;
2929 goto err;
2930 }
2931
2932 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2933 hdd_info("WISA Mode: %d", wisa_mode);
2934 wisa.mode = wisa_mode;
2935 wisa.vdev_id = adapter->sessionId;
2936 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002937 if (!QDF_IS_STATUS_SUCCESS(status)) {
2938 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002939 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002940 }
2941 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07002942 cdp_set_wisa_mode(soc,
2943 cdp_get_vdev_from_vdev_id(soc, pdev,
2944 adapter->sessionId),
2945 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002946err:
2947 EXIT();
2948 return ret_val;
2949}
2950
2951/**
2952 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2953 * @wiphy: corestack handler
2954 * @wdev: wireless device
2955 * @data: data
2956 * @data_len: data length
2957 *
2958 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2959 * setup WISA mode features.
2960 *
2961 * Return: Success(0) or reason code for failure
2962 */
2963static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2964 struct wireless_dev *wdev,
2965 const void *data,
2966 int data_len)
2967{
2968 int ret;
2969
2970 cds_ssr_protect(__func__);
2971 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2972 cds_ssr_unprotect(__func__);
2973
2974 return ret;
2975}
2976
Anurag Chouhan96919482016-07-13 16:36:57 +05302977/*
2978 * define short names for the global vendor params
2979 * used by __wlan_hdd_cfg80211_get_station_cmd()
2980 */
2981#define STATION_INVALID \
2982 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2983#define STATION_INFO \
2984 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2985#define STATION_ASSOC_FAIL_REASON \
2986 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2987#define STATION_MAX \
2988 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2989
2990static const struct nla_policy
2991hdd_get_station_policy[STATION_MAX + 1] = {
2992 [STATION_INFO] = {.type = NLA_FLAG},
2993 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2994};
2995
2996/**
2997 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2998 * @hdd_ctx: HDD context within host driver
2999 * @wdev: wireless device
3000 *
3001 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3002 * Validate cmd attributes and send the station info to upper layers.
3003 *
3004 * Return: Success(0) or reason code for failure
3005 */
3006static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3007 hdd_adapter_t *adapter)
3008{
3009 struct sk_buff *skb = NULL;
3010 uint32_t nl_buf_len;
3011 hdd_station_ctx_t *hdd_sta_ctx;
3012
3013 nl_buf_len = NLMSG_HDRLEN;
3014 nl_buf_len += sizeof(uint32_t);
3015 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3016
3017 if (!skb) {
3018 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3019 return -ENOMEM;
3020 }
3021
3022 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3023
3024 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3025 hdd_sta_ctx->conn_info.assoc_status_code)) {
3026 hdd_err("put fail");
3027 goto fail;
3028 }
3029 return cfg80211_vendor_cmd_reply(skb);
3030fail:
3031 if (skb)
3032 kfree_skb(skb);
3033 return -EINVAL;
3034}
3035
3036/**
3037 * hdd_map_auth_type() - transform auth type specific to
3038 * vendor command
3039 * @auth_type: csr auth type
3040 *
3041 * Return: Success(0) or reason code for failure
3042 */
3043static int hdd_convert_auth_type(uint32_t auth_type)
3044{
3045 uint32_t ret_val;
3046
3047 switch (auth_type) {
3048 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3049 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3050 break;
3051 case eCSR_AUTH_TYPE_SHARED_KEY:
3052 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3053 break;
3054 case eCSR_AUTH_TYPE_WPA:
3055 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3056 break;
3057 case eCSR_AUTH_TYPE_WPA_PSK:
3058 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3059 break;
3060 case eCSR_AUTH_TYPE_AUTOSWITCH:
3061 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3062 break;
3063 case eCSR_AUTH_TYPE_WPA_NONE:
3064 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3065 break;
3066 case eCSR_AUTH_TYPE_RSN:
3067 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3068 break;
3069 case eCSR_AUTH_TYPE_RSN_PSK:
3070 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3071 break;
3072 case eCSR_AUTH_TYPE_FT_RSN:
3073 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3074 break;
3075 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3076 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3077 break;
3078 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3079 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3080 break;
3081 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3082 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3083 break;
3084 case eCSR_AUTH_TYPE_CCKM_WPA:
3085 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3086 break;
3087 case eCSR_AUTH_TYPE_CCKM_RSN:
3088 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3089 break;
3090 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3091 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3092 break;
3093 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3094 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3095 break;
3096 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3097 case eCSR_AUTH_TYPE_FAILED:
3098 case eCSR_AUTH_TYPE_NONE:
3099 default:
3100 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3101 break;
3102 }
3103 return ret_val;
3104}
3105
3106/**
3107 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3108 * vendor command
3109 * @dot11mode: dot11mode
3110 *
3111 * Return: Success(0) or reason code for failure
3112 */
3113static int hdd_convert_dot11mode(uint32_t dot11mode)
3114{
3115 uint32_t ret_val;
3116
3117 switch (dot11mode) {
3118 case eCSR_CFG_DOT11_MODE_11A:
3119 ret_val = QCA_WLAN_802_11_MODE_11A;
3120 break;
3121 case eCSR_CFG_DOT11_MODE_11B:
3122 ret_val = QCA_WLAN_802_11_MODE_11B;
3123 break;
3124 case eCSR_CFG_DOT11_MODE_11G:
3125 ret_val = QCA_WLAN_802_11_MODE_11G;
3126 break;
3127 case eCSR_CFG_DOT11_MODE_11N:
3128 ret_val = QCA_WLAN_802_11_MODE_11N;
3129 break;
3130 case eCSR_CFG_DOT11_MODE_11AC:
3131 ret_val = QCA_WLAN_802_11_MODE_11AC;
3132 break;
3133 case eCSR_CFG_DOT11_MODE_AUTO:
3134 case eCSR_CFG_DOT11_MODE_ABG:
3135 default:
3136 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3137 }
3138 return ret_val;
3139}
3140
3141/**
3142 * hdd_add_tx_bitrate() - add tx bitrate attribute
3143 * @skb: pointer to sk buff
3144 * @hdd_sta_ctx: pointer to hdd station context
3145 * @idx: attribute index
3146 *
3147 * Return: Success(0) or reason code for failure
3148 */
3149static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3150 hdd_station_ctx_t *hdd_sta_ctx,
3151 int idx)
3152{
3153 struct nlattr *nla_attr;
3154 uint32_t bitrate, bitrate_compat;
3155
3156 nla_attr = nla_nest_start(skb, idx);
3157 if (!nla_attr)
3158 goto fail;
3159 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3160 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3161
3162 /* report 16-bit bitrate only if we can */
3163 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3164 if (bitrate > 0 &&
3165 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3166 hdd_err("put fail");
3167 goto fail;
3168 }
3169 if (bitrate_compat > 0 &&
3170 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3171 hdd_err("put fail");
3172 goto fail;
3173 }
3174 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3175 hdd_sta_ctx->conn_info.txrate.nss)) {
3176 hdd_err("put fail");
3177 goto fail;
3178 }
3179 nla_nest_end(skb, nla_attr);
3180 return 0;
3181fail:
3182 return -EINVAL;
3183}
3184
3185/**
3186 * hdd_add_sta_info() - add station info attribute
3187 * @skb: pointer to sk buff
3188 * @hdd_sta_ctx: pointer to hdd station context
3189 * @idx: attribute index
3190 *
3191 * Return: Success(0) or reason code for failure
3192 */
3193static int32_t hdd_add_sta_info(struct sk_buff *skb,
3194 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3195{
3196 struct nlattr *nla_attr;
3197
3198 nla_attr = nla_nest_start(skb, idx);
3199 if (!nla_attr)
3200 goto fail;
3201 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3202 (hdd_sta_ctx->conn_info.signal + 100))) {
3203 hdd_err("put fail");
3204 goto fail;
3205 }
3206 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3207 goto fail;
3208 nla_nest_end(skb, nla_attr);
3209 return 0;
3210fail:
3211 return -EINVAL;
3212}
3213
3214/**
3215 * hdd_add_survey_info() - add survey info attribute
3216 * @skb: pointer to sk buff
3217 * @hdd_sta_ctx: pointer to hdd station context
3218 * @idx: attribute index
3219 *
3220 * Return: Success(0) or reason code for failure
3221 */
3222static int32_t hdd_add_survey_info(struct sk_buff *skb,
3223 hdd_station_ctx_t *hdd_sta_ctx,
3224 int idx)
3225{
3226 struct nlattr *nla_attr;
3227
3228 nla_attr = nla_nest_start(skb, idx);
3229 if (!nla_attr)
3230 goto fail;
3231 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3232 hdd_sta_ctx->conn_info.freq) ||
3233 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3234 (hdd_sta_ctx->conn_info.noise + 100))) {
3235 hdd_err("put fail");
3236 goto fail;
3237 }
3238 nla_nest_end(skb, nla_attr);
3239 return 0;
3240fail:
3241 return -EINVAL;
3242}
3243
3244/**
3245 * hdd_add_link_standard_info() - add link info attribute
3246 * @skb: pointer to sk buff
3247 * @hdd_sta_ctx: pointer to hdd station context
3248 * @idx: attribute index
3249 *
3250 * Return: Success(0) or reason code for failure
3251 */
3252static int32_t
3253hdd_add_link_standard_info(struct sk_buff *skb,
3254 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3255{
3256 struct nlattr *nla_attr;
3257
3258 nla_attr = nla_nest_start(skb, idx);
3259 if (!nla_attr)
3260 goto fail;
3261 if (nla_put(skb,
3262 NL80211_ATTR_SSID,
3263 hdd_sta_ctx->conn_info.SSID.SSID.length,
3264 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3265 hdd_err("put fail");
3266 goto fail;
3267 }
3268 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3269 goto fail;
3270 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3271 goto fail;
3272 nla_nest_end(skb, nla_attr);
3273 return 0;
3274fail:
3275 return -EINVAL;
3276}
3277
3278/**
3279 * hdd_add_ap_standard_info() - add ap info attribute
3280 * @skb: pointer to sk buff
3281 * @hdd_sta_ctx: pointer to hdd station context
3282 * @idx: attribute index
3283 *
3284 * Return: Success(0) or reason code for failure
3285 */
3286static int32_t
3287hdd_add_ap_standard_info(struct sk_buff *skb,
3288 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3289{
3290 struct nlattr *nla_attr;
3291
3292 nla_attr = nla_nest_start(skb, idx);
3293 if (!nla_attr)
3294 goto fail;
3295 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3296 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3297 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3298 &hdd_sta_ctx->conn_info.vht_caps)) {
3299 hdd_err("put fail");
3300 goto fail;
3301 }
3302 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3303 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3304 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3305 &hdd_sta_ctx->conn_info.ht_caps)) {
3306 hdd_err("put fail");
3307 goto fail;
3308 }
3309 nla_nest_end(skb, nla_attr);
3310 return 0;
3311fail:
3312 return -EINVAL;
3313}
3314
3315/**
3316 * hdd_get_station_info() - send BSS information to supplicant
3317 * @hdd_ctx: pointer to hdd context
3318 * @adapter: pointer to adapter
3319 *
3320 * Return: 0 if success else error status
3321 */
3322static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3323 hdd_adapter_t *adapter)
3324{
3325 struct sk_buff *skb = NULL;
3326 uint8_t *tmp_hs20 = NULL;
3327 uint32_t nl_buf_len;
3328 hdd_station_ctx_t *hdd_sta_ctx;
3329
3330 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3331
3332 nl_buf_len = NLMSG_HDRLEN;
3333 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3334 sizeof(hdd_sta_ctx->conn_info.freq) +
3335 sizeof(hdd_sta_ctx->conn_info.noise) +
3336 sizeof(hdd_sta_ctx->conn_info.signal) +
3337 (sizeof(uint32_t) * 2) +
3338 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3339 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3340 sizeof(hdd_sta_ctx->conn_info.authType) +
3341 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3342 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3343 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3344 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3345 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3346 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3347 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3348 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3349 1);
3350 }
3351 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3352 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3353 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3354 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3355
3356
3357 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3358 if (!skb) {
3359 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3360 return -ENOMEM;
3361 }
3362
3363 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3364 LINK_INFO_STANDARD_NL80211_ATTR)) {
3365 hdd_err("put fail");
3366 goto fail;
3367 }
3368 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3369 AP_INFO_STANDARD_NL80211_ATTR)) {
3370 hdd_err("put fail");
3371 goto fail;
3372 }
3373 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3374 hdd_sta_ctx->conn_info.roam_count) ||
3375 nla_put_u32(skb, INFO_AKM,
3376 hdd_convert_auth_type(
3377 hdd_sta_ctx->conn_info.authType)) ||
3378 nla_put_u32(skb, WLAN802_11_MODE,
3379 hdd_convert_dot11mode(
3380 hdd_sta_ctx->conn_info.dot11Mode))) {
3381 hdd_err("put fail");
3382 goto fail;
3383 }
3384 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3385 if (nla_put(skb, HT_OPERATION,
3386 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3387 &hdd_sta_ctx->conn_info.ht_operation)) {
3388 hdd_err("put fail");
3389 goto fail;
3390 }
3391 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3392 if (nla_put(skb, VHT_OPERATION,
3393 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3394 &hdd_sta_ctx->conn_info.vht_operation)) {
3395 hdd_err("put fail");
3396 goto fail;
3397 }
3398 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3399 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3400 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3401 tmp_hs20 + 1)) {
3402 hdd_err("put fail");
3403 goto fail;
3404 }
3405
3406 return cfg80211_vendor_cmd_reply(skb);
3407fail:
3408 if (skb)
3409 kfree_skb(skb);
3410 return -EINVAL;
3411}
3412
3413/**
3414 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3415 * @wiphy: corestack handler
3416 * @wdev: wireless device
3417 * @data: data
3418 * @data_len: data length
3419 *
3420 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3421 * Validate cmd attributes and send the station info to upper layers.
3422 *
3423 * Return: Success(0) or reason code for failure
3424 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303425static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303426__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3427 struct wireless_dev *wdev,
3428 const void *data,
3429 int data_len)
3430{
3431 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3432 struct net_device *dev = wdev->netdev;
3433 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3434 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3435 int32_t status;
3436
3437 ENTER_DEV(dev);
3438 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3439 hdd_err("Command not allowed in FTM mode");
3440 status = -EPERM;
3441 goto out;
3442 }
3443
3444 status = wlan_hdd_validate_context(hdd_ctx);
3445 if (0 != status)
3446 goto out;
3447
3448
3449 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3450 data, data_len, NULL);
3451 if (status) {
3452 hdd_err("Invalid ATTR");
3453 goto out;
3454 }
3455
3456 /* Parse and fetch Command Type*/
3457 if (tb[STATION_INFO]) {
3458 status = hdd_get_station_info(hdd_ctx, adapter);
3459 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3460 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3461 } else {
3462 hdd_err("get station info cmd type failed");
3463 status = -EINVAL;
3464 goto out;
3465 }
3466 EXIT();
3467out:
3468 return status;
3469}
3470
3471/**
3472 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3473 * @wiphy: corestack handler
3474 * @wdev: wireless device
3475 * @data: data
3476 * @data_len: data length
3477 *
3478 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3479 * Validate cmd attributes and send the station info to upper layers.
3480 *
3481 * Return: Success(0) or reason code for failure
3482 */
3483static int32_t
3484hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3485 struct wireless_dev *wdev,
3486 const void *data,
3487 int data_len)
3488{
3489 int ret;
3490
3491 cds_ssr_protect(__func__);
3492 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3493 cds_ssr_unprotect(__func__);
3494
3495 return ret;
3496}
3497
3498/*
3499 * undef short names defined for get station command
3500 * used by __wlan_hdd_cfg80211_get_station_cmd()
3501 */
3502#undef STATION_INVALID
3503#undef STATION_INFO
3504#undef STATION_ASSOC_FAIL_REASON
3505#undef STATION_MAX
3506
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003507#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3508/**
3509 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3510 * @wiphy: pointer to wireless wiphy structure.
3511 * @wdev: pointer to wireless_dev structure.
3512 * @data: Pointer to the Key data
3513 * @data_len:Length of the data passed
3514 *
3515 * This is called when wlan driver needs to save the keys received via
3516 * vendor specific command.
3517 *
3518 * Return: Return the Success or Failure code.
3519 */
3520static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3521 struct wireless_dev *wdev,
3522 const void *data, int data_len)
3523{
3524 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3525 struct net_device *dev = wdev->netdev;
3526 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3527 hdd_context_t *hdd_ctx_ptr;
3528 int status;
3529
Jeff Johnson1f61b612016-02-12 16:28:33 -08003530 ENTER_DEV(dev);
3531
Anurag Chouhan6d760662016-02-20 16:05:43 +05303532 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003533 hdd_err("Command not allowed in FTM mode");
3534 return -EPERM;
3535 }
3536
3537 if ((data == NULL) || (data_len == 0) ||
3538 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003539 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003540 return -EINVAL;
3541 }
3542
3543 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3544 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003545 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003546 return -EINVAL;
3547 }
3548
3549 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303550 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003552 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3553 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003554 true,
3555 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303556 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3557 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003558 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3559 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3560 return 0;
3561}
3562
3563/**
3564 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3565 * @wiphy: pointer to wireless wiphy structure.
3566 * @wdev: pointer to wireless_dev structure.
3567 * @data: Pointer to the Key data
3568 * @data_len:Length of the data passed
3569 *
3570 * This is called when wlan driver needs to save the keys received via
3571 * vendor specific command.
3572 *
3573 * Return: Return the Success or Failure code.
3574 */
3575static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3576 struct wireless_dev *wdev,
3577 const void *data, int data_len)
3578{
3579 int ret;
3580
3581 cds_ssr_protect(__func__);
3582 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3583 cds_ssr_unprotect(__func__);
3584
3585 return ret;
3586}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003587#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003588
3589static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3590 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3591 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3592 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003593 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003594};
3595
3596/**
3597 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3598 * @wiphy: pointer to wireless wiphy structure.
3599 * @wdev: pointer to wireless_dev structure.
3600 * @data: Pointer to the data to be passed via vendor interface
3601 * @data_len:Length of the data to be passed
3602 *
3603 * This is called when wlan driver needs to send wifi driver related info
3604 * (driver/fw version) to the user space application upon request.
3605 *
3606 * Return: Return the Success or Failure code.
3607 */
3608static int
3609__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3610 struct wireless_dev *wdev,
3611 const void *data, int data_len)
3612{
3613 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3614 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003615 tSirVersionString driver_version;
3616 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003617 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003618 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003619 struct sk_buff *reply_skb;
3620 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003621
Jeff Johnson1f61b612016-02-12 16:28:33 -08003622 ENTER_DEV(wdev->netdev);
3623
Anurag Chouhan6d760662016-02-20 16:05:43 +05303624 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003625 hdd_err("Command not allowed in FTM mode");
3626 return -EPERM;
3627 }
3628
3629 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303630 if (status)
3631 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003632
3633 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3634 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003635 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003636 return -EINVAL;
3637 }
3638
3639 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003640 hdd_err("Rcvd req for Driver version");
3641 strlcpy(driver_version, QWLAN_VERSIONSTR,
3642 sizeof(driver_version));
3643 skb_len += strlen(driver_version) + 1;
3644 count++;
3645 }
3646
3647 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3648 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003649 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3650 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003651 snprintf(firmware_version, sizeof(firmware_version),
3652 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3653 skb_len += strlen(firmware_version) + 1;
3654 count++;
3655 }
3656
3657 if (count == 0) {
3658 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003659 return -EINVAL;
3660 }
3661
Ryan Hsu7ac88852016-04-28 10:20:34 -07003662 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3663 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3664
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003666 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003667 return -ENOMEM;
3668 }
3669
Ryan Hsu7ac88852016-04-28 10:20:34 -07003670 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3671 if (nla_put_string(reply_skb,
3672 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3673 driver_version))
3674 goto error_nla_fail;
3675 }
3676
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05303677 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003678 if (nla_put_string(reply_skb,
3679 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3680 firmware_version))
3681 goto error_nla_fail;
3682 }
3683
3684 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3685 if (nla_put_u32(reply_skb,
3686 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3687 hdd_ctx->radio_index))
3688 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003689 }
3690
3691 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003692
3693error_nla_fail:
3694 hdd_err("nla put fail");
3695 kfree_skb(reply_skb);
3696 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003697}
3698
3699/**
3700 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3701 * @wiphy: pointer to wireless wiphy structure.
3702 * @wdev: pointer to wireless_dev structure.
3703 * @data: Pointer to the data to be passed via vendor interface
3704 * @data_len:Length of the data to be passed
3705 *
3706 * This is called when wlan driver needs to send wifi driver related info
3707 * (driver/fw version) to the user space application upon request.
3708 *
3709 * Return: Return the Success or Failure code.
3710 */
3711static int
3712wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3713 struct wireless_dev *wdev,
3714 const void *data, int data_len)
3715{
3716 int ret;
3717
3718 cds_ssr_protect(__func__);
3719 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3720 cds_ssr_unprotect(__func__);
3721
3722 return ret;
3723}
3724
3725/**
3726 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3727 * @wiphy: pointer to wireless wiphy structure.
3728 * @wdev: pointer to wireless_dev structure.
3729 * @data: Pointer to the data to be passed via vendor interface
3730 * @data_len:Length of the data to be passed
3731 *
3732 * This is called by userspace to know the supported logger features
3733 *
3734 * Return: Return the Success or Failure code.
3735 */
3736static int
3737__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3738 struct wireless_dev *wdev,
3739 const void *data, int data_len)
3740{
3741 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3742 int status;
3743 uint32_t features;
3744 struct sk_buff *reply_skb = NULL;
3745
Jeff Johnson1f61b612016-02-12 16:28:33 -08003746 ENTER_DEV(wdev->netdev);
3747
Anurag Chouhan6d760662016-02-20 16:05:43 +05303748 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003749 hdd_err("Command not allowed in FTM mode");
3750 return -EPERM;
3751 }
3752
3753 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303754 if (status)
3755 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003756
3757 features = 0;
3758
3759 if (hdd_is_memdump_supported())
3760 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3761 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3762 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3763 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3764
3765 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3766 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3767 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003768 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003769 return -ENOMEM;
3770 }
3771
Jeff Johnson020db452016-06-29 14:37:26 -07003772 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003773 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3774 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003775 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003776 kfree_skb(reply_skb);
3777 return -EINVAL;
3778 }
3779
3780 return cfg80211_vendor_cmd_reply(reply_skb);
3781}
3782
3783/**
3784 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3785 * @wiphy: pointer to wireless wiphy structure.
3786 * @wdev: pointer to wireless_dev structure.
3787 * @data: Pointer to the data to be passed via vendor interface
3788 * @data_len:Length of the data to be passed
3789 *
3790 * This is called by userspace to know the supported logger features
3791 *
3792 * Return: Return the Success or Failure code.
3793 */
3794static int
3795wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3796 struct wireless_dev *wdev,
3797 const void *data, int data_len)
3798{
3799 int ret;
3800
3801 cds_ssr_protect(__func__);
3802 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3803 data, data_len);
3804 cds_ssr_unprotect(__func__);
3805
3806 return ret;
3807}
3808
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003809#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003810/**
3811 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05303812 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003813 * @bssid: pointer to bssid of roamed AP.
3814 * @req_rsn_ie: Pointer to request RSN IE
3815 * @req_rsn_len: Length of the request RSN IE
3816 * @rsp_rsn_ie: Pointer to response RSN IE
3817 * @rsp_rsn_len: Length of the response RSN IE
3818 * @roam_info_ptr: Pointer to the roaming related information
3819 *
3820 * This is called when wlan driver needs to send the roaming and
3821 * authorization information after roaming.
3822 *
3823 * The information that would be sent is the request RSN IE, response
3824 * RSN IE and BSSID of the newly roamed AP.
3825 *
3826 * If the Authorized status is authenticated, then additional parameters
3827 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3828 * supplicant.
3829 *
3830 * The supplicant upon receiving this event would ignore the legacy
3831 * cfg80211_roamed call and use the entire information from this event.
3832 * The cfg80211_roamed should still co-exist since the kernel will
3833 * make use of the parameters even if the supplicant ignores it.
3834 *
3835 * Return: Return the Success or Failure code.
3836 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05303837int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003838 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3839 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3840{
Prakash Dhavali989127d2016-11-29 14:56:44 +05303841 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003842 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003843 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003844 ENTER();
3845
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303846 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003848
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003849 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003850 !roam_info_ptr->roamSynchInProgress)
3851 return 0;
3852
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003853 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05303854 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003855 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3856 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3857 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003858 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003859 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3860 GFP_KERNEL);
3861
3862 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003863 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003864 return -EINVAL;
3865 }
3866
3867 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3868 ETH_ALEN, bssid) ||
3869 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3870 req_rsn_len, req_rsn_ie) ||
3871 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3872 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003873 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003874 goto nla_put_failure;
3875 }
Jeff Johnson020db452016-06-29 14:37:26 -07003876 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003877 if (roam_info_ptr->synchAuthStatus ==
3878 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003879 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003880 if (nla_put_u8(skb,
3881 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3882 hdd_err("nla put fail");
3883 goto nla_put_failure;
3884 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003885 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3886 /* if FT or CCKM connection: dont send replay counter */
3887 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3888 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3889 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3890 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3891 nla_put(skb,
3892 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3893 SIR_REPLAY_CTR_LEN,
3894 roam_info_ptr->replay_ctr)) {
3895 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003896 hdd_err("failed to send replay counter.");
3897 goto nla_put_failure;
3898 }
3899 if (nla_put(skb,
3900 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3901 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3902 nla_put(skb,
3903 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3904 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3905 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003906 goto nla_put_failure;
3907 }
3908 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003909 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003910 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3911 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003912 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003913 goto nla_put_failure;
3914 }
3915 }
3916
Jeff Johnson020db452016-06-29 14:37:26 -07003917 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003918 roam_info_ptr->subnet_change_status);
3919
3920 /*
3921 * Add subnet change status if subnet has changed
3922 * 0 = unchanged
3923 * 1 = changed
3924 * 2 = unknown
3925 */
3926 if (roam_info_ptr->subnet_change_status) {
3927 if (nla_put_u8(skb,
3928 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3929 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003930 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003931 goto nla_put_failure;
3932 }
3933 }
3934
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003935 cfg80211_vendor_event(skb, GFP_KERNEL);
3936 return 0;
3937
3938nla_put_failure:
3939 kfree_skb(skb);
3940 return -EINVAL;
3941}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003942#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003943
3944static const struct nla_policy
3945wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3946
3947 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3948 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3949 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303950 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303951 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3952 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003953 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
3954 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
3955 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
3956 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
3957 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05303958 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003959};
3960
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003961/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303962 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3963 *
3964 * @adapter: Pointer to HDD adapter
3965 * @ie_data: Pointer to Scan IEs buffer
3966 * @ie_len: Length of Scan IEs
3967 *
3968 * Return: 0 on success; error number otherwise
3969 */
3970static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3971 uint8_t *ie_data, uint8_t ie_len)
3972{
3973 hdd_scaninfo_t *scan_info = NULL;
3974 scan_info = &adapter->scan_info;
3975
3976 if (scan_info->default_scan_ies) {
3977 qdf_mem_free(scan_info->default_scan_ies);
3978 scan_info->default_scan_ies = NULL;
3979 }
3980
3981 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3982 if (!scan_info->default_scan_ies)
3983 return -ENOMEM;
3984
3985 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3986 scan_info->default_scan_ies_len = ie_len;
3987 return 0;
3988}
3989
3990/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003991 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3992 * vendor command
3993 *
3994 * @wiphy: wiphy device pointer
3995 * @wdev: wireless device pointer
3996 * @data: Vendor command data buffer
3997 * @data_len: Buffer length
3998 *
3999 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4000 *
4001 * Return: Error code.
4002 */
4003static int
4004__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4005 struct wireless_dev *wdev,
4006 const void *data,
4007 int data_len)
4008{
4009 struct net_device *dev = wdev->netdev;
4010 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4011 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4012 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4013 int ret_val = 0;
4014 u32 modulated_dtim;
4015 u16 stats_avg_factor;
4016 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304017 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004018 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004019 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304020 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304021 int attr_len;
4022 int access_policy = 0;
4023 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4024 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304025 uint16_t scan_ie_len = 0;
4026 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304027 struct sir_set_tx_rx_aggregation_size request;
4028 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004029 uint8_t retry, delay;
4030 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304031 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304032
Jeff Johnson1f61b612016-02-12 16:28:33 -08004033 ENTER_DEV(dev);
4034
Anurag Chouhan6d760662016-02-20 16:05:43 +05304035 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036 hdd_err("Command not allowed in FTM mode");
4037 return -EPERM;
4038 }
4039
4040 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304041 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043
4044 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4045 data, data_len,
4046 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004047 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004048 return -EINVAL;
4049 }
4050
Krunal Sonie3531942016-04-12 17:43:53 -07004051 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4052 ftm_capab = nla_get_u32(tb[
4053 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4054 hdd_ctx->config->fine_time_meas_cap =
4055 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4056 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304057 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004058 hdd_ctx->config->fine_time_meas_cap);
4059 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4060 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4061 hdd_ctx->config->fine_time_meas_cap);
4062 }
4063
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004064 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4065 modulated_dtim = nla_get_u32(
4066 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4067
4068 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4069 adapter->sessionId,
4070 modulated_dtim);
4071
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304072 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073 ret_val = -EPERM;
4074 }
4075
Kapil Gupta6213c012016-09-02 19:39:09 +05304076 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4077 qpower = nla_get_u8(
4078 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4079 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4080 ret_val = -EINVAL;
4081 }
4082
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004083 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4084 stats_avg_factor = nla_get_u16(
4085 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4086 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4087 adapter->sessionId,
4088 stats_avg_factor);
4089
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304090 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091 ret_val = -EPERM;
4092 }
4093
4094
4095 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4096 guard_time = nla_get_u32(
4097 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4098 status = sme_configure_guard_time(hdd_ctx->hHal,
4099 adapter->sessionId,
4100 guard_time);
4101
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304102 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004103 ret_val = -EPERM;
4104 }
4105
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304106 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4107 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4108 attr_len = nla_len(
4109 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4110 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4111 hdd_info("Invalid value. attr_len %d",
4112 attr_len);
4113 return -EINVAL;
4114 }
4115
4116 nla_memcpy(&vendor_ie,
4117 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4118 attr_len);
4119 vendor_ie_present = true;
4120 hdd_info("Access policy vendor ie present.attr_len %d",
4121 attr_len);
4122 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4123 &vendor_ie[0], attr_len);
4124 }
4125
4126 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4127 access_policy = (int) nla_get_u32(
4128 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4129 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4130 (access_policy >
4131 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4132 hdd_info("Invalid value. access_policy %d",
4133 access_policy);
4134 return -EINVAL;
4135 }
4136 access_policy_present = true;
4137 hdd_info("Access policy present. access_policy %d",
4138 access_policy);
4139 }
4140
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004141 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4142 retry = nla_get_u8(tb[
4143 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4144 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4145 CFG_NON_AGG_RETRY_MAX : retry;
4146 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4147 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4148 retry, PDEV_CMD);
4149 }
4150
4151 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4152 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4153 retry = retry > CFG_AGG_RETRY_MAX ?
4154 CFG_AGG_RETRY_MAX : retry;
4155
4156 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4157 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4158 CFG_AGG_RETRY_MIN : retry;
4159 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4160 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4161 retry, PDEV_CMD);
4162 }
4163
4164 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4165 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4166 retry = retry > CFG_MGMT_RETRY_MAX ?
4167 CFG_MGMT_RETRY_MAX : retry;
4168 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4169 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4170 retry, PDEV_CMD);
4171 }
4172
4173 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4174 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4175 retry = retry > CFG_CTRL_RETRY_MAX ?
4176 CFG_CTRL_RETRY_MAX : retry;
4177 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4178 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4179 retry, PDEV_CMD);
4180 }
4181
4182 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4183 delay = nla_get_u8(tb[
4184 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4185 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4186 CFG_PROPAGATION_DELAY_MAX : delay;
4187 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4188 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4189 delay, PDEV_CMD);
4190 }
4191
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304192 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4193 tx_fail_count = nla_get_u32(
4194 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4195 if (tx_fail_count) {
4196 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4197 adapter->sessionId, tx_fail_count);
4198 if (QDF_STATUS_SUCCESS != status) {
4199 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4200 status);
4201 return -EINVAL;
4202 }
4203 }
4204 }
4205
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304206 if (vendor_ie_present && access_policy_present) {
4207 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4208 access_policy =
4209 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304210 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304211 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304212 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304213
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304214 hdd_info("calling sme_update_access_policy_vendor_ie");
4215 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4216 adapter->sessionId, &vendor_ie[0],
4217 access_policy);
4218 if (QDF_STATUS_SUCCESS != status) {
4219 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304220 return -EINVAL;
4221 }
4222 }
4223
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304224 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4225 set_value = nla_get_u8(
4226 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4227 hdd_info("set_value: %d", set_value);
4228 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4229 }
4230
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304231 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4232 scan_ie_len = nla_len(
4233 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4234 hdd_info("Received default scan IE of len %d session %d device mode %d",
4235 scan_ie_len, adapter->sessionId,
4236 adapter->device_mode);
4237 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4238 scan_ie = (uint8_t *) nla_data(tb
4239 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304240
4241 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4242 scan_ie_len))
4243 hdd_err("Failed to save default scan IEs");
4244
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304245 if (adapter->device_mode == QDF_STA_MODE) {
4246 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4247 adapter->sessionId, scan_ie,
4248 scan_ie_len);
4249 if (QDF_STATUS_SUCCESS != status)
4250 ret_val = -EPERM;
4251 }
4252 } else
4253 ret_val = -EPERM;
4254 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304255
4256 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4257 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4258 /* if one is specified, both must be specified */
4259 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4260 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4261 hdd_err("Both TX and RX MPDU Aggregation required");
4262 return -EINVAL;
4263 }
4264
4265 request.tx_aggregation_size = nla_get_u8(
4266 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4267 request.rx_aggregation_size = nla_get_u8(
4268 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4269 request.vdev_id = adapter->sessionId;
4270
4271 if (request.tx_aggregation_size >=
4272 CFG_TX_AGGREGATION_SIZE_MIN &&
4273 request.tx_aggregation_size <=
4274 CFG_TX_AGGREGATION_SIZE_MAX &&
4275 request.rx_aggregation_size >=
4276 CFG_RX_AGGREGATION_SIZE_MIN &&
4277 request.rx_aggregation_size <=
4278 CFG_RX_AGGREGATION_SIZE_MAX) {
4279 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4280 if (qdf_status != QDF_STATUS_SUCCESS) {
4281 hdd_err("failed to set aggr sizes err %d",
4282 qdf_status);
4283 ret_val = -EPERM;
4284 }
4285 } else {
4286 hdd_err("TX %d RX %d MPDU aggr size not in range",
4287 request.tx_aggregation_size,
4288 request.rx_aggregation_size);
4289 ret_val = -EINVAL;
4290 }
4291 }
4292
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304293 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4294 uint8_t ignore_assoc_disallowed;
4295
4296 ignore_assoc_disallowed
4297 = nla_get_u8(tb[
4298 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4299 hdd_info("Set ignore_assoc_disallowed value - %d",
4300 ignore_assoc_disallowed);
4301 if ((ignore_assoc_disallowed <
4302 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4303 (ignore_assoc_disallowed >
4304 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4305 return -EPERM;
4306
4307 sme_update_session_param(hdd_ctx->hHal,
4308 adapter->sessionId,
4309 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4310 ignore_assoc_disallowed);
4311 }
4312
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313 return ret_val;
4314}
4315
4316/**
4317 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4318 * vendor command
4319 *
4320 * @wiphy: wiphy device pointer
4321 * @wdev: wireless device pointer
4322 * @data: Vendor command data buffer
4323 * @data_len: Buffer length
4324 *
4325 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4326 *
4327 * Return: EOK or other error codes.
4328 */
4329static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4330 struct wireless_dev *wdev,
4331 const void *data,
4332 int data_len)
4333{
4334 int ret;
4335
4336 cds_ssr_protect(__func__);
4337 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4338 data, data_len);
4339 cds_ssr_unprotect(__func__);
4340
4341 return ret;
4342}
4343
4344static const struct
4345nla_policy
4346qca_wlan_vendor_wifi_logger_start_policy
4347[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4348 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4349 = {.type = NLA_U32 },
4350 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4351 = {.type = NLA_U32 },
4352 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4353 = {.type = NLA_U32 },
4354};
4355
4356/**
4357 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4358 * or disable the collection of packet statistics from the firmware
4359 * @wiphy: WIPHY structure pointer
4360 * @wdev: Wireless device structure pointer
4361 * @data: Pointer to the data received
4362 * @data_len: Length of the data received
4363 *
4364 * This function enables or disables the collection of packet statistics from
4365 * the firmware
4366 *
4367 * Return: 0 on success and errno on failure
4368 */
4369static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4370 struct wireless_dev *wdev,
4371 const void *data,
4372 int data_len)
4373{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304374 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4376 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4377 struct sir_wifi_start_log start_log;
4378
Jeff Johnson1f61b612016-02-12 16:28:33 -08004379 ENTER_DEV(wdev->netdev);
4380
Anurag Chouhan6d760662016-02-20 16:05:43 +05304381 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004382 hdd_err("Command not allowed in FTM mode");
4383 return -EPERM;
4384 }
4385
4386 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304387 if (status)
4388 return status;
4389
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004390
4391 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4392 data, data_len,
4393 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004394 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004395 return -EINVAL;
4396 }
4397
4398 /* Parse and fetch ring id */
4399 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004400 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004401 return -EINVAL;
4402 }
4403 start_log.ring_id = nla_get_u32(
4404 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004405 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004406
4407 /* Parse and fetch verbose level */
4408 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004409 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004410 return -EINVAL;
4411 }
4412 start_log.verbose_level = nla_get_u32(
4413 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004414 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004415
4416 /* Parse and fetch flag */
4417 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004418 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004419 return -EINVAL;
4420 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304421 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004422 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304423 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004424
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304425 /* size is buff size which can be set using iwpriv command*/
4426 start_log.size = 0;
4427
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4429
4430 if (start_log.ring_id == RING_ID_WAKELOCK) {
4431 /* Start/stop wakelock events */
4432 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4433 cds_set_wakelock_logging(true);
4434 else
4435 cds_set_wakelock_logging(false);
4436 return 0;
4437 }
4438
4439 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304440 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004441 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004442 status);
4443 return -EINVAL;
4444 }
4445 return 0;
4446}
4447
4448/**
4449 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4450 * or disable the collection of packet statistics from the firmware
4451 * @wiphy: WIPHY structure pointer
4452 * @wdev: Wireless device structure pointer
4453 * @data: Pointer to the data received
4454 * @data_len: Length of the data received
4455 *
4456 * This function is used to enable or disable the collection of packet
4457 * statistics from the firmware
4458 *
4459 * Return: 0 on success and errno on failure
4460 */
4461static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4462 struct wireless_dev *wdev,
4463 const void *data,
4464 int data_len)
4465{
4466 int ret = 0;
4467
4468 cds_ssr_protect(__func__);
4469 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4470 wdev, data, data_len);
4471 cds_ssr_unprotect(__func__);
4472
4473 return ret;
4474}
4475
4476static const struct
4477nla_policy
4478qca_wlan_vendor_wifi_logger_get_ring_data_policy
4479[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4480 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4481 = {.type = NLA_U32 },
4482};
4483
4484/**
4485 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4486 * @wiphy: WIPHY structure pointer
4487 * @wdev: Wireless device structure pointer
4488 * @data: Pointer to the data received
4489 * @data_len: Length of the data received
4490 *
4491 * This function is used to flush or retrieve the per packet statistics from
4492 * the driver
4493 *
4494 * Return: 0 on success and errno on failure
4495 */
4496static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4497 struct wireless_dev *wdev,
4498 const void *data,
4499 int data_len)
4500{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304501 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004502 uint32_t ring_id;
4503 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4504 struct nlattr *tb
4505 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4506
Jeff Johnson1f61b612016-02-12 16:28:33 -08004507 ENTER_DEV(wdev->netdev);
4508
Anurag Chouhan6d760662016-02-20 16:05:43 +05304509 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004510 hdd_err("Command not allowed in FTM mode");
4511 return -EPERM;
4512 }
4513
4514 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304515 if (status)
4516 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004517
4518 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4519 data, data_len,
4520 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004521 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004522 return -EINVAL;
4523 }
4524
4525 /* Parse and fetch ring id */
4526 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004527 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528 return -EINVAL;
4529 }
4530
4531 ring_id = nla_get_u32(
4532 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4533
4534 if (ring_id == RING_ID_PER_PACKET_STATS) {
4535 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004536 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304537 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4538 /*
4539 * As part of DRIVER ring ID, flush both driver and fw logs.
4540 * For other Ring ID's driver doesn't have any rings to flush
4541 */
4542 hdd_notice("Bug report triggered by framework");
4543
4544 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4545 WLAN_LOG_INDICATOR_FRAMEWORK,
4546 WLAN_LOG_REASON_CODE_UNUSED,
4547 true, false);
4548 if (QDF_STATUS_SUCCESS != status) {
4549 hdd_err("Failed to trigger bug report");
4550 return -EINVAL;
4551 }
4552 } else {
4553 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4554 WLAN_LOG_INDICATOR_FRAMEWORK,
4555 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004556 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004557 return 0;
4558}
4559
4560/**
4561 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4562 * @wiphy: WIPHY structure pointer
4563 * @wdev: Wireless device structure pointer
4564 * @data: Pointer to the data received
4565 * @data_len: Length of the data received
4566 *
4567 * This function is used to flush or retrieve the per packet statistics from
4568 * the driver
4569 *
4570 * Return: 0 on success and errno on failure
4571 */
4572static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4573 struct wireless_dev *wdev,
4574 const void *data,
4575 int data_len)
4576{
4577 int ret = 0;
4578
4579 cds_ssr_protect(__func__);
4580 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4581 wdev, data, data_len);
4582 cds_ssr_unprotect(__func__);
4583
4584 return ret;
4585}
4586
4587#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4588/**
4589 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4590 * @hdd_ctx: HDD context
4591 * @request_id: [input] request id
4592 * @pattern_id: [output] pattern id
4593 *
4594 * This function loops through request id to pattern id array
4595 * if the slot is available, store the request id and return pattern id
4596 * if entry exists, return the pattern id
4597 *
4598 * Return: 0 on success and errno on failure
4599 */
4600static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4601 uint32_t request_id,
4602 uint8_t *pattern_id)
4603{
4604 uint32_t i;
4605
4606 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4607 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4608 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4609 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4610 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4611 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4612 return 0;
4613 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4614 request_id) {
4615 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4616 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4617 return 0;
4618 }
4619 }
4620 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4621 return -EINVAL;
4622}
4623
4624/**
4625 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4626 * @hdd_ctx: HDD context
4627 * @request_id: [input] request id
4628 * @pattern_id: [output] pattern id
4629 *
4630 * This function loops through request id to pattern id array
4631 * reset request id to 0 (slot available again) and
4632 * return pattern id
4633 *
4634 * Return: 0 on success and errno on failure
4635 */
4636static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4637 uint32_t request_id,
4638 uint8_t *pattern_id)
4639{
4640 uint32_t i;
4641
4642 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4643 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4644 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4645 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4646 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4647 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4648 return 0;
4649 }
4650 }
4651 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4652 return -EINVAL;
4653}
4654
4655
4656/*
4657 * define short names for the global vendor params
4658 * used by __wlan_hdd_cfg80211_offloaded_packets()
4659 */
4660#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4661#define PARAM_REQUEST_ID \
4662 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4663#define PARAM_CONTROL \
4664 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4665#define PARAM_IP_PACKET \
4666 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4667#define PARAM_SRC_MAC_ADDR \
4668 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4669#define PARAM_DST_MAC_ADDR \
4670 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4671#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4672
4673/**
4674 * wlan_hdd_add_tx_ptrn() - add tx pattern
4675 * @adapter: adapter pointer
4676 * @hdd_ctx: hdd context
4677 * @tb: nl attributes
4678 *
4679 * This function reads the NL attributes and forms a AddTxPtrn message
4680 * posts it to SME.
4681 *
4682 */
4683static int
4684wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4685 struct nlattr **tb)
4686{
4687 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304688 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689 uint32_t request_id, ret, len;
4690 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304691 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004692 uint16_t eth_type = htons(ETH_P_IP);
4693
4694 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004695 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004696 return -ENOTSUPP;
4697 }
4698
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304699 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004700 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004701 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004702 return -ENOMEM;
4703 }
4704
4705 /* Parse and fetch request Id */
4706 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004707 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004708 goto fail;
4709 }
4710
4711 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4712 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004713 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004714 return -EINVAL;
4715 }
Jeff Johnson77848112016-06-29 14:52:06 -07004716 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004717
4718 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004719 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004720 goto fail;
4721 }
4722 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004723 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004724 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004725 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004726 goto fail;
4727 }
4728
4729 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004730 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004731 goto fail;
4732 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004733 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304734 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004735 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004736 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004737
Anurag Chouhanc5548422016-02-24 18:33:27 +05304738 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004739 &adapter->macAddressCurrent)) {
4740 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004741 goto fail;
4742 }
4743
4744 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004745 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004746 goto fail;
4747 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304748 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004749 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004750 MAC_ADDR_ARRAY(dst_addr.bytes));
4751
4752 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004753 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004754 goto fail;
4755 }
4756 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004757 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004758
4759 if (add_req->ucPtrnSize < 0 ||
4760 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4761 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004762 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004763 add_req->ucPtrnSize);
4764 goto fail;
4765 }
4766
4767 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304768 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304769 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304770 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304771 QDF_MAC_ADDR_SIZE);
4772 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304773 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004774 len += 2;
4775
4776 /*
4777 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4778 * ------------------------------------------------------------
4779 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4780 * ------------------------------------------------------------
4781 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304782 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004783 nla_data(tb[PARAM_IP_PACKET]),
4784 add_req->ucPtrnSize);
4785 add_req->ucPtrnSize += len;
4786
4787 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4788 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004789 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004790 goto fail;
4791 }
4792 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004793 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004794
4795 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304796 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004797 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004798 goto fail;
4799 }
4800
4801 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304802 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004803 return 0;
4804
4805fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304806 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004807 return -EINVAL;
4808}
4809
4810/**
4811 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4812 * @adapter: adapter pointer
4813 * @hdd_ctx: hdd context
4814 * @tb: nl attributes
4815 *
4816 * This function reads the NL attributes and forms a DelTxPtrn message
4817 * posts it to SME.
4818 *
4819 */
4820static int
4821wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4822 struct nlattr **tb)
4823{
4824 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304825 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004826 uint32_t request_id, ret;
4827 uint8_t pattern_id = 0;
4828
4829 /* Parse and fetch request Id */
4830 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004831 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004832 return -EINVAL;
4833 }
4834 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4835 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004836 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004837 return -EINVAL;
4838 }
4839
4840 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4841 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004842 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843 return -EINVAL;
4844 }
4845
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304846 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004847 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004848 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004849 return -ENOMEM;
4850 }
4851
Anurag Chouhanc5548422016-02-24 18:33:27 +05304852 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004853 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004854 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004855 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004856 request_id, del_req->ucPtrnId);
4857
4858 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304859 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004860 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004861 goto fail;
4862 }
4863
4864 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304865 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004866 return 0;
4867
4868fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304869 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870 return -EINVAL;
4871}
4872
4873
4874/**
4875 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4876 * @wiphy: Pointer to wireless phy
4877 * @wdev: Pointer to wireless device
4878 * @data: Pointer to data
4879 * @data_len: Data length
4880 *
4881 * Return: 0 on success, negative errno on failure
4882 */
4883static int
4884__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4885 struct wireless_dev *wdev,
4886 const void *data,
4887 int data_len)
4888{
4889 struct net_device *dev = wdev->netdev;
4890 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4891 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4892 struct nlattr *tb[PARAM_MAX + 1];
4893 uint8_t control;
4894 int ret;
4895 static const struct nla_policy policy[PARAM_MAX + 1] = {
4896 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4897 [PARAM_CONTROL] = { .type = NLA_U32 },
4898 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304899 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004900 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304901 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004902 [PARAM_PERIOD] = { .type = NLA_U32 },
4903 };
4904
Jeff Johnson1f61b612016-02-12 16:28:33 -08004905 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004906
Anurag Chouhan6d760662016-02-20 16:05:43 +05304907 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004908 hdd_err("Command not allowed in FTM mode");
4909 return -EPERM;
4910 }
4911
4912 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304913 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004915
4916 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004917 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004918 return -ENOTSUPP;
4919 }
4920
4921 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004922 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004923 return -EINVAL;
4924 }
4925
4926 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004927 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004928 return -EINVAL;
4929 }
4930 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004931 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004932
4933 if (control == WLAN_START_OFFLOADED_PACKETS)
4934 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4935 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4936 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4937 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004938 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004939 return -EINVAL;
4940 }
4941}
4942
4943/*
4944 * done with short names for the global vendor params
4945 * used by __wlan_hdd_cfg80211_offloaded_packets()
4946 */
4947#undef PARAM_MAX
4948#undef PARAM_REQUEST_ID
4949#undef PARAM_CONTROL
4950#undef PARAM_IP_PACKET
4951#undef PARAM_SRC_MAC_ADDR
4952#undef PARAM_DST_MAC_ADDR
4953#undef PARAM_PERIOD
4954
4955/**
4956 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4957 * @wiphy: wiphy structure pointer
4958 * @wdev: Wireless device structure pointer
4959 * @data: Pointer to the data received
4960 * @data_len: Length of @data
4961 *
4962 * Return: 0 on success; errno on failure
4963 */
4964static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4965 struct wireless_dev *wdev,
4966 const void *data,
4967 int data_len)
4968{
4969 int ret = 0;
4970
4971 cds_ssr_protect(__func__);
4972 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4973 wdev, data, data_len);
4974 cds_ssr_unprotect(__func__);
4975
4976 return ret;
4977}
4978#endif
4979
4980/*
4981 * define short names for the global vendor params
4982 * used by __wlan_hdd_cfg80211_monitor_rssi()
4983 */
4984#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4985#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4986#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4987#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4988#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4989
4990/**
4991 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4992 * @wiphy: Pointer to wireless phy
4993 * @wdev: Pointer to wireless device
4994 * @data: Pointer to data
4995 * @data_len: Data length
4996 *
4997 * Return: 0 on success, negative errno on failure
4998 */
4999static int
5000__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5001 struct wireless_dev *wdev,
5002 const void *data,
5003 int data_len)
5004{
5005 struct net_device *dev = wdev->netdev;
5006 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5007 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5008 struct nlattr *tb[PARAM_MAX + 1];
5009 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305010 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005011 int ret;
5012 uint32_t control;
5013 static const struct nla_policy policy[PARAM_MAX + 1] = {
5014 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5015 [PARAM_CONTROL] = { .type = NLA_U32 },
5016 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5017 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5018 };
5019
Jeff Johnson1f61b612016-02-12 16:28:33 -08005020 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005021
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305022 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5023 hdd_err("invalid session id: %d", adapter->sessionId);
5024 return -EINVAL;
5025 }
5026
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305028 if (ret)
5029 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005030
5031 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005032 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005033 return -ENOTSUPP;
5034 }
5035
5036 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005037 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005038 return -EINVAL;
5039 }
5040
5041 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005042 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005043 return -EINVAL;
5044 }
5045
5046 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005047 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048 return -EINVAL;
5049 }
5050
5051 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5052 req.session_id = adapter->sessionId;
5053 control = nla_get_u32(tb[PARAM_CONTROL]);
5054
5055 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5056 req.control = true;
5057 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005058 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005059 return -EINVAL;
5060 }
5061
5062 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005063 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005064 return -EINVAL;
5065 }
5066
5067 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5068 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5069
5070 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005071 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005072 req.min_rssi, req.max_rssi);
5073 return -EINVAL;
5074 }
Jeff Johnson77848112016-06-29 14:52:06 -07005075 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005076 req.min_rssi, req.max_rssi);
5077
5078 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5079 req.control = false;
5080 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005081 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005082 return -EINVAL;
5083 }
Jeff Johnson77848112016-06-29 14:52:06 -07005084 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005085 req.request_id, req.session_id, req.control);
5086
5087 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305088 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005089 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005090 return -EINVAL;
5091 }
5092
5093 return 0;
5094}
5095
5096/*
5097 * done with short names for the global vendor params
5098 * used by __wlan_hdd_cfg80211_monitor_rssi()
5099 */
5100#undef PARAM_MAX
5101#undef PARAM_CONTROL
5102#undef PARAM_REQUEST_ID
5103#undef PARAM_MAX_RSSI
5104#undef PARAM_MIN_RSSI
5105
5106/**
5107 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5108 * @wiphy: wiphy structure pointer
5109 * @wdev: Wireless device structure pointer
5110 * @data: Pointer to the data received
5111 * @data_len: Length of @data
5112 *
5113 * Return: 0 on success; errno on failure
5114 */
5115static int
5116wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5117 const void *data, int data_len)
5118{
5119 int ret;
5120
5121 cds_ssr_protect(__func__);
5122 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5123 cds_ssr_unprotect(__func__);
5124
5125 return ret;
5126}
5127
5128/**
5129 * hdd_rssi_threshold_breached() - rssi breached NL event
5130 * @hddctx: HDD context
5131 * @data: rssi breached event data
5132 *
5133 * This function reads the rssi breached event %data and fill in the skb with
5134 * NL attributes and send up the NL event.
5135 *
5136 * Return: none
5137 */
5138void hdd_rssi_threshold_breached(void *hddctx,
5139 struct rssi_breach_event *data)
5140{
5141 hdd_context_t *hdd_ctx = hddctx;
5142 struct sk_buff *skb;
5143
5144 ENTER();
5145
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305146 if (wlan_hdd_validate_context(hdd_ctx))
5147 return;
5148 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005149 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005150 return;
5151 }
5152
5153 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5154 NULL,
5155 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5156 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5157 GFP_KERNEL);
5158
5159 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005160 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005161 return;
5162 }
5163
Jeff Johnson77848112016-06-29 14:52:06 -07005164 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005165 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005166 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005167 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5168
5169 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5170 data->request_id) ||
5171 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5172 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5173 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5174 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005175 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005176 goto fail;
5177 }
5178
5179 cfg80211_vendor_event(skb, GFP_KERNEL);
5180 return;
5181
5182fail:
5183 kfree_skb(skb);
5184 return;
5185}
5186
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305187static const struct nla_policy
5188ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5189 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5190};
5191
5192/**
5193 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5194 * @wiphy: Pointer to wireless phy
5195 * @wdev: Pointer to wireless device
5196 * @data: Pointer to data
5197 * @data_len: Length of @data
5198 *
5199 * Return: 0 on success, negative errno on failure
5200 */
5201static int
5202__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5203 struct wireless_dev *wdev,
5204 const void *data, int data_len)
5205{
5206 int status;
5207 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5208 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005209 struct net_device *dev = wdev->netdev;
5210 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305211
5212 ENTER_DEV(wdev->netdev);
5213
5214 status = wlan_hdd_validate_context(pHddCtx);
5215 if (0 != status)
5216 return status;
5217 if (!pHddCtx->config->fhostNSOffload) {
5218 hdd_err("ND Offload not supported");
5219 return -EINVAL;
5220 }
5221
5222 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5223 (struct nlattr *)data,
5224 data_len, ns_offload_set_policy)) {
5225 hdd_err("nla_parse failed");
5226 return -EINVAL;
5227 }
5228
5229 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5230 hdd_err("ND Offload flag attribute not present");
5231 return -EINVAL;
5232 }
5233
5234 pHddCtx->ns_offload_enable =
5235 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5236
Dustin Brownd8279d22016-09-07 14:52:57 -07005237 /* update ns offload in case it is already enabled/disabled */
5238 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5239
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305240 return 0;
5241}
5242
5243/**
5244 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5245 * @wiphy: pointer to wireless wiphy structure.
5246 * @wdev: pointer to wireless_dev structure.
5247 * @data: Pointer to the data to be passed via vendor interface
5248 * @data_len:Length of the data to be passed
5249 *
5250 * Return: Return the Success or Failure code.
5251 */
5252static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5253 struct wireless_dev *wdev,
5254 const void *data, int data_len)
5255{
5256 int ret;
5257
5258 cds_ssr_protect(__func__);
5259 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5260 cds_ssr_unprotect(__func__);
5261
5262 return ret;
5263}
5264
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005265/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5266 * @wiphy: Pointer to wireless phy
5267 * @wdev: Pointer to wireless device
5268 * @data: Pointer to data
5269 * @data_len: Data length
5270 *
5271 * This function return the preferred frequency list generated by the policy
5272 * manager.
5273 *
5274 * Return: success or failure code
5275 */
5276static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5277 struct wireless_dev
5278 *wdev, const void *data,
5279 int data_len)
5280{
5281 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5282 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305283 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305284 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005285 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305286 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005287 enum cds_con_mode intf_mode;
5288 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5289 struct sk_buff *reply_skb;
5290
Jeff Johnson1f61b612016-02-12 16:28:33 -08005291 ENTER_DEV(wdev->netdev);
5292
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005293 ret = wlan_hdd_validate_context(hdd_ctx);
5294 if (ret)
5295 return -EINVAL;
5296
5297 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5298 data, data_len, NULL)) {
5299 hdd_err("Invalid ATTR");
5300 return -EINVAL;
5301 }
5302
5303 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5304 hdd_err("attr interface type failed");
5305 return -EINVAL;
5306 }
5307
5308 intf_mode = nla_get_u32(tb
5309 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5310
5311 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5312 hdd_err("Invalid interface type");
5313 return -EINVAL;
5314 }
5315
5316 hdd_debug("Userspace requested pref freq list");
5317
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305318 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5319 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305320 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005321 hdd_err("Get pcl failed");
5322 return -EINVAL;
5323 }
5324
5325 /* convert channel number to frequency */
5326 for (i = 0; i < pcl_len; i++) {
5327 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5328 freq_list[i] =
5329 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005330 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005331 else
5332 freq_list[i] =
5333 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005334 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005335 }
5336
5337 /* send the freq_list back to supplicant */
5338 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5339 sizeof(u32) *
5340 pcl_len +
5341 NLMSG_HDRLEN);
5342
5343 if (!reply_skb) {
5344 hdd_err("Allocate reply_skb failed");
5345 return -EINVAL;
5346 }
5347
5348 if (nla_put_u32(reply_skb,
5349 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5350 intf_mode) ||
5351 nla_put(reply_skb,
5352 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5353 sizeof(uint32_t) * pcl_len,
5354 freq_list)) {
5355 hdd_err("nla put fail");
5356 kfree_skb(reply_skb);
5357 return -EINVAL;
5358 }
5359
5360 return cfg80211_vendor_cmd_reply(reply_skb);
5361}
5362
5363/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5364 * @wiphy: Pointer to wireless phy
5365 * @wdev: Pointer to wireless device
5366 * @data: Pointer to data
5367 * @data_len: Data length
5368 *
5369 * This function return the preferred frequency list generated by the policy
5370 * manager.
5371 *
5372 * Return: success or failure code
5373 */
5374static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5375 struct wireless_dev
5376 *wdev, const void *data,
5377 int data_len)
5378{
5379 int ret = 0;
5380
5381 cds_ssr_protect(__func__);
5382 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5383 data, data_len);
5384 cds_ssr_unprotect(__func__);
5385
5386 return ret;
5387}
5388
5389/**
5390 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5391 * @wiphy: Pointer to wireless phy
5392 * @wdev: Pointer to wireless device
5393 * @data: Pointer to data
5394 * @data_len: Data length
5395 *
5396 * Return: 0 on success, negative errno on failure
5397 */
5398static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5399 struct wireless_dev *wdev,
5400 const void *data,
5401 int data_len)
5402{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305403 struct net_device *ndev = wdev->netdev;
5404 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005405 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5406 int ret = 0;
5407 enum cds_con_mode intf_mode;
5408 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5409 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005410
Jeff Johnson1f61b612016-02-12 16:28:33 -08005411 ENTER_DEV(ndev);
5412
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005413 ret = wlan_hdd_validate_context(hdd_ctx);
5414 if (ret)
5415 return ret;
5416
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005417 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5418 data, data_len, NULL)) {
5419 hdd_err("Invalid ATTR");
5420 return -EINVAL;
5421 }
5422
5423 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5424 hdd_err("attr interface type failed");
5425 return -EINVAL;
5426 }
5427
5428 intf_mode = nla_get_u32(tb
5429 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5430
5431 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5432 hdd_err("Invalid interface type");
5433 return -EINVAL;
5434 }
5435
5436 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5437 hdd_err("attr probable freq failed");
5438 return -EINVAL;
5439 }
5440
5441 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5442 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5443
5444 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005445 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446 channel_hint, HW_MODE_20_MHZ)) {
5447 hdd_err("Set channel hint failed due to concurrency check");
5448 return -EINVAL;
5449 }
5450
Krunal Soni09e55032016-06-07 10:06:55 -07005451 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5452 hdd_warn("Remain On Channel Pending");
5453
Krunal Soni3091bcc2016-06-23 12:28:21 -07005454 ret = qdf_reset_connection_update();
5455 if (!QDF_IS_STATUS_SUCCESS(ret))
5456 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005457
Krunal Soni3091bcc2016-06-23 12:28:21 -07005458 ret = cds_current_connections_update(adapter->sessionId,
5459 channel_hint,
5460 SIR_UPDATE_REASON_SET_OPER_CHAN);
5461 if (QDF_STATUS_E_FAILURE == ret) {
5462 /* return in the failure case */
5463 hdd_err("ERROR: connections update failed!!");
5464 return -EINVAL;
5465 }
5466
5467 if (QDF_STATUS_SUCCESS == ret) {
5468 /*
5469 * Success is the only case for which we expect hw mode
5470 * change to take place, hence we need to wait.
5471 * For any other return value it should be a pass
5472 * through
5473 */
5474 ret = qdf_wait_for_connection_update();
5475 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5476 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477 return -EINVAL;
5478 }
5479
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005480 }
5481
5482 return 0;
5483}
5484
5485/**
5486 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5487 * @wiphy: Pointer to wireless phy
5488 * @wdev: Pointer to wireless device
5489 * @data: Pointer to data
5490 * @data_len: Data length
5491 *
5492 * Return: 0 on success, negative errno on failure
5493 */
5494static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5495 struct wireless_dev *wdev,
5496 const void *data,
5497 int data_len)
5498{
5499 int ret = 0;
5500
5501 cds_ssr_protect(__func__);
5502 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5503 data, data_len);
5504 cds_ssr_unprotect(__func__);
5505
5506 return ret;
5507}
5508
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305509static const struct
5510nla_policy
5511qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5512 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5513};
5514
5515/**
5516 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5517 * @wiphy: WIPHY structure pointer
5518 * @wdev: Wireless device structure pointer
5519 * @data: Pointer to the data received
5520 * @data_len: Length of the data received
5521 *
5522 * This function is used to get link properties like nss, rate flags and
5523 * operating frequency for the active connection with the given peer.
5524 *
5525 * Return: 0 on success and errno on failure
5526 */
5527static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5528 struct wireless_dev *wdev,
5529 const void *data,
5530 int data_len)
5531{
5532 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5533 struct net_device *dev = wdev->netdev;
5534 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5535 hdd_station_ctx_t *hdd_sta_ctx;
5536 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305537 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305538 uint32_t sta_id;
5539 struct sk_buff *reply_skb;
5540 uint32_t rate_flags = 0;
5541 uint8_t nss;
5542 uint8_t final_rate_flags = 0;
5543 uint32_t freq;
5544
Jeff Johnson1f61b612016-02-12 16:28:33 -08005545 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305546
Anurag Chouhan6d760662016-02-20 16:05:43 +05305547 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305548 hdd_err("Command not allowed in FTM mode");
5549 return -EPERM;
5550 }
5551
5552 if (0 != wlan_hdd_validate_context(hdd_ctx))
5553 return -EINVAL;
5554
5555 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5556 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005557 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305558 return -EINVAL;
5559 }
5560
5561 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005562 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305563 adapter->device_mode);
5564 return -EINVAL;
5565 }
5566
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305567 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305568 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005569 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305570 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5571
Krunal Sonib4326f22016-03-10 13:05:51 -08005572 if (adapter->device_mode == QDF_STA_MODE ||
5573 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305574 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5575 if ((hdd_sta_ctx->conn_info.connState !=
5576 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305577 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305578 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005579 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305580 MAC_ADDR_ARRAY(peer_mac));
5581 return -EINVAL;
5582 }
5583
5584 nss = hdd_sta_ctx->conn_info.nss;
5585 freq = cds_chan_to_freq(
5586 hdd_sta_ctx->conn_info.operationChannel);
5587 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005588 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5589 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305590
5591 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5592 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305593 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305594 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305595 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305596 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305597 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305598 break;
5599 }
5600
5601 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005602 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305603 MAC_ADDR_ARRAY(peer_mac));
5604 return -EINVAL;
5605 }
5606
5607 nss = adapter->aStaInfo[sta_id].nss;
5608 freq = cds_chan_to_freq(
5609 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5610 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5611 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005612 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305613 MAC_ADDR_ARRAY(peer_mac));
5614 return -EINVAL;
5615 }
5616
5617 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5618 if (rate_flags & eHAL_TX_RATE_VHT80) {
5619 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005620#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305621 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005622#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305623 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5624 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005625#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305626 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005627#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305628 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5629 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5630 } else if (rate_flags &
5631 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5632 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005633#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305634 if (rate_flags & eHAL_TX_RATE_HT40)
5635 final_rate_flags |=
5636 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005637#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305638 }
5639
5640 if (rate_flags & eHAL_TX_RATE_SGI) {
5641 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5642 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5643 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5644 }
5645 }
5646
5647 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5648 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5649
5650 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005651 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305652 return -EINVAL;
5653 }
5654
5655 if (nla_put_u8(reply_skb,
5656 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5657 nss) ||
5658 nla_put_u8(reply_skb,
5659 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5660 final_rate_flags) ||
5661 nla_put_u32(reply_skb,
5662 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5663 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005664 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305665 kfree_skb(reply_skb);
5666 return -EINVAL;
5667 }
5668
5669 return cfg80211_vendor_cmd_reply(reply_skb);
5670}
5671
5672/**
5673 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5674 * properties.
5675 * @wiphy: WIPHY structure pointer
5676 * @wdev: Wireless device structure pointer
5677 * @data: Pointer to the data received
5678 * @data_len: Length of the data received
5679 *
5680 * This function is used to get link properties like nss, rate flags and
5681 * operating frequency for the active connection with the given peer.
5682 *
5683 * Return: 0 on success and errno on failure
5684 */
5685static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5686 struct wireless_dev *wdev,
5687 const void *data,
5688 int data_len)
5689{
5690 int ret = 0;
5691
5692 cds_ssr_protect(__func__);
5693 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5694 wdev, data, data_len);
5695 cds_ssr_unprotect(__func__);
5696
5697 return ret;
5698}
5699
Peng Xu278d0122015-09-24 16:34:17 -07005700static const struct
5701nla_policy
5702qca_wlan_vendor_ota_test_policy
5703[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5704 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5705};
5706
5707/**
5708 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5709 * @wiphy: Pointer to wireless phy
5710 * @wdev: Pointer to wireless device
5711 * @data: Pointer to data
5712 * @data_len: Data length
5713 *
5714 * Return: 0 on success, negative errno on failure
5715 */
5716static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5717 struct wireless_dev *wdev,
5718 const void *data,
5719 int data_len)
5720{
5721 struct net_device *dev = wdev->netdev;
5722 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5723 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5724 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5725 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5726 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305727 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005728 uint32_t current_roam_state;
5729
Jeff Johnson1f61b612016-02-12 16:28:33 -08005730 ENTER_DEV(dev);
5731
Anurag Chouhan6d760662016-02-20 16:05:43 +05305732 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005733 hdd_err("Command not allowed in FTM mode");
5734 return -EPERM;
5735 }
5736
5737 if (0 != wlan_hdd_validate_context(hdd_ctx))
5738 return -EINVAL;
5739
5740 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5741 data, data_len,
5742 qca_wlan_vendor_ota_test_policy)) {
5743 hdd_err("invalid attr");
5744 return -EINVAL;
5745 }
5746
5747 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5748 hdd_err("attr ota test failed");
5749 return -EINVAL;
5750 }
5751
5752 ota_enable = nla_get_u8(
5753 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5754
5755 hdd_info(" OTA test enable = %d", ota_enable);
5756 if (ota_enable != 1) {
5757 hdd_err("Invalid value, only enable test mode is supported!");
5758 return -EINVAL;
5759 }
5760
5761 current_roam_state =
5762 sme_get_current_roam_state(hal, adapter->sessionId);
5763 status = sme_stop_roaming(hal, adapter->sessionId,
5764 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305765 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005766 hdd_err("Enable/Disable roaming failed");
5767 return -EINVAL;
5768 }
5769
5770 status = sme_ps_enable_disable(hal, adapter->sessionId,
5771 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305772 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005773 hdd_err("Enable/Disable power save failed");
5774 /* restore previous roaming setting */
5775 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5776 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5777 status = sme_start_roaming(hal, adapter->sessionId,
5778 eCsrHddIssued);
5779 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5780 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5781 status = sme_stop_roaming(hal, adapter->sessionId,
5782 eCsrHddIssued);
5783
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305784 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005785 hdd_err("Restoring roaming state failed");
5786
5787 return -EINVAL;
5788 }
5789
5790
5791 return 0;
5792}
5793
5794/**
5795 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5796 * @wiphy: Pointer to wireless phy
5797 * @wdev: Pointer to wireless device
5798 * @data: Pointer to data
5799 * @data_len: Data length
5800 *
5801 * Return: 0 on success, negative errno on failure
5802 */
5803static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5804 struct wireless_dev *wdev,
5805 const void *data,
5806 int data_len)
5807{
5808 int ret = 0;
5809
5810 cds_ssr_protect(__func__);
5811 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5812 cds_ssr_unprotect(__func__);
5813
5814 return ret;
5815}
5816
Peng Xu4d67c8f2015-10-16 16:02:26 -07005817/**
5818 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5819 * @wiphy: Pointer to wireless phy
5820 * @wdev: Pointer to wireless device
5821 * @data: Pointer to data
5822 * @data_len: Data length
5823 *
5824 * Return: 0 on success, negative errno on failure
5825 */
5826static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5827 struct wireless_dev *wdev,
5828 const void *data,
5829 int data_len)
5830{
5831 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5832 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005833 hdd_adapter_t *adapter;
5834 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005835 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5836 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005837 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005838
Jeff Johnson1f61b612016-02-12 16:28:33 -08005839 ENTER_DEV(dev);
5840
Peng Xu4d67c8f2015-10-16 16:02:26 -07005841 ret = wlan_hdd_validate_context(hdd_ctx);
5842 if (ret)
5843 return ret;
5844
5845 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5846
5847 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5848 data, data_len, NULL)) {
5849 hdd_err("Invalid ATTR");
5850 return -EINVAL;
5851 }
5852
5853 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5854 hdd_err("attr tx power scale failed");
5855 return -EINVAL;
5856 }
5857
5858 scale_value = nla_get_u8(tb
5859 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5860
5861 if (scale_value > MAX_TXPOWER_SCALE) {
5862 hdd_err("Invalid tx power scale level");
5863 return -EINVAL;
5864 }
5865
Peng Xu62c8c432016-05-09 15:23:02 -07005866 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005867
Peng Xu62c8c432016-05-09 15:23:02 -07005868 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005869 hdd_err("Set tx power scale failed");
5870 return -EINVAL;
5871 }
5872
5873 return 0;
5874}
5875
5876/**
5877 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5878 * @wiphy: Pointer to wireless phy
5879 * @wdev: Pointer to wireless device
5880 * @data: Pointer to data
5881 * @data_len: Data length
5882 *
5883 * Return: 0 on success, negative errno on failure
5884 */
5885static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5886 struct wireless_dev *wdev,
5887 const void *data,
5888 int data_len)
5889{
Peng Xu62c8c432016-05-09 15:23:02 -07005890 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005891
5892 cds_ssr_protect(__func__);
5893 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5894 data, data_len);
5895 cds_ssr_unprotect(__func__);
5896
5897 return ret;
5898}
5899
5900/**
5901 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5902 * @wiphy: Pointer to wireless phy
5903 * @wdev: Pointer to wireless device
5904 * @data: Pointer to data
5905 * @data_len: Data length
5906 *
5907 * Return: 0 on success, negative errno on failure
5908 */
5909static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5910 struct wireless_dev *wdev,
5911 const void *data,
5912 int data_len)
5913{
5914 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5915 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005916 hdd_adapter_t *adapter;
5917 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005918 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5919 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005920 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005921
Jeff Johnson1f61b612016-02-12 16:28:33 -08005922 ENTER_DEV(dev);
5923
Peng Xu4d67c8f2015-10-16 16:02:26 -07005924 ret = wlan_hdd_validate_context(hdd_ctx);
5925 if (ret)
5926 return ret;
5927
5928 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5929
5930 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5931 data, data_len, NULL)) {
5932 hdd_err("Invalid ATTR");
5933 return -EINVAL;
5934 }
5935
5936 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5937 hdd_err("attr tx power decrease db value failed");
5938 return -EINVAL;
5939 }
5940
5941 scale_value = nla_get_u8(tb
5942 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5943
Peng Xu62c8c432016-05-09 15:23:02 -07005944 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5945 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005946
Peng Xu62c8c432016-05-09 15:23:02 -07005947 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005948 hdd_err("Set tx power decrease db failed");
5949 return -EINVAL;
5950 }
5951
5952 return 0;
5953}
5954
5955/**
5956 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5957 * @wiphy: Pointer to wireless phy
5958 * @wdev: Pointer to wireless device
5959 * @data: Pointer to data
5960 * @data_len: Data length
5961 *
5962 * Return: 0 on success, negative errno on failure
5963 */
5964static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5965 struct wireless_dev *wdev,
5966 const void *data,
5967 int data_len)
5968{
Peng Xu62c8c432016-05-09 15:23:02 -07005969 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005970
5971 cds_ssr_protect(__func__);
5972 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5973 data, data_len);
5974 cds_ssr_unprotect(__func__);
5975
5976 return ret;
5977}
Peng Xu8fdaa492016-06-22 10:20:47 -07005978
5979/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305980 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5981 * @wiphy: Pointer to wireless phy
5982 * @wdev: Pointer to wireless device
5983 * @data: Pointer to data
5984 * @data_len: Data length
5985 *
5986 * Processes the conditional channel switch request and invokes the helper
5987 * APIs to process the channel switch request.
5988 *
5989 * Return: 0 on success, negative errno on failure
5990 */
5991static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5992 struct wireless_dev *wdev,
5993 const void *data,
5994 int data_len)
5995{
5996 int ret;
5997 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5998 struct net_device *dev = wdev->netdev;
5999 hdd_adapter_t *adapter;
6000 struct nlattr
6001 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6002 uint32_t freq_len, i;
6003 uint32_t *freq;
6004 uint8_t chans[QDF_MAX_NUM_CHAN];
6005
6006 ENTER_DEV(dev);
6007
6008 ret = wlan_hdd_validate_context(hdd_ctx);
6009 if (ret)
6010 return ret;
6011
6012 if (!hdd_ctx->config->enableDFSMasterCap) {
6013 hdd_err("DFS master capability is not present in the driver");
6014 return -EINVAL;
6015 }
6016
6017 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6018 hdd_err("Command not allowed in FTM mode");
6019 return -EPERM;
6020 }
6021
6022 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6023 if (adapter->device_mode != QDF_SAP_MODE) {
6024 hdd_err("Invalid device mode %d", adapter->device_mode);
6025 return -EINVAL;
6026 }
6027
6028 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6029 data, data_len, NULL)) {
6030 hdd_err("Invalid ATTR");
6031 return -EINVAL;
6032 }
6033
6034 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6035 hdd_err("Frequency list is missing");
6036 return -EINVAL;
6037 }
6038
6039 freq_len = nla_len(
6040 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6041 sizeof(uint32_t);
6042
6043 if (freq_len > QDF_MAX_NUM_CHAN) {
6044 hdd_err("insufficient space to hold channels");
6045 return -ENOMEM;
6046 }
6047
6048 hdd_debug("freq_len=%d", freq_len);
6049
6050 freq = nla_data(
6051 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6052
6053
6054 for (i = 0; i < freq_len; i++) {
6055 if (freq[i] == 0)
6056 chans[i] = 0;
6057 else
6058 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6059
6060 hdd_debug("freq[%d]=%d", i, freq[i]);
6061 }
6062
6063 /*
6064 * The input frequency list from user space is designed to be a
6065 * priority based frequency list. This is only to accommodate any
6066 * future request. But, current requirement is only to perform CAC
6067 * on a single channel. So, the first entry from the list is picked.
6068 *
6069 * If channel is zero, any channel in the available outdoor regulatory
6070 * domain will be selected.
6071 */
6072 ret = wlan_hdd_request_pre_cac(chans[0]);
6073 if (ret) {
6074 hdd_err("pre cac request failed with reason:%d", ret);
6075 return ret;
6076 }
6077
6078 return 0;
6079}
6080
6081/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006082 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6083 * @wiphy: Pointer to wireless phy
6084 * @wdev: Pointer to wireless device
6085 * @data: Pointer to data
6086 * @data_len: Data length
6087 *
6088 * This function is to process the p2p listen offload start vendor
6089 * command. It parses the input parameters and invoke WMA API to
6090 * send the command to firmware.
6091 *
6092 * Return: 0 on success, negative errno on failure
6093 */
6094static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6095 struct wireless_dev *wdev,
6096 const void *data,
6097 int data_len)
6098{
6099 int ret;
6100 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6101 struct net_device *dev = wdev->netdev;
6102 hdd_adapter_t *adapter;
6103 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6104 struct sir_p2p_lo_start params;
6105 QDF_STATUS status;
6106
6107 ENTER_DEV(dev);
6108
6109 ret = wlan_hdd_validate_context(hdd_ctx);
6110 if (ret)
6111 return ret;
6112
6113 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6114 hdd_err("Command not allowed in FTM mode");
6115 return -EPERM;
6116 }
6117
6118 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6119 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6120 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6121 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6122 hdd_err("Invalid device mode %d", adapter->device_mode);
6123 return -EINVAL;
6124 }
6125
6126 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6127 data, data_len, NULL)) {
6128 hdd_err("Invalid ATTR");
6129 return -EINVAL;
6130 }
6131
6132 memset(&params, 0, sizeof(params));
6133
6134 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6135 params.ctl_flags = 1; /* set to default value */
6136 else
6137 params.ctl_flags = nla_get_u32(tb
6138 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6139
6140 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6141 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6142 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6143 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6144 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6145 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6146 hdd_err("Attribute parsing failed");
6147 return -EINVAL;
6148 }
6149
6150 params.vdev_id = adapter->sessionId;
6151 params.freq = nla_get_u32(tb
6152 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6153 if ((params.freq != 2412) && (params.freq != 2437) &&
6154 (params.freq != 2462)) {
6155 hdd_err("Invalid listening channel: %d", params.freq);
6156 return -EINVAL;
6157 }
6158
6159 params.period = nla_get_u32(tb
6160 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6161 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6162 hdd_err("Invalid period: %d", params.period);
6163 return -EINVAL;
6164 }
6165
6166 params.interval = nla_get_u32(tb
6167 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6168 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6169 hdd_err("Invalid interval: %d", params.interval);
6170 return -EINVAL;
6171 }
6172
6173 params.count = nla_get_u32(tb
6174 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006175 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006176 hdd_err("Invalid count: %d", params.count);
6177 return -EINVAL;
6178 }
6179
6180 params.device_types = nla_data(tb
6181 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6182 if (params.device_types == NULL) {
6183 hdd_err("Invalid device types");
6184 return -EINVAL;
6185 }
6186
6187 params.dev_types_len = nla_len(tb
6188 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6189 if (params.dev_types_len < 8) {
6190 hdd_err("Invalid device type length: %d", params.dev_types_len);
6191 return -EINVAL;
6192 }
6193
6194 params.probe_resp_tmplt = nla_data(tb
6195 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6196 if (params.probe_resp_tmplt == NULL) {
6197 hdd_err("Invalid probe response template");
6198 return -EINVAL;
6199 }
6200
6201 params.probe_resp_len = nla_len(tb
6202 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6203 if (params.probe_resp_len == 0) {
6204 hdd_err("Invalid probe resp template length: %d",
6205 params.probe_resp_len);
6206 return -EINVAL;
6207 }
6208
6209 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6210 params.freq, params.period, params.interval, params.count);
6211
6212 status = wma_p2p_lo_start(&params);
6213
6214 if (!QDF_IS_STATUS_SUCCESS(status)) {
6215 hdd_err("P2P LO start failed");
6216 return -EINVAL;
6217 }
6218
6219 return 0;
6220}
6221
6222
6223/**
6224 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6225 * @wiphy: Pointer to wireless phy
6226 * @wdev: Pointer to wireless device
6227 * @data: Pointer to data
6228 * @data_len: Data length
6229 *
6230 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6231 * to process p2p listen offload start vendor command.
6232 *
6233 * Return: 0 on success, negative errno on failure
6234 */
6235static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6236 struct wireless_dev *wdev,
6237 const void *data,
6238 int data_len)
6239{
6240 int ret = 0;
6241
6242 cds_ssr_protect(__func__);
6243 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6244 data, data_len);
6245 cds_ssr_unprotect(__func__);
6246
6247 return ret;
6248}
6249
6250/**
6251 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6252 * @wiphy: Pointer to wireless phy
6253 * @wdev: Pointer to wireless device
6254 * @data: Pointer to data
6255 * @data_len: Data length
6256 *
6257 * This function is to process the p2p listen offload stop vendor
6258 * command. It invokes WMA API to send command to firmware.
6259 *
6260 * Return: 0 on success, negative errno on failure
6261 */
6262static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6263 struct wireless_dev *wdev,
6264 const void *data,
6265 int data_len)
6266{
6267 QDF_STATUS status;
6268 hdd_adapter_t *adapter;
6269 struct net_device *dev = wdev->netdev;
6270
6271 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6272 hdd_err("Command not allowed in FTM mode");
6273 return -EPERM;
6274 }
6275
6276 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6277 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6278 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6279 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6280 hdd_err("Invalid device mode");
6281 return -EINVAL;
6282 }
6283
6284 status = wma_p2p_lo_stop(adapter->sessionId);
6285
6286 if (!QDF_IS_STATUS_SUCCESS(status)) {
6287 hdd_err("P2P LO stop failed");
6288 return -EINVAL;
6289 }
6290
6291 return 0;
6292}
6293
6294/**
6295 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6296 * @wiphy: Pointer to wireless phy
6297 * @wdev: Pointer to wireless device
6298 * @data: Pointer to data
6299 * @data_len: Data length
6300 *
6301 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6302 * to process p2p listen offload stop vendor command.
6303 *
6304 * Return: 0 on success, negative errno on failure
6305 */
6306static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6307 struct wireless_dev *wdev,
6308 const void *data,
6309 int data_len)
6310{
6311 int ret = 0;
6312
6313 cds_ssr_protect(__func__);
6314 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6315 data, data_len);
6316 cds_ssr_unprotect(__func__);
6317
6318 return ret;
6319}
6320
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306321/**
6322 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6323 * @wiphy: Pointer to wireless phy
6324 * @wdev: Pointer to wireless device
6325 * @data: Pointer to data
6326 * @data_len: Data length
6327 *
6328 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6329 * to process the conditional channel switch request.
6330 *
6331 * Return: 0 on success, negative errno on failure
6332 */
6333static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6334 struct wireless_dev *wdev,
6335 const void *data,
6336 int data_len)
6337{
6338 int ret;
6339
6340 cds_ssr_protect(__func__);
6341 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6342 data, data_len);
6343 cds_ssr_unprotect(__func__);
6344
6345 return ret;
6346}
6347
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306348/*
6349 * define short names for the global vendor params
6350 * used by __wlan_hdd_cfg80211_bpf_offload()
6351 */
6352#define BPF_INVALID \
6353 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6354#define BPF_SET_RESET \
6355 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6356#define BPF_VERSION \
6357 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6358#define BPF_FILTER_ID \
6359 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6360#define BPF_PACKET_SIZE \
6361 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6362#define BPF_CURRENT_OFFSET \
6363 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6364#define BPF_PROGRAM \
6365 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6366#define BPF_MAX \
6367 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006368
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306369static const struct nla_policy
6370wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6371 [BPF_SET_RESET] = {.type = NLA_U32},
6372 [BPF_VERSION] = {.type = NLA_U32},
6373 [BPF_FILTER_ID] = {.type = NLA_U32},
6374 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6375 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6376 [BPF_PROGRAM] = {.type = NLA_U8},
6377};
6378
6379/**
6380 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6381 * @hdd_context: hdd_context
6382 * @bpf_get_offload: struct for get offload
6383 *
6384 * This function receives the response/data from the lower layer and
6385 * checks to see if the thread is still waiting then post the results to
6386 * upper layer, if the request has timed out then ignore.
6387 *
6388 * Return: None
6389 */
6390void hdd_get_bpf_offload_cb(void *hdd_context,
6391 struct sir_bpf_get_offload *data)
6392{
6393 hdd_context_t *hdd_ctx = hdd_context;
6394 struct hdd_bpf_context *context;
6395
6396 ENTER();
6397
6398 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006399 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306400 data);
6401 return;
6402 }
6403
6404 spin_lock(&hdd_context_lock);
6405
6406 context = &bpf_context;
6407 /* The caller presumably timed out so there is nothing we can do */
6408 if (context->magic != BPF_CONTEXT_MAGIC) {
6409 spin_unlock(&hdd_context_lock);
6410 return;
6411 }
6412
6413 /* context is valid so caller is still waiting */
6414 /* paranoia: invalidate the magic */
6415 context->magic = 0;
6416
6417 context->capability_response = *data;
6418 complete(&context->completion);
6419
6420 spin_unlock(&hdd_context_lock);
6421
6422 return;
6423}
6424
6425/**
6426 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6427 * @hdd_context: hdd_context
6428 * @bpf_get_offload: struct for get offload
6429 *
6430 * Return: 0 on success, error number otherwise.
6431 */
6432static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6433 struct sir_bpf_get_offload *bpf_get_offload)
6434{
6435 struct sk_buff *skb;
6436 uint32_t nl_buf_len;
6437
6438 ENTER();
6439
6440 nl_buf_len = NLMSG_HDRLEN;
6441 nl_buf_len +=
6442 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6443 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6444
6445 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6446 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006447 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306448 return -ENOMEM;
6449 }
6450
Jeff Johnson77848112016-06-29 14:52:06 -07006451 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306452 bpf_get_offload->bpf_version,
6453 bpf_get_offload->max_bytes_for_bpf_inst);
6454
6455 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6456 bpf_get_offload->max_bytes_for_bpf_inst) ||
6457 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006458 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306459 goto nla_put_failure;
6460 }
6461
6462 cfg80211_vendor_cmd_reply(skb);
6463 EXIT();
6464 return 0;
6465
6466nla_put_failure:
6467 kfree_skb(skb);
6468 return -EINVAL;
6469}
6470
6471/**
6472 * hdd_get_bpf_offload - Get BPF offload Capabilities
6473 * @hdd_ctx: Hdd context
6474 *
6475 * Return: 0 on success, errno on failure
6476 */
6477static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6478{
6479 unsigned long rc;
Houston Hoffman59c097f2016-11-09 15:50:25 -08006480 static struct hdd_bpf_context *context;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306481 QDF_STATUS status;
6482 int ret;
6483
6484 ENTER();
6485
6486 spin_lock(&hdd_context_lock);
6487 context = &bpf_context;
6488 context->magic = BPF_CONTEXT_MAGIC;
6489 INIT_COMPLETION(context->completion);
6490 spin_unlock(&hdd_context_lock);
6491
6492 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6493 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006494 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306495 return -EINVAL;
6496 }
6497 /* request was sent -- wait for the response */
6498 rc = wait_for_completion_timeout(&context->completion,
6499 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6500 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006501 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306502 spin_lock(&hdd_context_lock);
6503 context->magic = 0;
6504 spin_unlock(&hdd_context_lock);
6505
6506 return -ETIMEDOUT;
6507 }
6508 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6509 &bpf_context.capability_response);
6510 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006511 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306512
6513 EXIT();
6514 return ret;
6515}
6516
6517/**
6518 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6519 * @hdd_ctx: Hdd context
6520 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306521 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306522 *
6523 * Return: 0 on success; errno on failure
6524 */
6525static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6526 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306527 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306528{
6529 struct sir_bpf_set_offload *bpf_set_offload;
6530 QDF_STATUS status;
6531 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306532 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306533
6534 ENTER();
6535
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306536 if (adapter->device_mode == QDF_STA_MODE ||
6537 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6538 if (!hdd_conn_is_connected(
6539 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6540 hdd_err("Not in Connected state!");
6541 return -ENOTSUPP;
6542 }
6543 }
6544
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306545 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6546 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006547 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306548 return -ENOMEM;
6549 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306550
6551 /* Parse and fetch bpf packet size */
6552 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006553 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306554 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306555 goto fail;
6556 }
6557 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6558
6559 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006560 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306561 goto post_sme;
6562 }
6563
6564 /* Parse and fetch bpf program */
6565 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006566 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306567 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306568 goto fail;
6569 }
6570
6571 prog_len = nla_len(tb[BPF_PROGRAM]);
6572 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306573
6574 if (bpf_set_offload->program == NULL) {
6575 hdd_err("qdf_mem_malloc failed for bpf offload program");
6576 ret = -ENOMEM;
6577 goto fail;
6578 }
6579
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306580 bpf_set_offload->current_length = prog_len;
6581 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306582 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306583
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306584 hdd_info("BPF set instructions");
6585 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6586 bpf_set_offload->program, prog_len);
6587
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306588 /* Parse and fetch filter Id */
6589 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006590 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306591 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306592 goto fail;
6593 }
6594 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6595
6596 /* Parse and fetch current offset */
6597 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006598 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306599 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306600 goto fail;
6601 }
6602 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6603
6604post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006605 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 +05306606 bpf_set_offload->session_id,
6607 bpf_set_offload->version,
6608 bpf_set_offload->filter_id,
6609 bpf_set_offload->total_length,
6610 bpf_set_offload->current_length,
6611 bpf_set_offload->current_offset);
6612
6613 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6614 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006615 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306616 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306617 goto fail;
6618 }
6619 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306620
6621fail:
6622 if (bpf_set_offload->current_length)
6623 qdf_mem_free(bpf_set_offload->program);
6624 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306625 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306626}
6627
6628/**
6629 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6630 * @wiphy: wiphy structure pointer
6631 * @wdev: Wireless device structure pointer
6632 * @data: Pointer to the data received
6633 * @data_len: Length of @data
6634 *
6635 * Return: 0 on success; errno on failure
6636 */
6637static int
6638__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6639 struct wireless_dev *wdev,
6640 const void *data, int data_len)
6641{
6642 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6643 struct net_device *dev = wdev->netdev;
6644 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6645 struct nlattr *tb[BPF_MAX + 1];
6646 int ret_val, packet_filter_subcmd;
6647
6648 ENTER();
6649
6650 ret_val = wlan_hdd_validate_context(hdd_ctx);
6651 if (ret_val)
6652 return ret_val;
6653
6654 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006655 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306656 return -EINVAL;
6657 }
6658
6659 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006660 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306661 return -ENOTSUPP;
6662 }
6663
6664 if (nla_parse(tb, BPF_MAX, data, data_len,
6665 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006666 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306667 return -EINVAL;
6668 }
6669
6670 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006671 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306672 return -EINVAL;
6673 }
6674
6675 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6676
6677 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6678 return hdd_get_bpf_offload(hdd_ctx);
6679 else
6680 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306681 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306682}
6683
6684/**
6685 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6686 * @wiphy: wiphy structure pointer
6687 * @wdev: Wireless device structure pointer
6688 * @data: Pointer to the data received
6689 * @data_len: Length of @data
6690 *
6691 * Return: 0 on success; errno on failure
6692 */
6693
6694static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6695 struct wireless_dev *wdev,
6696 const void *data, int data_len)
6697{
6698 int ret;
6699
6700 cds_ssr_protect(__func__);
6701 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6702 cds_ssr_unprotect(__func__);
6703
6704 return ret;
6705}
6706
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306707/**
6708 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6709 * @pre_cac_adapter: AP adapter used for pre cac
6710 * @status: Status (true or false)
6711 * @handle: Global handle
6712 *
6713 * Sets the status of pre cac i.e., whether the pre cac is active or not
6714 *
6715 * Return: Zero on success, non-zero on failure
6716 */
6717static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6718 bool status, tHalHandle handle)
6719{
6720 QDF_STATUS ret;
6721
6722 ret = wlan_sap_set_pre_cac_status(
6723 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6724 if (QDF_IS_STATUS_ERROR(ret))
6725 return -EINVAL;
6726
6727 return 0;
6728}
6729
6730/**
6731 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6732 * @ap_adapter: AP adapter
6733 * @chan_before_pre_cac: Channel
6734 *
6735 * Saves the channel which the AP was beaconing on before moving to the pre
6736 * cac channel. If radar is detected on the pre cac channel, this saved
6737 * channel will be used for AP operations.
6738 *
6739 * Return: Zero on success, non-zero on failure
6740 */
6741static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6742 uint8_t chan_before_pre_cac)
6743{
6744 QDF_STATUS ret;
6745
6746 ret = wlan_sap_set_chan_before_pre_cac(
6747 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6748 if (QDF_IS_STATUS_ERROR(ret))
6749 return -EINVAL;
6750
6751 return 0;
6752}
6753
6754/**
6755 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6756 * @ap_adapter: AP adapter
6757 * @nol: Non-occupancy list
6758 * @nol_len: Length of NOL
6759 *
6760 * Get the NOL for SAP
6761 *
6762 * Return: Zero on success, non-zero on failure
6763 */
6764static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6765 uint32_t *nol_len)
6766{
6767 QDF_STATUS ret;
6768
6769 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6770 nol, nol_len);
6771 if (QDF_IS_STATUS_ERROR(ret))
6772 return -EINVAL;
6773
6774 return 0;
6775}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306776
6777/**
6778 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6779 * @hdd_ctx: HDD context
6780 * @ap_adapter: AP adapter
6781 * @channel: Channel requested by userspace
6782 * @pre_cac_chan: Pointer to the pre CAC channel
6783 *
6784 * Validates the channel provided by userspace. If user provided channel 0,
6785 * a valid outdoor channel must be selected from the regulatory channel.
6786 *
6787 * Return: Zero on success and non zero value on error
6788 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006789static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6790 hdd_adapter_t *ap_adapter,
6791 uint8_t channel,
6792 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306793{
6794 uint32_t i, j;
6795 QDF_STATUS status;
6796 int ret;
6797 uint8_t nol[QDF_MAX_NUM_CHAN];
6798 uint32_t nol_len = 0, weight_len = 0;
6799 bool found;
6800 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6801 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6802 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6803
6804 if (0 == channel) {
6805 /* Channel is not obtained from PCL because PCL may not have
6806 * the entire channel list. For example: if SAP is up on
6807 * channel 6 and PCL is queried for the next SAP interface,
6808 * if SCC is preferred, the PCL will contain only the channel
6809 * 6. But, we are in need of a DFS channel. So, going with the
6810 * first channel from the valid channel list.
6811 */
6812 status = cds_get_valid_chans(channel_list, &len);
6813 if (QDF_IS_STATUS_ERROR(status)) {
6814 hdd_err("Failed to get channel list");
6815 return -EINVAL;
6816 }
6817 cds_update_with_safe_channel_list(channel_list, &len,
6818 pcl_weights, weight_len);
6819 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6820 for (i = 0; i < len; i++) {
6821 found = false;
6822 for (j = 0; j < nol_len; j++) {
6823 if (channel_list[i] == nol[j]) {
6824 found = true;
6825 break;
6826 }
6827 }
6828 if (found)
6829 continue;
6830 if (CDS_IS_DFS_CH(channel_list[i])) {
6831 *pre_cac_chan = channel_list[i];
6832 break;
6833 }
6834 }
6835 if (*pre_cac_chan == 0) {
6836 hdd_err("unable to find outdoor channel");
6837 return -EINVAL;
6838 }
6839 } else {
6840 /* Only when driver selects a channel, check is done for
6841 * unnsafe and NOL channels. When user provides a fixed channel
6842 * the user is expected to take care of this.
6843 */
6844 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6845 !CDS_IS_DFS_CH(channel)) {
6846 hdd_err("Invalid channel for pre cac:%d", channel);
6847 return -EINVAL;
6848 } else {
6849 *pre_cac_chan = channel;
6850 }
6851 }
6852 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6853 return 0;
6854}
6855
6856/**
6857 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6858 * @channel: Channel option provided by userspace
6859 *
6860 * Sets the driver to the required hardware mode and start an adapater for
6861 * pre CAC which will mimic an AP.
6862 *
6863 * Return: Zero on success, non-zero value on error
6864 */
6865int wlan_hdd_request_pre_cac(uint8_t channel)
6866{
Krunal Sonib37bb352016-12-20 14:12:21 -08006867 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306868 hdd_context_t *hdd_ctx;
6869 int ret;
6870 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6871 hdd_ap_ctx_t *hdd_ap_ctx;
6872 QDF_STATUS status;
6873 struct wiphy *wiphy;
6874 struct net_device *dev;
6875 struct cfg80211_chan_def chandef;
6876 enum nl80211_channel_type channel_type;
6877 uint32_t freq;
6878 struct ieee80211_channel *chan;
6879 tHalHandle handle;
6880 bool val;
6881
6882 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6883 if (0 != wlan_hdd_validate_context(hdd_ctx))
6884 return -EINVAL;
6885
6886 if (cds_get_connection_count() > 1) {
6887 hdd_err("pre cac not allowed in concurrency");
6888 return -EINVAL;
6889 }
6890
6891 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6892 if (!ap_adapter) {
6893 hdd_err("unable to get SAP adapter");
6894 return -EINVAL;
6895 }
6896
6897 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6898 if (!handle) {
6899 hdd_err("Invalid handle");
6900 return -EINVAL;
6901 }
6902
6903 val = wlan_sap_is_pre_cac_active(handle);
6904 if (val) {
6905 hdd_err("pre cac is already in progress");
6906 return -EINVAL;
6907 }
6908
6909 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6910 if (!hdd_ap_ctx) {
6911 hdd_err("SAP context is NULL");
6912 return -EINVAL;
6913 }
6914
6915 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6916 hdd_err("SAP is already on DFS channel:%d",
6917 hdd_ap_ctx->operatingChannel);
6918 return -EINVAL;
6919 }
6920
6921 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6922 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6923 hdd_ap_ctx->operatingChannel);
6924 return -EINVAL;
6925 }
6926
Krunal Sonib37bb352016-12-20 14:12:21 -08006927 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6928 if (!mac_addr) {
6929 hdd_err("can't add virtual intf: Not getting valid mac addr");
6930 return -EINVAL;
6931 }
6932
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306933 hdd_info("channel:%d", channel);
6934
6935 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6936 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08006937 if (ret != 0) {
6938 hdd_err("can't validate pre-cac channel");
6939 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306940 }
6941
6942 hdd_debug("starting pre cac SAP adapter");
6943
6944 /* Starting a SAP adapter:
6945 * Instead of opening an adapter, we could just do a SME open session
6946 * for AP type. But, start BSS would still need an adapter.
6947 * So, this option is not taken.
6948 *
6949 * hdd open adapter is going to register this precac interface with
6950 * user space. This interface though exposed to user space will be in
6951 * DOWN state. Consideration was done to avoid this registration to the
6952 * user space. But, as part of SAP operations multiple events are sent
6953 * to user space. Some of these events received from unregistered
6954 * interface was causing crashes. So, retaining the registration.
6955 *
6956 * So, this interface would remain registered and will remain in DOWN
6957 * state for the CAC duration. We will add notes in the feature
6958 * announcement to not use this temporary interface for any activity
6959 * from user space.
6960 */
6961 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08006962 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306963 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306964 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08006965 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306966 }
6967
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306968 /*
6969 * This interface is internally created by the driver. So, no interface
6970 * up comes for this interface from user space and hence starting
6971 * the adapter internally.
6972 */
6973 if (hdd_start_adapter(pre_cac_adapter)) {
6974 hdd_err("error starting the pre cac adapter");
6975 goto close_pre_cac_adapter;
6976 }
6977
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306978 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6979
6980 wiphy = hdd_ctx->wiphy;
6981 dev = pre_cac_adapter->dev;
6982
6983 /* Since this is only a dummy interface lets us use the IEs from the
6984 * other active SAP interface. In regular scenarios, these IEs would
6985 * come from the user space entity
6986 */
6987 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6988 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6989 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6990 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306991 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306992 }
6993 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6994 ap_adapter->sessionCtx.ap.beacon,
6995 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6996 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6997 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6998 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6999 ap_adapter->sessionCtx.ap.sapConfig.authType;
7000
7001 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7002 * to operate on the same bandwidth as that of the 2.4GHz operations.
7003 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7004 */
7005 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7006 case CH_WIDTH_20MHZ:
7007 channel_type = NL80211_CHAN_HT20;
7008 break;
7009 case CH_WIDTH_40MHZ:
7010 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7011 ap_adapter->sessionCtx.ap.sapConfig.channel)
7012 channel_type = NL80211_CHAN_HT40PLUS;
7013 else
7014 channel_type = NL80211_CHAN_HT40MINUS;
7015 break;
7016 default:
7017 channel_type = NL80211_CHAN_NO_HT;
7018 break;
7019 }
7020
7021 freq = cds_chan_to_freq(pre_cac_chan);
7022 chan = __ieee80211_get_channel(wiphy, freq);
7023 if (!chan) {
7024 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307025 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307026 }
7027
7028 cfg80211_chandef_create(&chandef, chan, channel_type);
7029
7030 hdd_debug("orig width:%d channel_type:%d freq:%d",
7031 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7032 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007033 /*
7034 * Doing update after opening and starting pre-cac adapter will make
7035 * sure that driver won't do hardware mode change if there are any
7036 * initial hick-ups or issues in pre-cac adapter's configuration.
7037 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7038 * connection update should result in DBS mode
7039 */
7040 status = cds_update_and_wait_for_connection_update(
7041 ap_adapter->sessionId,
7042 pre_cac_chan,
7043 SIR_UPDATE_REASON_PRE_CAC);
7044 if (QDF_IS_STATUS_ERROR(status)) {
7045 hdd_err("error in moving to DBS mode");
7046 goto stop_close_pre_cac_adapter;
7047 }
7048
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307049
7050 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7051 if (0 != ret) {
7052 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307053 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307054 }
7055
7056 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7057 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007058 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307059 if (QDF_IS_STATUS_ERROR(status)) {
7060 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307061 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307062 }
7063
7064 /*
7065 * The pre cac status is set here. But, it would not be reset explicitly
7066 * anywhere, since after the pre cac success/failure, the pre cac
7067 * adapter itself would be removed.
7068 */
7069 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7070 if (0 != ret) {
7071 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307072 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307073 }
7074
7075 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7076 hdd_ap_ctx->operatingChannel);
7077 if (0 != ret) {
7078 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307079 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307080 }
7081
7082 ap_adapter->pre_cac_chan = pre_cac_chan;
7083
7084 return 0;
7085
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307086stop_close_pre_cac_adapter:
7087 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307088 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7089 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307090close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307091 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007092release_intf_addr_and_return_failure:
7093 /*
7094 * Release the interface address as the adapter
7095 * failed to start, if you don't release then next
7096 * adapter which is trying to come wouldn't get valid
7097 * mac address. Remember we have limited pool of mac addresses
7098 */
7099 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307100 return -EINVAL;
7101}
7102
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307103/**
7104 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7105 *
7106 * Return: None
7107 */
7108void hdd_init_bpf_completion(void)
7109{
7110 init_completion(&bpf_context.completion);
7111}
7112
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307113static const struct nla_policy
7114wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7115 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7116};
7117
Agrawal Ashish65634612016-08-18 13:24:32 +05307118static const struct nla_policy
7119wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7120 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7121 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7122};
7123
7124/**
7125 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7126 * @wiphy: Pointer to wireless phy
7127 * @wdev: Pointer to wireless device
7128 * @data: Pointer to data
7129 * @data_len: Length of @data
7130 *
7131 * This function parses the incoming NL vendor command data attributes and
7132 * updates the SAP context about channel_hint and DFS mode.
7133 * If channel_hint is set, SAP will choose that channel
7134 * as operating channel.
7135 *
7136 * If DFS mode is enabled, driver will include DFS channels
7137 * in ACS else driver will skip DFS channels.
7138 *
7139 * Return: 0 on success, negative errno on failure
7140 */
7141static int
7142__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7143 struct wireless_dev *wdev,
7144 const void *data, int data_len)
7145{
7146 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7147 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7148 int ret;
7149 struct acs_dfs_policy *acs_policy;
7150 int mode = DFS_MODE_NONE;
7151 int channel_hint = 0;
7152
7153 ENTER_DEV(wdev->netdev);
7154
7155 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7156 hdd_err("Command not allowed in FTM mode");
7157 return -EINVAL;
7158 }
7159
7160 ret = wlan_hdd_validate_context(hdd_ctx);
7161 if (0 != ret)
7162 return ret;
7163
7164 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7165 data, data_len,
7166 wlan_hdd_set_acs_dfs_config_policy)) {
7167 hdd_err("invalid attr");
7168 return -EINVAL;
7169 }
7170
7171 acs_policy = &hdd_ctx->acs_policy;
7172 /*
7173 * SCM sends this attribute to restrict SAP from choosing
7174 * DFS channels from ACS.
7175 */
7176 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7177 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7178
7179 if (!IS_DFS_MODE_VALID(mode)) {
7180 hdd_err("attr acs dfs mode is not valid");
7181 return -EINVAL;
7182 }
7183 acs_policy->acs_dfs_mode = mode;
7184
7185 /*
7186 * SCM sends this attribute to provide an active channel,
7187 * to skip redundant ACS between drivers, and save driver start up time
7188 */
7189 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7190 channel_hint = nla_get_u8(
7191 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7192
7193 if (!IS_CHANNEL_VALID(channel_hint)) {
7194 hdd_err("acs channel is not valid");
7195 return -EINVAL;
7196 }
7197 acs_policy->acs_channel = channel_hint;
7198
7199 return 0;
7200}
7201
7202/**
7203 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7204 * @wiphy: wiphy structure pointer
7205 * @wdev: Wireless device structure pointer
7206 * @data: Pointer to the data received
7207 * @data_len: Length of @data
7208 *
7209 * This function parses the incoming NL vendor command data attributes and
7210 * updates the SAP context about channel_hint and DFS mode.
7211 *
7212 * Return: 0 on success; errno on failure
7213 */
7214static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7215 struct wireless_dev *wdev,
7216 const void *data, int data_len)
7217{
7218 int ret;
7219
7220 cds_ssr_protect(__func__);
7221 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7222 cds_ssr_unprotect(__func__);
7223
7224 return ret;
7225}
7226
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307227/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307228 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7229 * @mode : cfg80211 dfs mode
7230 *
7231 * Return: return csr sta roam dfs mode else return NONE
7232 */
7233static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7234 enum dfs_mode mode)
7235{
7236 switch (mode) {
7237 case DFS_MODE_ENABLE:
7238 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7239 break;
7240 case DFS_MODE_DISABLE:
7241 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7242 break;
7243 case DFS_MODE_DEPRIORITIZE:
7244 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7245 break;
7246 default:
7247 hdd_err("STA Roam policy dfs mode is NONE");
7248 return CSR_STA_ROAM_POLICY_NONE;
7249 }
7250}
7251
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307252/*
7253 * hdd_get_sap_operating_band: Get current operating channel
7254 * for sap.
7255 * @hdd_ctx: hdd context
7256 *
7257 * Return : Corresponding band for SAP operating channel
7258 */
7259uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7260{
7261 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7262 QDF_STATUS status;
7263 hdd_adapter_t *adapter;
7264 uint8_t operating_channel = 0;
7265 uint8_t sap_operating_band = 0;
7266 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7267 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7268 adapter = adapter_node->pAdapter;
7269
7270 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7271 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7272 &next);
7273 adapter_node = next;
7274 continue;
7275 }
7276 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7277 if (IS_24G_CH(operating_channel))
7278 sap_operating_band = eCSR_BAND_24;
7279 else if (IS_5G_CH(operating_channel))
7280 sap_operating_band = eCSR_BAND_5G;
7281 else
7282 sap_operating_band = eCSR_BAND_ALL;
7283 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7284 &next);
7285 }
7286 return sap_operating_band;
7287}
7288
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307289static const struct nla_policy
7290wlan_hdd_set_sta_roam_config_policy[
7291QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7292 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7293 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7294};
7295
7296/**
7297 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7298 * for station connection or roaming.
7299 * @wiphy: Pointer to wireless phy
7300 * @wdev: Pointer to wireless device
7301 * @data: Pointer to data
7302 * @data_len: Length of @data
7303 *
7304 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7305 * channels needs to be skipped in scanning or not.
7306 * If dfs_mode is disabled, driver will not scan DFS channels.
7307 * If skip_unsafe_channels is set, driver will skip unsafe channels
7308 * in Scanning.
7309 *
7310 * Return: 0 on success, negative errno on failure
7311 */
7312static int
7313__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7314 struct wireless_dev *wdev,
7315 const void *data, int data_len)
7316{
7317 struct net_device *dev = wdev->netdev;
7318 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7319 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7320 struct nlattr *tb[
7321 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7322 int ret;
7323 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7324 enum dfs_mode mode = DFS_MODE_NONE;
7325 bool skip_unsafe_channels = false;
7326 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307327 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307328
7329 ENTER_DEV(dev);
7330
7331 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7332 hdd_err("Command not allowed in FTM mode");
7333 return -EINVAL;
7334 }
7335
7336 ret = wlan_hdd_validate_context(hdd_ctx);
7337 if (0 != ret)
7338 return ret;
7339 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7340 data, data_len,
7341 wlan_hdd_set_sta_roam_config_policy)) {
7342 hdd_err("invalid attr");
7343 return -EINVAL;
7344 }
7345 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7346 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7347 if (!IS_DFS_MODE_VALID(mode)) {
7348 hdd_err("attr sta roam dfs mode policy is not valid");
7349 return -EINVAL;
7350 }
7351
7352 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7353
7354 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7355 skip_unsafe_channels = nla_get_u8(
7356 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307357 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307358 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307359 skip_unsafe_channels, adapter->sessionId,
7360 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307361
7362 if (!QDF_IS_STATUS_SUCCESS(status)) {
7363 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7364 return -EINVAL;
7365 }
7366 return 0;
7367}
7368
7369/**
7370 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7371 * connection and roaming for station.
7372 * @wiphy: wiphy structure pointer
7373 * @wdev: Wireless device structure pointer
7374 * @data: Pointer to the data received
7375 * @data_len: Length of @data
7376 *
7377 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7378 * channels needs to be skipped in scanning or not.
7379 * If dfs_mode is disabled, driver will not scan DFS channels.
7380 * If skip_unsafe_channels is set, driver will skip unsafe channels
7381 * in Scanning.
7382 * Return: 0 on success; errno on failure
7383 */
7384static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7385 struct wireless_dev *wdev,
7386 const void *data, int data_len)
7387{
7388 int ret;
7389
7390 cds_ssr_protect(__func__);
7391 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7392 cds_ssr_unprotect(__func__);
7393
7394 return ret;
7395}
7396
Agrawal Ashish467dde42016-09-08 18:44:22 +05307397#ifdef FEATURE_WLAN_CH_AVOID
7398/**
7399 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7400 * is on unsafe channel.
7401 * @wiphy: wiphy structure pointer
7402 * @wdev: Wireless device structure pointer
7403 * @data: Pointer to the data received
7404 * @data_len: Length of @data
7405 *
7406 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7407 * on any of unsafe channels.
7408 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7409 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7410 *
7411 * Return: 0 on success; errno on failure
7412 */
7413static int
7414__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7415 struct wireless_dev *wdev,
7416 const void *data, int data_len)
7417{
7418 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7419 int ret;
7420 uint16_t unsafe_channel_count;
7421 int unsafe_channel_index;
7422 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7423
7424 ENTER_DEV(wdev->netdev);
7425
7426 if (!qdf_ctx) {
7427 cds_err("qdf_ctx is NULL");
7428 return -EINVAL;
7429 }
7430
7431 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7432 hdd_err("Command not allowed in FTM mode");
7433 return -EINVAL;
7434 }
7435
7436 ret = wlan_hdd_validate_context(hdd_ctx);
7437 if (0 != ret)
7438 return ret;
7439 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7440 &(hdd_ctx->unsafe_channel_count),
7441 sizeof(hdd_ctx->unsafe_channel_list));
7442
7443 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7444 (uint16_t)NUM_CHANNELS);
7445 for (unsafe_channel_index = 0;
7446 unsafe_channel_index < unsafe_channel_count;
7447 unsafe_channel_index++) {
7448 hdd_info("Channel %d is not safe",
7449 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7450 }
7451 hdd_unsafe_channel_restart_sap(hdd_ctx);
7452 return 0;
7453}
7454
7455/**
7456 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7457 * is on unsafe channel.
7458 * @wiphy: wiphy structure pointer
7459 * @wdev: Wireless device structure pointer
7460 * @data: Pointer to the data received
7461 * @data_len: Length of @data
7462 *
7463 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7464 * on any of unsafe channels.
7465 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7466 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7467 *
7468 * Return: 0 on success; errno on failure
7469 */
7470static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7471 struct wireless_dev *wdev,
7472 const void *data, int data_len)
7473{
7474 int ret;
7475
7476 cds_ssr_protect(__func__);
7477 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7478 cds_ssr_unprotect(__func__);
7479
7480 return ret;
7481}
7482
7483#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307484/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307485 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7486 * SAP is on unsafe channel.
7487 * @wiphy: wiphy structure pointer
7488 * @wdev: Wireless device structure pointer
7489 * @data: Pointer to the data received
7490 * @data_len: Length of @data
7491 *
7492 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7493 * driver.
7494 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7495 * will initiate restart of sap.
7496 *
7497 * Return: 0 on success; errno on failure
7498 */
7499static int
7500__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7501 struct wireless_dev *wdev,
7502 const void *data, int data_len)
7503{
7504 struct net_device *ndev = wdev->netdev;
7505 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7506 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7507 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7508 uint8_t config_channel = 0;
7509 hdd_ap_ctx_t *ap_ctx;
7510 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307511 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307512
7513 ENTER();
7514
7515 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007516 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307517 return -EINVAL;
7518 }
7519
7520 ret = wlan_hdd_validate_context(hdd_ctx);
7521 if (0 != ret)
7522 return -EINVAL;
7523
7524 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7525 data, data_len,
7526 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007527 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307528 return -EINVAL;
7529 }
7530
7531 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7532 if (!test_bit(SOFTAP_BSS_STARTED,
7533 &hostapd_adapter->event_flags)) {
7534 hdd_err("SAP is not started yet. Restart sap will be invalid");
7535 return -EINVAL;
7536 }
7537
7538 config_channel =
7539 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7540
7541 if (!((IS_24G_CH(config_channel)) ||
7542 (IS_5G_CH(config_channel)))) {
7543 hdd_err("Channel %d is not valid to restart SAP",
7544 config_channel);
7545 return -ENOTSUPP;
7546 }
7547
7548 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7549 ap_ctx->sapConfig.channel = config_channel;
7550 ap_ctx->sapConfig.ch_params.ch_width =
7551 ap_ctx->sapConfig.ch_width_orig;
7552
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007553 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307554 ap_ctx->sapConfig.sec_ch,
7555 &ap_ctx->sapConfig.ch_params);
7556
7557 cds_restart_sap(hostapd_adapter);
7558 }
7559
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307560 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7561 uint32_t freq_len, i;
7562 uint32_t *freq;
7563 uint8_t chans[QDF_MAX_NUM_CHAN];
7564
7565 hdd_debug("setting mandatory freq/chan list");
7566
7567 freq_len = nla_len(
7568 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7569 sizeof(uint32_t);
7570
7571 if (freq_len > QDF_MAX_NUM_CHAN) {
7572 hdd_err("insufficient space to hold channels");
7573 return -ENOMEM;
7574 }
7575
7576 freq = nla_data(
7577 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7578
7579 hdd_debug("freq_len=%d", freq_len);
7580
7581 for (i = 0; i < freq_len; i++) {
7582 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7583 hdd_debug("freq[%d]=%d", i, freq[i]);
7584 }
7585
7586 status = cds_set_sap_mandatory_channels(chans, freq_len);
7587 if (QDF_IS_STATUS_ERROR(status))
7588 return -EINVAL;
7589 }
7590
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307591 return 0;
7592}
7593
7594/**
7595 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7596 * @wiphy: wiphy structure pointer
7597 * @wdev: Wireless device structure pointer
7598 * @data: Pointer to the data received
7599 * @data_len: Length of @data
7600 *
7601 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7602 * driver.
7603 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7604 * will initiate restart of sap.
7605 *
7606 * Return: 0 on success; errno on failure
7607 */
7608static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7609 struct wireless_dev *wdev,
7610 const void *data, int data_len)
7611{
7612 int ret;
7613
7614 cds_ssr_protect(__func__);
7615 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7616 wdev, data, data_len);
7617 cds_ssr_unprotect(__func__);
7618
7619 return ret;
7620}
7621
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307622#undef BPF_INVALID
7623#undef BPF_SET_RESET
7624#undef BPF_VERSION
7625#undef BPF_ID
7626#undef BPF_PACKET_SIZE
7627#undef BPF_CURRENT_OFFSET
7628#undef BPF_PROGRAM
7629#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307630
7631/**
7632 * define short names for the global vendor params
7633 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7634 */
7635#define PARAM_TOTAL_CMD_EVENT_WAKE \
7636 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7637#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7638 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7639#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7640 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7641#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7642 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7643#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7644 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7645#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7646 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7647#define PARAM_TOTAL_RX_DATA_WAKE \
7648 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7649#define PARAM_RX_UNICAST_CNT \
7650 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7651#define PARAM_RX_MULTICAST_CNT \
7652 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7653#define PARAM_RX_BROADCAST_CNT \
7654 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7655#define PARAM_ICMP_PKT \
7656 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7657#define PARAM_ICMP6_PKT \
7658 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7659#define PARAM_ICMP6_RA \
7660 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7661#define PARAM_ICMP6_NA \
7662 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7663#define PARAM_ICMP6_NS \
7664 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7665#define PARAM_ICMP4_RX_MULTICAST_CNT \
7666 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7667#define PARAM_ICMP6_RX_MULTICAST_CNT \
7668 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7669#define PARAM_OTHER_RX_MULTICAST_CNT \
7670 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307671#define PARAM_RSSI_BREACH_CNT \
7672 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
7673#define PARAM_LOW_RSSI_CNT \
7674 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
7675#define PARAM_GSCAN_CNT \
7676 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
7677#define PARAM_PNO_COMPLETE_CNT \
7678 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
7679#define PARAM_PNO_MATCH_CNT \
7680 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
7681
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307682
7683
7684/**
7685 * hdd_send_wakelock_stats() - API to send wakelock stats
7686 * @ctx: context to be passed to callback
7687 * @data: data passed to callback
7688 *
7689 * This function is used to send wake lock stats to HAL layer
7690 *
7691 * Return: 0 on success, error number otherwise.
7692 */
7693static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7694 const struct sir_wake_lock_stats *data)
7695{
7696 struct sk_buff *skb;
7697 uint32_t nl_buf_len;
7698 uint32_t total_rx_data_wake, rx_multicast_cnt;
7699 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307700 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307701
7702 ENTER();
7703
7704 nl_buf_len = NLMSG_HDRLEN;
7705 nl_buf_len +=
7706 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7707 (NLMSG_HDRLEN + sizeof(uint32_t));
7708
7709 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7710
7711 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007712 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307713 return -ENOMEM;
7714 }
7715
Jeff Johnson64943bd2016-08-23 13:14:06 -07007716 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307717 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007718 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307719 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007720 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307721 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007722 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307723 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007724 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307725 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007726 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307727 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007728 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307729 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007730 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7731 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307732 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307733 hdd_info("wow_rssi_breach_wake_up_count %d",
7734 data->wow_rssi_breach_wake_up_count);
7735 hdd_info("wow_low_rssi_wake_up_count %d",
7736 data->wow_low_rssi_wake_up_count);
7737 hdd_info("wow_gscan_wake_up_count %d",
7738 data->wow_gscan_wake_up_count);
7739 hdd_info("wow_pno_complete_wake_up_count %d",
7740 data->wow_pno_complete_wake_up_count);
7741 hdd_info("wow_pno_match_wake_up_count %d",
7742 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307743
7744 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307745 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307746
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307747 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307748 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307749
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307750 rx_multicast_cnt =
7751 data->wow_ipv4_mcast_wake_up_count +
7752 ipv6_rx_multicast_addr_cnt;
7753
7754 total_rx_data_wake =
7755 data->wow_ucast_wake_up_count +
7756 data->wow_bcast_wake_up_count +
7757 rx_multicast_cnt;
7758
7759 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7760 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7761 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7762 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7763 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7764 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7765 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7766 total_rx_data_wake) ||
7767 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7768 data->wow_ucast_wake_up_count) ||
7769 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7770 rx_multicast_cnt) ||
7771 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7772 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307773 nla_put_u32(skb, PARAM_ICMP_PKT,
7774 data->wow_icmpv4_count) ||
7775 nla_put_u32(skb, PARAM_ICMP6_PKT,
7776 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307777 nla_put_u32(skb, PARAM_ICMP6_RA,
7778 data->wow_ipv6_mcast_ra_stats) ||
7779 nla_put_u32(skb, PARAM_ICMP6_NA,
7780 data->wow_ipv6_mcast_na_stats) ||
7781 nla_put_u32(skb, PARAM_ICMP6_NS,
7782 data->wow_ipv6_mcast_ns_stats) ||
7783 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7784 data->wow_ipv4_mcast_wake_up_count) ||
7785 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7786 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307787 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
7788 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
7789 data->wow_rssi_breach_wake_up_count) ||
7790 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
7791 data->wow_low_rssi_wake_up_count) ||
7792 nla_put_u32(skb, PARAM_GSCAN_CNT,
7793 data->wow_gscan_wake_up_count) ||
7794 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
7795 data->wow_pno_complete_wake_up_count) ||
7796 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
7797 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007798 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307799 goto nla_put_failure;
7800 }
7801
7802 cfg80211_vendor_cmd_reply(skb);
7803
7804 EXIT();
7805 return 0;
7806
7807nla_put_failure:
7808 kfree_skb(skb);
7809 return -EINVAL;
7810}
7811
7812/**
7813 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7814 * @wiphy: wiphy pointer
7815 * @wdev: pointer to struct wireless_dev
7816 * @data: pointer to incoming NL vendor data
7817 * @data_len: length of @data
7818 *
7819 * This function parses the incoming NL vendor command data attributes and
7820 * invokes the SME Api and blocks on a completion variable.
7821 * WMA copies required data and invokes callback
7822 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7823 *
7824 * Return: 0 on success; error number otherwise.
7825 */
7826static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7827 struct wireless_dev *wdev,
7828 const void *data,
7829 int data_len)
7830{
7831 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7832 int status, ret;
7833 struct sir_wake_lock_stats wake_lock_stats;
7834 QDF_STATUS qdf_status;
7835
7836 ENTER();
7837
7838 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007839 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307840 return -EINVAL;
7841 }
7842
7843 status = wlan_hdd_validate_context(hdd_ctx);
7844 if (0 != status)
7845 return -EINVAL;
7846
7847 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7848 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007849 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307850 return -EINVAL;
7851 }
7852
7853 ret = hdd_send_wakelock_stats(hdd_ctx,
7854 &wake_lock_stats);
7855 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007856 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307857
7858 EXIT();
7859 return ret;
7860}
7861
7862/**
7863 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7864 * @wiphy: wiphy pointer
7865 * @wdev: pointer to struct wireless_dev
7866 * @data: pointer to incoming NL vendor data
7867 * @data_len: length of @data
7868 *
7869 * This function parses the incoming NL vendor command data attributes and
7870 * invokes the SME Api and blocks on a completion variable.
7871 * WMA copies required data and invokes callback
7872 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7873 *
7874 * Return: 0 on success; error number otherwise.
7875 */
7876static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7877 struct wireless_dev *wdev,
7878 const void *data, int data_len)
7879{
7880 int ret;
7881
7882 cds_ssr_protect(__func__);
7883 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7884 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007885 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307886
7887 return ret;
7888}
7889
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307890/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307891 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7892 * @wiphy: wiphy structure pointer
7893 * @wdev: Wireless device structure pointer
7894 * @data: Pointer to the data received
7895 * @data_len: Length of @data
7896 *
7897 * This function reads wmi max bus size and fill in the skb with
7898 * NL attributes and send up the NL event.
7899 * Return: 0 on success; errno on failure
7900 */
7901static int
7902__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7903 struct wireless_dev *wdev,
7904 const void *data, int data_len)
7905{
7906 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7907 int ret_val;
7908 struct sk_buff *skb;
7909 uint32_t nl_buf_len;
7910
7911 ENTER();
7912
7913 ret_val = wlan_hdd_validate_context(hdd_ctx);
7914 if (ret_val)
7915 return ret_val;
7916
7917 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7918 hdd_err("Command not allowed in FTM mode");
7919 return -EINVAL;
7920 }
7921
7922 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7923
7924 nl_buf_len = NLMSG_HDRLEN;
7925 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7926
7927 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7928 if (!skb) {
7929 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7930 return -ENOMEM;
7931 }
7932
7933 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7934 hdd_ctx->wmi_max_len)) {
7935 hdd_err("nla put failure");
7936 goto nla_put_failure;
7937 }
7938
7939 cfg80211_vendor_cmd_reply(skb);
7940
7941 EXIT();
7942
7943 return 0;
7944
7945nla_put_failure:
7946 kfree_skb(skb);
7947 return -EINVAL;
7948}
7949
7950/**
7951 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7952 * @wiphy: wiphy structure pointer
7953 * @wdev: Wireless device structure pointer
7954 * @data: Pointer to the data received
7955 * @data_len: Length of @data
7956 *
7957 * Return: 0 on success; errno on failure
7958 */
7959static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7960 struct wireless_dev *wdev,
7961 const void *data, int data_len)
7962{
7963 int ret;
7964
7965 cds_ssr_protect(__func__);
7966 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7967 cds_ssr_unprotect(__func__);
7968
7969 return ret;
7970}
7971
7972/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307973 *__wlan_hdd_cfg80211_setband() - set band
7974 * @wiphy: Pointer to wireless phy
7975 * @wdev: Pointer to wireless device
7976 * @data: Pointer to data
7977 * @data_len: Length of @data
7978 *
7979 * Return: 0 on success, negative errno on failure
7980 */
7981static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7982 struct wireless_dev *wdev,
7983 const void *data, int data_len)
7984{
7985 struct net_device *dev = wdev->netdev;
7986 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7987 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7988 int ret;
7989 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7990 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7991
7992 ENTER();
7993
7994 ret = wlan_hdd_validate_context(hdd_ctx);
7995 if (ret)
7996 return ret;
7997
7998 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7999 hdd_err(FL("Invalid ATTR"));
8000 return -EINVAL;
8001 }
8002
8003 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8004 hdd_err(FL("attr SETBAND_VALUE failed"));
8005 return -EINVAL;
8006 }
8007
8008 ret = hdd_set_band(dev,
8009 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8010
8011 EXIT();
8012 return ret;
8013}
8014
8015/**
8016 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8017 * @wiphy: wiphy structure pointer
8018 * @wdev: Wireless device structure pointer
8019 * @data: Pointer to the data received
8020 * @data_len: Length of @data
8021 *
8022 * Return: 0 on success; errno on failure
8023 */
8024static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8025 struct wireless_dev *wdev,
8026 const void *data, int data_len)
8027{
8028 int ret;
8029
8030 cds_ssr_protect(__func__);
8031 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8032 cds_ssr_unprotect(__func__);
8033
8034 return ret;
8035}
8036
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008037/**
8038 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8039 * @nl80211_value: Vendor command attribute value
8040 * @wmi_value: Pointer to return converted WMI return value
8041 *
8042 * Convert NL80211 vendor command value for SAR limit set to WMI value
8043 * Return: 0 on success, -1 on invalid value
8044 */
8045static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8046 u32 *wmi_value)
8047{
8048 int ret = 0;
8049
8050 switch (nl80211_value) {
8051 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8052 *wmi_value = WMI_SAR_FEATURE_OFF;
8053 break;
8054 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8055 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8056 break;
8057 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8058 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8059 break;
8060 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8061 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8062 break;
8063 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8064 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8065 break;
8066 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8067 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8068 break;
8069 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8070 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8071 break;
8072 default:
8073 ret = -1;
8074 }
8075 return ret;
8076}
8077
8078/**
8079 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8080 * @nl80211_value: Vendor command attribute value
8081 * @wmi_value: Pointer to return converted WMI return value
8082 *
8083 * Convert NL80211 vendor command value for SAR BAND to WMI value
8084 * Return: 0 on success, -1 on invalid value
8085 */
8086static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8087{
8088 int ret = 0;
8089
8090 switch (nl80211_value) {
8091 case NL80211_BAND_2GHZ:
8092 *wmi_value = WMI_SAR_2G_ID;
8093 break;
8094 case NL80211_BAND_5GHZ:
8095 *wmi_value = WMI_SAR_5G_ID;
8096 break;
8097 default:
8098 ret = -1;
8099 }
8100 return ret;
8101}
8102
8103/**
8104 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8105 * @nl80211_value: Vendor command attribute value
8106 * @wmi_value: Pointer to return converted WMI return value
8107 *
8108 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8109 * Return: 0 on success, -1 on invalid value
8110 */
8111static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8112 u32 *wmi_value)
8113{
8114 int ret = 0;
8115
8116 switch (nl80211_value) {
8117 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
8118 *wmi_value = WMI_SAR_MOD_CCK;
8119 break;
8120 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
8121 *wmi_value = WMI_SAR_MOD_OFDM;
8122 break;
8123 default:
8124 ret = -1;
8125 }
8126 return ret;
8127}
8128
8129
8130/**
8131 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
8132 * @wiphy: Pointer to wireless phy
8133 * @wdev: Pointer to wireless device
8134 * @data: Pointer to data
8135 * @data_len: Length of @data
8136 *
8137 * This function is used to setup Specific Absorption Rate limit specs.
8138 *
8139 * Return: 0 on success, negative errno on failure
8140 */
8141static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
8142 struct wireless_dev *wdev,
8143 const void *data, int data_len)
8144{
8145 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8146 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8147 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
8148 *sar_spec_list;
8149 struct sar_limit_cmd_params sar_limit_cmd = {0};
8150 int ret = -EINVAL, i = 0, rem = 0;
8151
8152 ENTER();
8153
8154 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8155 hdd_err("Command not allowed in FTM mode");
8156 return -EPERM;
8157 }
8158
8159 if (wlan_hdd_validate_context(hdd_ctx))
8160 return -EINVAL;
8161
8162 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
8163 data, data_len, NULL)) {
8164 hdd_err("Invalid SAR attributes");
8165 return -EINVAL;
8166 }
8167
8168 /* Vendor command manadates all SAR Specs in single call */
8169 sar_limit_cmd.commit_limits = 1;
8170 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
8171 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
8172 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
8173 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
8174 &sar_limit_cmd.sar_enable) < 0) {
8175 hdd_err("Invalid SAR Enable attr");
8176 goto fail;
8177 }
8178 }
8179 hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
8180
8181 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
8182 sar_limit_cmd.num_limit_rows = nla_get_u32(
8183 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
8184 hdd_info("attr sar num_limit_rows %d",
8185 sar_limit_cmd.num_limit_rows);
8186 }
8187 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
8188 hdd_err("SAR Spec list exceed supported size");
8189 goto fail;
8190 }
8191 if (sar_limit_cmd.num_limit_rows == 0)
8192 goto send_sar_limits;
8193 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
8194 struct sar_limit_cmd_row) *
8195 sar_limit_cmd.num_limit_rows);
8196 if (!sar_limit_cmd.sar_limit_row_list) {
8197 ret = -ENOMEM;
8198 goto fail;
8199 }
8200 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
8201 hdd_err("Invalid SAR SPECs list");
8202 goto fail;
8203 }
8204
8205 nla_for_each_nested(sar_spec_list,
8206 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
8207 if (i == sar_limit_cmd.num_limit_rows) {
8208 hdd_warn("SAR Cmd has excess SPECs in list");
8209 break;
8210 }
8211
8212 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
8213 nla_data(sar_spec_list), nla_len(sar_spec_list),
8214 NULL)) {
8215 hdd_err("nla_parse failed for SAR Spec list");
8216 goto fail;
8217 }
8218 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
8219 if (sar_spec[
8220 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
8221 sar_limit_cmd.sar_limit_row_list[i].limit_value =
8222 nla_get_u32(sar_spec[
8223 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
8224 } else {
8225 hdd_err("SAR Spec does not have power limit value");
8226 goto fail;
8227 }
8228
8229 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
8230 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
8231 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
8232 &sar_limit_cmd.sar_limit_row_list[i].band_id)
8233 < 0) {
8234 hdd_err("Invalid SAR Band attr");
8235 goto fail;
8236 }
8237 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8238 WMI_SAR_BAND_ID_VALID_MASK;
8239 }
8240 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
8241 sar_limit_cmd.sar_limit_row_list[i].chain_id =
8242 nla_get_u32(sar_spec[
8243 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
8244 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8245 WMI_SAR_CHAIN_ID_VALID_MASK;
8246 }
8247 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
8248 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
8249 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
8250 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
8251 < 0) {
8252 hdd_err("Invalid SAR Modulation attr");
8253 goto fail;
8254 }
8255 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
8256 WMI_SAR_MOD_ID_VALID_MASK;
8257 }
8258 hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
8259 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
8260 sar_limit_cmd.sar_limit_row_list[i].chain_id,
8261 sar_limit_cmd.sar_limit_row_list[i].mod_id,
8262 sar_limit_cmd.sar_limit_row_list[i].limit_value,
8263 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
8264 i++;
8265 }
8266
8267 if (i < sar_limit_cmd.num_limit_rows) {
8268 hdd_warn("SAR Cmd has less SPECs in list");
8269 sar_limit_cmd.num_limit_rows = i;
8270 }
8271
8272send_sar_limits:
8273 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
8274 QDF_STATUS_SUCCESS)
8275 ret = 0;
8276fail:
8277 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
8278 return ret;
8279}
8280
8281/**
8282 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
8283 * @wiphy: Pointer to wireless phy
8284 * @wdev: Pointer to wireless device
8285 * @data: Pointer to data
8286 * @data_len: Length of @data
8287 *
8288 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
8289 *
8290 * Return: 0 on success, negative errno on failure
8291 */
8292static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
8293 struct wireless_dev *wdev,
8294 const void *data,
8295 int data_len)
8296{
8297 int ret;
8298
8299 cds_ssr_protect(__func__);
8300 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
8301 data_len);
8302 cds_ssr_unprotect(__func__);
8303
8304 return ret;
8305}
8306
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308307static const struct
8308nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
8309 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
8310 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
8311 .len = QDF_MAC_ADDR_SIZE},
8312};
8313
8314/**
8315 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8316 * @wiphy: Pointer to wireless phy
8317 * @wdev: Pointer to wireless device
8318 * @data: Pointer to data
8319 * @data_len: Length of @data
8320 *
8321 * This function is used to enable/disable roaming using vendor commands
8322 *
8323 * Return: 0 on success, negative errno on failure
8324 */
8325static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8326 struct wireless_dev *wdev,
8327 const void *data, int data_len)
8328{
8329 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8330 struct net_device *dev = wdev->netdev;
8331 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
8332 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8333 uint32_t is_fast_roam_enabled;
8334 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05308335 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308336
8337 ENTER_DEV(dev);
8338
8339 ret = wlan_hdd_validate_context(hdd_ctx);
8340 if (0 != ret)
8341 return ret;
8342
8343 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8344 hdd_err("Command not allowed in FTM mode");
8345 return -EINVAL;
8346 }
8347
8348 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
8349 qca_wlan_vendor_attr);
8350 if (ret) {
8351 hdd_err("Invalid ATTR");
8352 return -EINVAL;
8353 }
8354
8355 /* Parse and fetch Enable flag */
8356 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
8357 hdd_err("attr enable failed");
8358 return -EINVAL;
8359 }
8360
8361 is_fast_roam_enabled = nla_get_u32(
8362 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008363 hdd_notice("isFastRoamEnabled %d fast_roaming_allowed %d",
8364 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308365
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008366 if (!adapter->fast_roaming_allowed) {
8367 hdd_err("fast roaming not allowed on %s interface",
8368 adapter->dev->name);
8369 return -EINVAL;
8370 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308371 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05308372 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08008373 (is_fast_roam_enabled &&
8374 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05308375 if (qdf_status != QDF_STATUS_SUCCESS)
8376 hdd_err("sme_config_fast_roaming failed with status=%d",
8377 qdf_status);
8378 ret = qdf_status_to_os_return(qdf_status);
8379
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308380 EXIT();
8381 return ret;
8382}
8383
8384/**
8385 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8386 * @wiphy: Pointer to wireless phy
8387 * @wdev: Pointer to wireless device
8388 * @data: Pointer to data
8389 * @data_len: Length of @data
8390 *
8391 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
8392 *
8393 * Return: 0 on success, negative errno on failure
8394 */
8395static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8396 struct wireless_dev *wdev,
8397 const void *data, int data_len)
8398{
8399 int ret;
8400
8401 cds_ssr_protect(__func__);
8402 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
8403 cds_ssr_unprotect(__func__);
8404
8405 return ret;
8406}
8407
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008408const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
8409 {
8410 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8411 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
8412 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05308413 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008414 .doit = is_driver_dfs_capable
8415 },
8416
8417#ifdef WLAN_FEATURE_NAN
8418 {
8419 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8420 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
8421 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8422 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8423 .doit = wlan_hdd_cfg80211_nan_request
8424 },
8425#endif
8426
8427#ifdef WLAN_FEATURE_STATS_EXT
8428 {
8429 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8430 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
8431 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8432 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8433 .doit = wlan_hdd_cfg80211_stats_ext_request
8434 },
8435#endif
8436#ifdef FEATURE_WLAN_EXTSCAN
8437 {
8438 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8439 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
8440 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8441 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8442 .doit = wlan_hdd_cfg80211_extscan_start
8443 },
8444 {
8445 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8446 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
8447 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8448 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8449 .doit = wlan_hdd_cfg80211_extscan_stop
8450 },
8451 {
8452 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8453 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8454 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8455 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8456 },
8457 {
8458 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8459 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8460 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8461 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8462 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8463 },
8464 {
8465 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8466 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8467 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8468 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8469 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8470 },
8471 {
8472 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8473 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8474 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8475 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8476 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8477 },
8478 {
8479 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8480 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8481 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8482 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8483 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8484 },
8485 {
8486 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8487 .info.subcmd =
8488 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8489 .flags =
8490 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8491 WIPHY_VENDOR_CMD_NEED_RUNNING,
8492 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8493 },
8494 {
8495 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8496 .info.subcmd =
8497 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8498 .flags =
8499 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8500 WIPHY_VENDOR_CMD_NEED_RUNNING,
8501 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8502 },
8503 {
8504 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8505 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8506 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8507 WIPHY_VENDOR_CMD_NEED_NETDEV |
8508 WIPHY_VENDOR_CMD_NEED_RUNNING,
8509 .doit = wlan_hdd_cfg80211_set_epno_list
8510 },
8511#endif /* FEATURE_WLAN_EXTSCAN */
8512
8513#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8514 {
8515 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8516 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8517 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8518 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8519 .doit = wlan_hdd_cfg80211_ll_stats_clear
8520 },
8521
8522 {
8523 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8524 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8525 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8526 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8527 .doit = wlan_hdd_cfg80211_ll_stats_set
8528 },
8529
8530 {
8531 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8532 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8533 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8534 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8535 .doit = wlan_hdd_cfg80211_ll_stats_get
8536 },
8537#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8538#ifdef FEATURE_WLAN_TDLS
8539 {
8540 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8541 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8542 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8543 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8544 .doit = wlan_hdd_cfg80211_exttdls_enable
8545 },
8546 {
8547 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8548 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8549 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8550 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8551 .doit = wlan_hdd_cfg80211_exttdls_disable
8552 },
8553 {
8554 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8555 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8556 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8557 .doit = wlan_hdd_cfg80211_exttdls_get_status
8558 },
8559#endif
8560 {
8561 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8562 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8563 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8564 .doit = wlan_hdd_cfg80211_get_supported_features
8565 },
8566 {
8567 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8568 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8569 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8570 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8571 },
8572 {
8573 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8574 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8575 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308576 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008577 },
8578 {
8579 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8580 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8581 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8582 WIPHY_VENDOR_CMD_NEED_NETDEV,
8583 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8584 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008585 {
8586 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8587 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8588 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8589 WIPHY_VENDOR_CMD_NEED_NETDEV,
8590 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8591 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008592 {
8593 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308594 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8595 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8596 WIPHY_VENDOR_CMD_NEED_NETDEV |
8597 WIPHY_VENDOR_CMD_NEED_RUNNING,
8598 .doit = hdd_cfg80211_get_station_cmd
8599 },
8600 {
8601 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008602 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8603 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8604 WIPHY_VENDOR_CMD_NEED_NETDEV |
8605 WIPHY_VENDOR_CMD_NEED_RUNNING,
8606 .doit = wlan_hdd_cfg80211_do_acs
8607 },
8608
8609 {
8610 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8611 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8612 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8613 WIPHY_VENDOR_CMD_NEED_NETDEV,
8614 .doit = wlan_hdd_cfg80211_get_features
8615 },
8616#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8617 {
8618 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8619 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8620 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8621 WIPHY_VENDOR_CMD_NEED_NETDEV |
8622 WIPHY_VENDOR_CMD_NEED_RUNNING,
8623 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8624 },
8625#endif
8626#ifdef FEATURE_WLAN_EXTSCAN
8627 {
8628 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8629 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8630 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8631 WIPHY_VENDOR_CMD_NEED_NETDEV |
8632 WIPHY_VENDOR_CMD_NEED_RUNNING,
8633 .doit = wlan_hdd_cfg80211_set_passpoint_list
8634 },
8635 {
8636 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8637 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8638 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8639 WIPHY_VENDOR_CMD_NEED_NETDEV |
8640 WIPHY_VENDOR_CMD_NEED_RUNNING,
8641 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8642 },
8643 {
8644 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8645 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8646 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8647 WIPHY_VENDOR_CMD_NEED_NETDEV |
8648 WIPHY_VENDOR_CMD_NEED_RUNNING,
8649 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8650 },
8651 {
8652 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8653 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8654 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8655 WIPHY_VENDOR_CMD_NEED_NETDEV |
8656 WIPHY_VENDOR_CMD_NEED_RUNNING,
8657 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8658 },
8659#endif /* FEATURE_WLAN_EXTSCAN */
8660 {
8661 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8662 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8663 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8664 WIPHY_VENDOR_CMD_NEED_NETDEV,
8665 .doit = wlan_hdd_cfg80211_get_wifi_info
8666 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008667#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008668 {
8669 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8670 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8671 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8672 WIPHY_VENDOR_CMD_NEED_NETDEV |
8673 WIPHY_VENDOR_CMD_NEED_RUNNING,
8674 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8675 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008676#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008677 {
8678 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8679 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8680 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8681 WIPHY_VENDOR_CMD_NEED_NETDEV,
8682 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8683 },
8684 {
8685 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8686 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8687 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8688 WIPHY_VENDOR_CMD_NEED_NETDEV,
8689 .doit = wlan_hdd_cfg80211_wifi_logger_start
8690 },
8691 {
8692 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8693 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8694 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8695 WIPHY_VENDOR_CMD_NEED_NETDEV,
8696 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8697 },
8698 {
8699 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8700 .info.subcmd =
8701 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8702 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8703 WIPHY_VENDOR_CMD_NEED_NETDEV |
8704 WIPHY_VENDOR_CMD_NEED_RUNNING,
8705 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8706 },
8707 {
8708 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8709 .info.subcmd =
8710 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8711 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8712 WIPHY_VENDOR_CMD_NEED_NETDEV |
8713 WIPHY_VENDOR_CMD_NEED_RUNNING,
8714 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8715 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008716#ifdef WLAN_FEATURE_TSF
8717 {
8718 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8719 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8720 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8721 WIPHY_VENDOR_CMD_NEED_NETDEV |
8722 WIPHY_VENDOR_CMD_NEED_RUNNING,
8723 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8724 },
8725#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008726#ifdef FEATURE_WLAN_TDLS
8727 {
8728 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8729 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8730 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8731 WIPHY_VENDOR_CMD_NEED_NETDEV |
8732 WIPHY_VENDOR_CMD_NEED_RUNNING,
8733 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8734 },
8735#endif
8736#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8737 {
8738 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8739 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8740 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8741 WIPHY_VENDOR_CMD_NEED_NETDEV |
8742 WIPHY_VENDOR_CMD_NEED_RUNNING,
8743 .doit = wlan_hdd_cfg80211_offloaded_packets
8744 },
8745#endif
8746 {
8747 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8748 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8749 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8750 WIPHY_VENDOR_CMD_NEED_NETDEV |
8751 WIPHY_VENDOR_CMD_NEED_RUNNING,
8752 .doit = wlan_hdd_cfg80211_monitor_rssi
8753 },
8754 {
8755 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308756 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8757 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8758 WIPHY_VENDOR_CMD_NEED_NETDEV |
8759 WIPHY_VENDOR_CMD_NEED_RUNNING,
8760 .doit = wlan_hdd_cfg80211_set_ns_offload
8761 },
8762 {
8763 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008764 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8765 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8766 WIPHY_VENDOR_CMD_NEED_NETDEV |
8767 WIPHY_VENDOR_CMD_NEED_RUNNING,
8768 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8769 },
8770#ifdef WLAN_FEATURE_MEMDUMP
8771 {
8772 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8773 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8774 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8775 WIPHY_VENDOR_CMD_NEED_NETDEV |
8776 WIPHY_VENDOR_CMD_NEED_RUNNING,
8777 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8778 },
8779#endif /* WLAN_FEATURE_MEMDUMP */
8780 {
8781 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8782 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8783 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8784 WIPHY_VENDOR_CMD_NEED_NETDEV |
8785 WIPHY_VENDOR_CMD_NEED_RUNNING,
8786 .doit = wlan_hdd_cfg80211_vendor_scan
8787 },
8788
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05308789 /* Vendor abort scan */
8790 {
8791 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8792 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
8793 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8794 WIPHY_VENDOR_CMD_NEED_NETDEV |
8795 WIPHY_VENDOR_CMD_NEED_RUNNING,
8796 .doit = wlan_hdd_vendor_abort_scan
8797 },
8798
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008799 /* OCB commands */
8800 {
8801 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8802 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8803 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8804 WIPHY_VENDOR_CMD_NEED_NETDEV |
8805 WIPHY_VENDOR_CMD_NEED_RUNNING,
8806 .doit = wlan_hdd_cfg80211_ocb_set_config
8807 },
8808 {
8809 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8810 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8811 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8812 WIPHY_VENDOR_CMD_NEED_NETDEV |
8813 WIPHY_VENDOR_CMD_NEED_RUNNING,
8814 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8815 },
8816 {
8817 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8818 .info.subcmd =
8819 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8820 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8821 WIPHY_VENDOR_CMD_NEED_NETDEV |
8822 WIPHY_VENDOR_CMD_NEED_RUNNING,
8823 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8824 },
8825 {
8826 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8827 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8828 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8829 WIPHY_VENDOR_CMD_NEED_NETDEV |
8830 WIPHY_VENDOR_CMD_NEED_RUNNING,
8831 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8832 },
8833 {
8834 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8835 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8836 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8837 WIPHY_VENDOR_CMD_NEED_NETDEV |
8838 WIPHY_VENDOR_CMD_NEED_RUNNING,
8839 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8840 },
8841 {
8842 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8843 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8844 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8845 WIPHY_VENDOR_CMD_NEED_NETDEV |
8846 WIPHY_VENDOR_CMD_NEED_RUNNING,
8847 .doit = wlan_hdd_cfg80211_dcc_get_stats
8848 },
8849 {
8850 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8851 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8852 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8853 WIPHY_VENDOR_CMD_NEED_NETDEV |
8854 WIPHY_VENDOR_CMD_NEED_RUNNING,
8855 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8856 },
8857 {
8858 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8859 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8860 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8861 WIPHY_VENDOR_CMD_NEED_NETDEV |
8862 WIPHY_VENDOR_CMD_NEED_RUNNING,
8863 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8864 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308865 {
8866 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8867 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8868 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8869 WIPHY_VENDOR_CMD_NEED_NETDEV |
8870 WIPHY_VENDOR_CMD_NEED_RUNNING,
8871 .doit = wlan_hdd_cfg80211_get_link_properties
8872 },
Peng Xu278d0122015-09-24 16:34:17 -07008873 {
Peng Xud2220962016-07-11 17:59:17 -07008874 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008875 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8876 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8877 WIPHY_VENDOR_CMD_NEED_NETDEV |
8878 WIPHY_VENDOR_CMD_NEED_RUNNING,
8879 .doit = wlan_hdd_cfg80211_set_ota_test
8880 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008881#ifdef FEATURE_LFR_SUBNET_DETECTION
8882 {
8883 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8884 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8885 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8886 WIPHY_VENDOR_CMD_NEED_NETDEV |
8887 WIPHY_VENDOR_CMD_NEED_RUNNING,
8888 .doit = wlan_hdd_cfg80211_set_gateway_params
8889 },
8890#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008891 {
Peng Xud2220962016-07-11 17:59:17 -07008892 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008893 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8894 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8895 WIPHY_VENDOR_CMD_NEED_NETDEV |
8896 WIPHY_VENDOR_CMD_NEED_RUNNING,
8897 .doit = wlan_hdd_cfg80211_txpower_scale
8898 },
8899 {
8900 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8901 .info.subcmd =
8902 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8903 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8904 WIPHY_VENDOR_CMD_NEED_NETDEV |
8905 WIPHY_VENDOR_CMD_NEED_RUNNING,
8906 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8907 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308908 {
8909 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8910 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8911 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8912 WIPHY_VENDOR_CMD_NEED_NETDEV |
8913 WIPHY_VENDOR_CMD_NEED_RUNNING,
8914 .doit = wlan_hdd_cfg80211_bpf_offload
8915 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308916 {
8917 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308918 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8919 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8920 WIPHY_VENDOR_CMD_NEED_NETDEV |
8921 WIPHY_VENDOR_CMD_NEED_RUNNING,
8922 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8923 },
8924 {
8925 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308926 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8927 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8928 WIPHY_VENDOR_CMD_NEED_NETDEV |
8929 WIPHY_VENDOR_CMD_NEED_RUNNING,
8930 .doit = wlan_hdd_cfg80211_sta_roam_policy
8931 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308932#ifdef FEATURE_WLAN_CH_AVOID
8933 {
8934 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8935 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8936 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8937 WIPHY_VENDOR_CMD_NEED_NETDEV |
8938 WIPHY_VENDOR_CMD_NEED_RUNNING,
8939 .doit = wlan_hdd_cfg80211_avoid_freq
8940 },
8941#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308942 {
8943 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308944 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8945 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8946 WIPHY_VENDOR_CMD_NEED_NETDEV |
8947 WIPHY_VENDOR_CMD_NEED_RUNNING,
8948 .doit = wlan_hdd_cfg80211_sap_configuration_set
8949 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008950 {
Peng Xu4225c152016-07-14 21:18:14 -07008951 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008952 .info.subcmd =
8953 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8954 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8955 WIPHY_VENDOR_CMD_NEED_NETDEV |
8956 WIPHY_VENDOR_CMD_NEED_RUNNING,
8957 .doit = wlan_hdd_cfg80211_p2p_lo_start
8958 },
8959 {
8960 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8961 .info.subcmd =
8962 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8963 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8964 WIPHY_VENDOR_CMD_NEED_NETDEV |
8965 WIPHY_VENDOR_CMD_NEED_RUNNING,
8966 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8967 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308968 {
8969 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8970 .info.subcmd =
8971 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8972 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8973 WIPHY_VENDOR_CMD_NEED_NETDEV |
8974 WIPHY_VENDOR_CMD_NEED_RUNNING,
8975 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8976 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008977#ifdef WLAN_FEATURE_NAN_DATAPATH
8978 {
8979 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8980 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8981 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8982 WIPHY_VENDOR_CMD_NEED_NETDEV |
8983 WIPHY_VENDOR_CMD_NEED_RUNNING,
8984 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8985 },
8986#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308987 {
8988 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8989 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8990 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8991 WIPHY_VENDOR_CMD_NEED_NETDEV |
8992 WIPHY_VENDOR_CMD_NEED_RUNNING,
8993 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8994 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308995 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308996 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8997 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8998 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8999 WIPHY_VENDOR_CMD_NEED_NETDEV |
9000 WIPHY_VENDOR_CMD_NEED_RUNNING,
9001 .doit = wlan_hdd_cfg80211_get_bus_size
9002 },
9003 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309004 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
9005 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9006 WIPHY_VENDOR_CMD_NEED_NETDEV |
9007 WIPHY_VENDOR_CMD_NEED_RUNNING,
9008 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309009 },
9010 {
9011 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9012 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
9013 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9014 WIPHY_VENDOR_CMD_NEED_NETDEV |
9015 WIPHY_VENDOR_CMD_NEED_RUNNING,
9016 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05309017 },
9018#ifdef WLAN_FEATURE_DISA
9019 {
9020 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9021 .info.subcmd =
9022 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
9023 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9024 WIPHY_VENDOR_CMD_NEED_NETDEV |
9025 WIPHY_VENDOR_CMD_NEED_RUNNING,
9026 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
9027 },
9028#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07009029#ifdef FEATURE_WLAN_TDLS
9030 {
9031 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9032 .info.subcmd =
9033 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
9034 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9035 WIPHY_VENDOR_CMD_NEED_NETDEV |
9036 WIPHY_VENDOR_CMD_NEED_RUNNING,
9037 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009038 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -07009039#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009040 {
9041 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9042 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
9043 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9044 WIPHY_VENDOR_CMD_NEED_RUNNING,
9045 .doit = wlan_hdd_cfg80211_set_sar_power_limits
9046 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009047#ifdef WLAN_UMAC_CONVERGENCE
9048 COMMON_VENDOR_COMMANDS
9049#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009050};
9051
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05309052#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
9053 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
9054 defined(FEATURE_WLAN_SCAN_PNO)
9055/**
9056 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
9057 * @wiphy: pointer to wiphy
9058 * @config: pointer to config
9059 *
9060 * Return: None
9061 */
9062static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
9063 struct hdd_config *config)
9064{
9065 if (config->configPNOScanSupport) {
9066 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9067 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
9068 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
9069 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
9070 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
9071 if (config->max_sched_scan_plan_interval)
9072 wiphy->max_sched_scan_plan_interval =
9073 config->max_sched_scan_plan_interval;
9074 if (config->max_sched_scan_plan_iterations)
9075 wiphy->max_sched_scan_plan_iterations =
9076 config->max_sched_scan_plan_iterations;
9077 }
9078}
9079#else
9080static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
9081 struct hdd_config *config)
9082{
9083}
9084#endif
9085
9086
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009087/**
9088 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
9089 * @priv_size: Size of the hdd context.
9090 *
9091 * Allocate wiphy context and hdd context.
9092 *
9093 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009094 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009095hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009096{
9097 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009098 hdd_context_t *hdd_ctx;
9099
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009100 ENTER();
9101
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009102 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
9103
9104 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009105 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009106 return NULL;
9107 }
9108
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08009109 hdd_ctx = wiphy_priv(wiphy);
9110
9111 hdd_ctx->wiphy = wiphy;
9112
9113 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009114}
9115
9116/*
9117 * FUNCTION: wlan_hdd_cfg80211_update_band
9118 * This function is called from the supplicant through a
9119 * private ioctl to change the band value
9120 */
9121int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
9122{
9123 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07009124 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009125
9126 ENTER();
9127
Dustin Browna30892e2016-10-12 17:28:36 -07009128 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009129
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009130 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009131 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009132
9133 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
9134 struct ieee80211_supported_band *band = wiphy->bands[i];
9135
9136 channelEnabledState =
9137 cds_get_channel_state(band->channels[j].
9138 hw_value);
9139
Dustin Browna30892e2016-10-12 17:28:36 -07009140 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009141 /* 5G only */
9142#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
9143 /* Enable Social channels for P2P */
9144 if (WLAN_HDD_IS_SOCIAL_CHANNEL
9145 (band->channels[j].center_freq)
9146 && CHANNEL_STATE_ENABLE ==
9147 channelEnabledState)
9148 band->channels[j].flags &=
9149 ~IEEE80211_CHAN_DISABLED;
9150 else
9151#endif
9152 band->channels[j].flags |=
9153 IEEE80211_CHAN_DISABLED;
9154 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07009155 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009156 eCSR_BAND_24 == eBand) {
9157 /* 2G only */
9158 band->channels[j].flags |=
9159 IEEE80211_CHAN_DISABLED;
9160 continue;
9161 }
9162
Amar Singhal6842e8f2016-02-23 16:30:32 -08009163 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009164 band->channels[j].flags &=
9165 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009166 }
9167 }
9168 return 0;
9169}
9170
9171/*
9172 * FUNCTION: wlan_hdd_cfg80211_init
9173 * This function is called by hdd_wlan_startup()
9174 * during initialization.
9175 * This function is used to initialize and register wiphy structure.
9176 */
9177int wlan_hdd_cfg80211_init(struct device *dev,
9178 struct wiphy *wiphy, struct hdd_config *pCfg)
9179{
9180 int i, j;
9181 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9182
9183 ENTER();
9184
9185 /* Now bind the underlying wlan device with wiphy */
9186 set_wiphy_dev(wiphy, dev);
9187
9188 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
9189
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009190#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
9191 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07009192 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009193#else
9194 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07009195 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009196#endif
9197
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009198 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
9199 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
9200 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
9201#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
9202 | WIPHY_FLAG_4ADDR_STATION
9203#endif
9204 | WIPHY_FLAG_OFFCHAN_TX;
9205
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009206#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9207 wiphy->wowlan = &wowlan_support_cfg80211_init;
9208#else
9209 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
9210 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
9211 wiphy->wowlan.pattern_min_len = 1;
9212 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
9213#endif
9214
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07009215 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009216#ifdef FEATURE_WLAN_ESE
9217 || pCfg->isEseIniFeatureEnabled
9218#endif
9219 ) {
9220 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
9221 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009222#ifdef FEATURE_WLAN_TDLS
9223 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
9224 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
9225#endif
9226
9227 wiphy->features |= NL80211_FEATURE_HT_IBSS;
9228
Naveen Rawatc77e6e72016-08-05 15:19:03 -07009229#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
9230 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
9231#endif
9232
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05309233 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009234
9235#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05309236 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009237#endif
9238
9239 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009240 * driver can still register regulatory callback and
9241 * it will get regulatory settings in wiphy->band[], but
9242 * driver need to determine what to do with both
9243 * regulatory settings
9244 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009245
9246 wiphy->reg_notifier = hdd_reg_notifier;
9247
9248#if defined QCA_WIFI_FTM
9249}
9250#endif
9251
9252 wiphy->max_scan_ssids = MAX_SCAN_SSID;
9253
9254 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
9255
9256 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
9257
Arun Khandavallifae92942016-08-01 13:31:08 +05309258 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
9259 | BIT(NL80211_IFTYPE_ADHOC)
9260 | BIT(NL80211_IFTYPE_P2P_CLIENT)
9261 | BIT(NL80211_IFTYPE_P2P_GO)
9262 | BIT(NL80211_IFTYPE_AP)
9263 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009264
Arun Khandavallifae92942016-08-01 13:31:08 +05309265 if (pCfg->advertiseConcurrentOperation) {
9266 if (pCfg->enableMCC) {
9267 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07009268
Arun Khandavallifae92942016-08-01 13:31:08 +05309269 for (i = 0;
9270 i < ARRAY_SIZE(wlan_hdd_iface_combination);
9271 i++) {
9272 if (!pCfg->allowMCCGODiffBI)
9273 wlan_hdd_iface_combination[i].
9274 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009275 }
9276 }
9277 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05309278 ARRAY_SIZE(wlan_hdd_iface_combination);
9279 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009280 }
9281
9282 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009283 * on ini values
9284 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009285 if (!pCfg->ShortGI20MhzEnable) {
9286 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
9287 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009288 }
9289
9290 if (!pCfg->ShortGI40MhzEnable) {
9291 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
9292 }
9293
9294 if (!pCfg->nChannelBondingMode5GHz) {
9295 wlan_hdd_band_5_ghz.ht_cap.cap &=
9296 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
9297 }
9298
Abhishek Singhf512bf32016-05-04 16:47:46 +05309299 /*
9300 * In case of static linked driver at the time of driver unload,
9301 * module exit doesn't happens. Module cleanup helps in cleaning
9302 * of static memory.
9303 * If driver load happens statically, at the time of driver unload,
9304 * wiphy flags don't get reset because of static memory.
9305 * It's better not to store channel in static memory.
9306 */
Dustin Browna30892e2016-10-12 17:28:36 -07009307 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
9308 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05309309 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07009310 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309311 hdd_err("Not enough memory to allocate channels");
9312 return -ENOMEM;
9313 }
Dustin Browna30892e2016-10-12 17:28:36 -07009314 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05309315 &hdd_channels_2_4_ghz[0],
9316 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05309317 if ((hdd_is_5g_supported(pHddCtx)) &&
9318 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
9319 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
9320 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
9321 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -07009322 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
9323 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05309324 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07009325 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309326 hdd_err("Not enough memory to allocate channels");
9327 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -07009328 bands[NL80211_BAND_2GHZ]->channels);
9329 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +05309330 return -ENOMEM;
9331 }
Dustin Browna30892e2016-10-12 17:28:36 -07009332 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05309333 &hdd_channels_5_ghz[0],
9334 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009335 }
9336
Dustin Browna30892e2016-10-12 17:28:36 -07009337 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009338
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08009339 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009340 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009341
9342 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
9343 struct ieee80211_supported_band *band = wiphy->bands[i];
9344
Dustin Browna30892e2016-10-12 17:28:36 -07009345 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009346 eCSR_BAND_5G == pCfg->nBandCapability) {
9347 /* 5G only */
9348#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
9349 /* Enable social channels for P2P */
9350 if (WLAN_HDD_IS_SOCIAL_CHANNEL
9351 (band->channels[j].center_freq))
9352 band->channels[j].flags &=
9353 ~IEEE80211_CHAN_DISABLED;
9354 else
9355#endif
9356 band->channels[j].flags |=
9357 IEEE80211_CHAN_DISABLED;
9358 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07009359 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009360 eCSR_BAND_24 == pCfg->nBandCapability) {
9361 /* 2G only */
9362 band->channels[j].flags |=
9363 IEEE80211_CHAN_DISABLED;
9364 continue;
9365 }
9366 }
9367 }
9368 /*Initialise the supported cipher suite details */
9369 wiphy->cipher_suites = hdd_cipher_suites;
9370 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
9371
9372 /*signal strength in mBm (100*dBm) */
9373 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
9374 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
9375
Anurag Chouhan6d760662016-02-20 16:05:43 +05309376 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009377 wiphy->n_vendor_commands =
9378 ARRAY_SIZE(hdd_wiphy_vendor_commands);
9379 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
9380
9381 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
9382 wiphy->n_vendor_events =
9383 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
9384 }
9385
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009386 if (pCfg->enableDFSMasterCap) {
9387 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
9388 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009389
9390 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
9391
9392#ifdef QCA_HT_2040_COEX
9393 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
9394#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +05309395 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05309396 hdd_add_channel_switch_support(&wiphy->flags);
9397
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009398 EXIT();
9399 return 0;
9400}
9401
Abhishek Singhf512bf32016-05-04 16:47:46 +05309402/**
Yingying Tang80e15f32016-09-27 18:23:01 +08009403 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
9404 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +05309405 *
9406 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309407 * memory allocated in wlan_hdd_cfg80211_init also
9408 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05309409 *
9410 * Return: void
9411 */
9412void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
9413{
9414 int i;
9415
Dustin Browna30892e2016-10-12 17:28:36 -07009416 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309417 if (NULL != wiphy->bands[i] &&
9418 (NULL != wiphy->bands[i]->channels)) {
9419 qdf_mem_free(wiphy->bands[i]->channels);
9420 wiphy->bands[i]->channels = NULL;
9421 }
9422 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309423 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05309424}
9425
Yingying Tang80e15f32016-09-27 18:23:01 +08009426/**
9427 * wlan_hdd_update_band_cap() - update capabilities for supported bands
9428 * @hdd_ctx: HDD context
9429 *
9430 * this function will update capabilities for supported bands
9431 *
9432 * Return: void
9433 */
9434static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
9435{
9436 uint32_t val32;
9437 uint16_t val16;
9438 tSirMacHTCapabilityInfo *ht_cap_info;
9439 QDF_STATUS status;
9440
9441 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
9442 if (QDF_STATUS_SUCCESS != status) {
9443 hdd_err("could not get HT capability info");
9444 val32 = 0;
9445 }
9446 val16 = (uint16_t)val32;
9447 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
9448
9449 if (ht_cap_info->txSTBC == true) {
9450 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
9451 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
9452 IEEE80211_HT_CAP_TX_STBC;
9453 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
9454 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
9455 IEEE80211_HT_CAP_TX_STBC;
9456 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009457
9458 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
9459 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
9460 vht_cap.vht_supported = 0;
9461 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
9462 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
9463 vht_cap.vht_supported = 0;
9464 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
9465 }
Yingying Tang80e15f32016-09-27 18:23:01 +08009466}
9467
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009468/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309469 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009470 * initialization. In wlan_hdd_cfg80211_init, only the
9471 * default values will be initialized. The final initialization
9472 * of all required members can be done here.
9473 */
Yingying Tang80e15f32016-09-27 18:23:01 +08009474void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009475{
Yingying Tang80e15f32016-09-27 18:23:01 +08009476 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
9477
9478 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009479}
9480
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009481/**
9482 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
9483 * @cfg: hdd cfg
9484 *
9485 * this function update 11n mode in hdd cfg
9486 *
9487 * Return: void
9488 */
9489void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
9490{
9491 if (sme_is_feature_supported_by_fw(DOT11AC)) {
9492 hdd_notice("support 11ac");
9493 } else {
9494 hdd_notice("not support 11ac");
9495 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
9496 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
9497 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
9498 cfg->sap_p2p_11ac_override = 0;
9499 }
9500 }
9501}
9502
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009503/* In this function we are registering wiphy. */
9504int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
9505{
9506 ENTER();
9507 /* Register our wiphy dev with cfg80211 */
9508 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009509 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009510 return -EIO;
9511 }
9512
9513 EXIT();
9514 return 0;
9515}
9516
9517/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009518 * HDD function to update wiphy capability based on target offload status.
9519 *
9520 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
9521 * capability even before downloading firmware to the target. In discrete
9522 * case, host will get know certain offload capability (say sched_scan
9523 * caps) only after downloading firmware to the target and target boots up.
9524 * This function is used to override setting done in wlan_hdd_cfg80211_init()
9525 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009526 */
9527void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
9528{
9529#ifdef FEATURE_WLAN_SCAN_PNO
9530 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9531 struct hdd_config *pCfg = pHddCtx->config;
9532
9533 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
9534 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009535 * have PNO support.
9536 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009537 if (!pCfg->PnoOffload) {
9538 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9539 wiphy->max_sched_scan_ssids = 0;
9540 wiphy->max_match_sets = 0;
9541 wiphy->max_sched_scan_ie_len = 0;
9542 }
9543#endif
9544}
9545
9546/* This function registers for all frame which supplicant is interested in */
9547void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
9548{
9549 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9550 /* Register for all P2P action, public action etc frames */
9551 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9552
9553 ENTER();
9554
Abhishek Singh7996eb72015-12-30 17:24:02 +05309555 /* Register frame indication call back */
9556 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
9557
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05309558 /* Register for p2p ack indication */
9559 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
9560
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009561 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009562 * initialized. Once we will move to 2.6.37 kernel, in which we have
9563 * frame register ops, we will move this code as a part of that
9564 */
9565
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009566 /* GAS Initial Request */
9567 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9568 (uint8_t *) GAS_INITIAL_REQ,
9569 GAS_INITIAL_REQ_SIZE);
9570
9571 /* GAS Initial Response */
9572 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9573 (uint8_t *) GAS_INITIAL_RSP,
9574 GAS_INITIAL_RSP_SIZE);
9575
9576 /* GAS Comeback Request */
9577 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9578 (uint8_t *) GAS_COMEBACK_REQ,
9579 GAS_COMEBACK_REQ_SIZE);
9580
9581 /* GAS Comeback Response */
9582 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9583 (uint8_t *) GAS_COMEBACK_RSP,
9584 GAS_COMEBACK_RSP_SIZE);
9585
9586 /* P2P Public Action */
9587 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9588 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9589 P2P_PUBLIC_ACTION_FRAME_SIZE);
9590
9591 /* P2P Action */
9592 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9593 (uint8_t *) P2P_ACTION_FRAME,
9594 P2P_ACTION_FRAME_SIZE);
9595
9596 /* WNM BSS Transition Request frame */
9597 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9598 (uint8_t *) WNM_BSS_ACTION_FRAME,
9599 WNM_BSS_ACTION_FRAME_SIZE);
9600
9601 /* WNM-Notification */
9602 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9603 (uint8_t *) WNM_NOTIFICATION_FRAME,
9604 WNM_NOTIFICATION_FRAME_SIZE);
9605}
9606
9607void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9608{
9609 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9610 /* Register for all P2P action, public action etc frames */
9611 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9612
9613 ENTER();
9614
9615 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009616 * initialized. Once we will move to 2.6.37 kernel, in which we have
9617 * frame register ops, we will move this code as a part of that
9618 */
9619
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009620 /* GAS Initial Request */
9621
9622 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9623 (uint8_t *) GAS_INITIAL_REQ,
9624 GAS_INITIAL_REQ_SIZE);
9625
9626 /* GAS Initial Response */
9627 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9628 (uint8_t *) GAS_INITIAL_RSP,
9629 GAS_INITIAL_RSP_SIZE);
9630
9631 /* GAS Comeback Request */
9632 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9633 (uint8_t *) GAS_COMEBACK_REQ,
9634 GAS_COMEBACK_REQ_SIZE);
9635
9636 /* GAS Comeback Response */
9637 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9638 (uint8_t *) GAS_COMEBACK_RSP,
9639 GAS_COMEBACK_RSP_SIZE);
9640
9641 /* P2P Public Action */
9642 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9643 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9644 P2P_PUBLIC_ACTION_FRAME_SIZE);
9645
9646 /* P2P Action */
9647 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9648 (uint8_t *) P2P_ACTION_FRAME,
9649 P2P_ACTION_FRAME_SIZE);
9650
9651 /* WNM-Notification */
9652 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9653 (uint8_t *) WNM_NOTIFICATION_FRAME,
9654 WNM_NOTIFICATION_FRAME_SIZE);
9655}
9656
9657#ifdef FEATURE_WLAN_WAPI
9658void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9659 const uint8_t *mac_addr, const uint8_t *key,
9660 int key_Len)
9661{
9662 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9663 tCsrRoamSetKey setKey;
9664 bool isConnected = true;
9665 int status = 0;
9666 uint32_t roamId = 0xFF;
9667 uint8_t *pKeyPtr = NULL;
9668 int n = 0;
9669
Jeff Johnson46b40792016-06-29 14:03:14 -07009670 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009671 hdd_device_mode_to_string(pAdapter->device_mode),
9672 pAdapter->device_mode);
9673
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309674 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009675 setKey.keyId = key_index; /* Store Key ID */
9676 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9677 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9678 setKey.paeRole = 0; /* the PAE role */
9679 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309680 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009681 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309682 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009683 }
9684 setKey.keyLength = key_Len;
9685 pKeyPtr = setKey.Key;
9686 memcpy(pKeyPtr, key, key_Len);
9687
Jeff Johnson46b40792016-06-29 14:03:14 -07009688 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009689 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009690 hdd_notice("WAPI KEY Data[%d]:%02x ",
9691 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009692
9693 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9694 if (isConnected) {
9695 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9696 pAdapter->sessionId, &setKey, &roamId);
9697 }
9698 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009699 hdd_err("sme_roam_set_key returned ERROR status= %d",
9700 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009701 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9702 }
9703}
9704#endif /* FEATURE_WLAN_WAPI */
9705
9706uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9707 uint8_t eid)
9708{
9709 int left = length;
9710 uint8_t *ptr = (uint8_t *)ies_ptr;
9711 uint8_t elem_id, elem_len;
9712
9713 while (left >= 2) {
9714 elem_id = ptr[0];
9715 elem_len = ptr[1];
9716 left -= 2;
9717 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009718 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009719 eid, elem_len, left);
9720 return NULL;
9721 }
9722 if (elem_id == eid) {
9723 return ptr;
9724 }
9725
9726 left -= elem_len;
9727 ptr += (elem_len + 2);
9728 }
9729 return NULL;
9730}
9731
9732/*
9733 * FUNCTION: wlan_hdd_validate_operation_channel
9734 * called by wlan_hdd_cfg80211_start_bss() and
9735 * wlan_hdd_set_channel()
9736 * This function validates whether given channel is part of valid
9737 * channel list.
9738 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309739QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009740 int channel)
9741{
9742
9743 uint32_t num_ch = 0;
9744 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9745 u32 indx = 0;
9746 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9747 uint8_t fValidChannel = false, count = 0;
9748 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9749
9750 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9751
9752 if (hdd_pConfig_ini->sapAllowAllChannel) {
9753 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009754 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009755 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009756 fValidChannel = true;
9757 break;
9758 }
9759 }
9760 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009761 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309762 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009763 }
9764 } else {
9765 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9766 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009767 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309768 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009769 }
9770 for (indx = 0; indx < num_ch; indx++) {
9771 if (channel == valid_ch[indx]) {
9772 break;
9773 }
9774 }
9775
9776 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009777 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309778 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009779 }
9780 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309781 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009782
9783}
9784
9785#ifdef DHCP_SERVER_OFFLOAD
9786static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9787{
9788 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9789 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9790 uint8_t numEntries = 0;
9791 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9792 uint8_t num;
9793 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309794 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009795 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009796 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009797 return;
9798 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009799 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9800 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9801 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9802 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9803 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9804 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009805 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009806 goto end;
9807 }
9808 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009809 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009810 goto end;
9811 }
9812 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009813 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009814 goto end;
9815 }
9816 for (num = 0; num < numEntries; num++) {
9817 temp = srv_ip[num];
9818 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9819 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309820 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009821 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009822 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009823 goto end;
9824 }
Jeff Johnson77848112016-06-29 14:52:06 -07009825 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009826end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309827 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009828 return;
9829}
9830#endif /* DHCP_SERVER_OFFLOAD */
9831
9832static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9833 struct net_device *dev,
9834 struct bss_parameters *params)
9835{
9836 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9837 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9838 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309839 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009840
9841 ENTER();
9842
Anurag Chouhan6d760662016-02-20 16:05:43 +05309843 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009844 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009845 return -EINVAL;
9846 }
9847
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309848 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9849 hdd_err("invalid session id: %d", pAdapter->sessionId);
9850 return -EINVAL;
9851 }
9852
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309853 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009854 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9855 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009856 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009857 hdd_device_mode_to_string(pAdapter->device_mode),
9858 pAdapter->device_mode, params->ap_isolate);
9859
9860 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9861 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309862 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009863 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009864
Krunal Sonib4326f22016-03-10 13:05:51 -08009865 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9866 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009867 return -EOPNOTSUPP;
9868 }
9869
9870 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -08009871 * want to update this parameter
9872 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009873 if (-1 != params->ap_isolate) {
9874 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9875 !!params->ap_isolate;
9876
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309877 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009878 pAdapter->sessionId,
9879 pAdapter->sessionCtx.
9880 ap.
9881 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309882 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009883 ret = -EINVAL;
9884 }
9885 }
9886
9887 EXIT();
9888 return ret;
9889}
9890
Krunal Soni8c37e322016-02-03 16:08:37 -08009891/**
9892 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9893 * @ndev: pointer to net device provided by supplicant
9894 * @type: type of the interface, upper layer wanted to change
9895 *
9896 * Upper layer provides the new interface mode that needs to be changed
9897 * for given net device
9898 *
9899 * Return: success or failure in terms of integer value
9900 */
9901static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009902 enum nl80211_iftype type)
9903{
Krunal Soni8c37e322016-02-03 16:08:37 -08009904 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9905 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9906 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009907 hdd_wext_state_t *wext;
9908 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309909 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009910
9911 ENTER();
9912
Krunal Soni8c37e322016-02-03 16:08:37 -08009913 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009914 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009915 return 0;
9916 }
9917
9918 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009919 hdd_stop_adapter(hdd_ctx, adapter, true);
9920 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009921 wdev->iftype = type;
9922 /*Check for sub-string p2p to confirm its a p2p interface */
9923 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009924 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009925 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009926 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009927 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009928 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009929 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009930 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009931 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009932 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009933 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009934 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9935 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009936 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9937 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009938 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009939 adapter->scan_info.scanAddIE.length;
9940 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309941 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009942 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9943 wext->roamProfile.phyMode =
9944 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9945 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009946 EXIT();
9947 return status;
9948}
9949
9950static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9951 struct net_device *dev,
9952 struct bss_parameters *params)
9953{
9954 int ret;
9955
9956 cds_ssr_protect(__func__);
9957 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9958 cds_ssr_unprotect(__func__);
9959
9960 return ret;
9961}
9962
9963/* FUNCTION: wlan_hdd_change_country_code_cd
9964 * to wait for contry code completion
9965 */
9966void *wlan_hdd_change_country_code_cb(void *pAdapter)
9967{
9968 hdd_adapter_t *call_back_pAdapter = pAdapter;
9969 complete(&call_back_pAdapter->change_country_code);
9970 return NULL;
9971}
9972
Rajeev Kumar98edb772016-01-19 12:42:19 -08009973/**
9974 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9975 * @wiphy: Pointer to the wiphy structure
9976 * @ndev: Pointer to the net device
9977 * @type: Interface type
9978 * @flags: Flags for change interface
9979 * @params: Pointer to change interface parameters
9980 *
9981 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009982 */
9983static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9984 struct net_device *ndev,
9985 enum nl80211_iftype type,
9986 u32 *flags,
9987 struct vif_params *params)
9988{
9989 struct wireless_dev *wdev;
9990 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9991 hdd_context_t *pHddCtx;
9992 tCsrRoamProfile *pRoamProfile = NULL;
9993 eCsrRoamBssType LastBSSType;
9994 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309995 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009996 int status;
9997
9998 ENTER();
9999
Anurag Chouhan6d760662016-02-20 16:05:43 +053010000 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010001 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010002 return -EINVAL;
10003 }
10004
10005 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10006 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010007 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010008 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010009
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010010 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010011 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
10012 pAdapter->sessionId, type));
10013
Jeff Johnson77848112016-06-29 14:52:06 -070010014 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010015 pAdapter->device_mode, type);
10016
Arun Khandavallifae92942016-08-01 13:31:08 +053010017 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
10018 if (status) {
10019 hdd_err("Failed to start modules");
10020 return -EINVAL;
10021 }
10022
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010023 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010024 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
10025 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010026 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010027 return -EINVAL;
10028 }
10029
10030 pConfig = pHddCtx->config;
10031 wdev = ndev->ieee80211_ptr;
10032
10033 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010034 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010035
10036 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
10037
Krunal Sonib4326f22016-03-10 13:05:51 -080010038 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10039 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
10040 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
10041 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010042 hdd_wext_state_t *pWextState =
10043 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10044
10045 pRoamProfile = &pWextState->roamProfile;
10046 LastBSSType = pRoamProfile->BSSType;
10047
10048 switch (type) {
10049 case NL80211_IFTYPE_STATION:
10050 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080010051 case NL80211_IFTYPE_ADHOC:
10052 if (type == NL80211_IFTYPE_ADHOC) {
10053 wlan_hdd_tdls_exit(pAdapter);
10054 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -070010055 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080010056 }
10057 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
10058 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010059 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010060 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010061 if (hdd_start_adapter(pAdapter)) {
10062 hdd_err("Failed to start adapter :%d",
10063 pAdapter->device_mode);
10064 return -EINVAL;
10065 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010066 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010067 case NL80211_IFTYPE_AP:
10068 case NL80211_IFTYPE_P2P_GO:
10069 {
Jeff Johnson77848112016-06-29 14:52:06 -070010070 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010071 (type ==
10072 NL80211_IFTYPE_AP) ? "SoftAP" :
10073 "P2pGo");
10074
10075 /* Cancel any remain on channel for GO mode */
10076 if (NL80211_IFTYPE_P2P_GO == type) {
10077 wlan_hdd_cancel_existing_remain_on_channel
10078 (pAdapter);
10079 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010080
Arun Khandavallifae92942016-08-01 13:31:08 +053010081 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010082 /* De-init the adapter */
10083 hdd_deinit_adapter(pHddCtx, pAdapter, true);
10084 memset(&pAdapter->sessionCtx, 0,
10085 sizeof(pAdapter->sessionCtx));
10086 pAdapter->device_mode =
10087 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080010088 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
10089 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010090
10091 /*
10092 * Fw will take care incase of concurrency
10093 */
10094
Krunal Sonib4326f22016-03-10 13:05:51 -080010095 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010096 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010097 /* To meet Android requirements create
10098 * a randomized MAC address of the
10099 * form 02:1A:11:Fx:xx:xx
10100 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010101 get_random_bytes(&ndev->dev_addr[3], 3);
10102 ndev->dev_addr[0] = 0x02;
10103 ndev->dev_addr[1] = 0x1A;
10104 ndev->dev_addr[2] = 0x11;
10105 ndev->dev_addr[3] |= 0xF0;
10106 memcpy(pAdapter->macAddressCurrent.
10107 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053010108 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010109 pr_info("wlan: Generated HotSpot BSSID "
10110 MAC_ADDRESS_STR "\n",
10111 MAC_ADDR_ARRAY(ndev->dev_addr));
10112 }
10113
10114 hdd_set_ap_ops(pAdapter->dev);
10115
Arun Khandavallifae92942016-08-01 13:31:08 +053010116 if (hdd_start_adapter(pAdapter)) {
10117 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010118 return -EINVAL;
10119 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010120 /* Interface type changed update in wiphy structure */
10121 if (wdev) {
10122 wdev->iftype = type;
10123 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070010124 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010125 return -EINVAL;
10126 }
10127 goto done;
10128 }
10129
10130 default:
Jeff Johnson77848112016-06-29 14:52:06 -070010131 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010132 type);
10133 return -EOPNOTSUPP;
10134 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010135 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10136 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010137 switch (type) {
10138 case NL80211_IFTYPE_STATION:
10139 case NL80211_IFTYPE_P2P_CLIENT:
10140 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080010141 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
10142 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010143 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010144 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010145 if (hdd_start_adapter(pAdapter)) {
10146 hdd_err("Failed to start adapter :%d",
10147 pAdapter->device_mode);
10148 return -EINVAL;
10149 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010150 goto done;
10151
10152 case NL80211_IFTYPE_AP:
10153 case NL80211_IFTYPE_P2P_GO:
10154 wdev->iftype = type;
10155 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080010156 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010157 goto done;
10158
10159 default:
Jeff Johnson77848112016-06-29 14:52:06 -070010160 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010161 type);
10162 return -EOPNOTSUPP;
10163 }
10164 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070010165 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010166 pAdapter->device_mode);
10167 return -EOPNOTSUPP;
10168 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010169done:
10170 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010171 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010172
Jeff Johnson2ae6f712016-09-23 15:08:48 -070010173 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010174
10175 EXIT();
10176 return 0;
10177}
10178
Rajeev Kumar98edb772016-01-19 12:42:19 -080010179/**
10180 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
10181 * @wiphy: Pointer to the wiphy structure
10182 * @ndev: Pointer to the net device
10183 * @type: Interface type
10184 * @flags: Flags for change interface
10185 * @params: Pointer to change interface parameters
10186 *
10187 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010188 */
10189static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
10190 struct net_device *ndev,
10191 enum nl80211_iftype type,
10192 u32 *flags,
10193 struct vif_params *params)
10194{
10195 int ret;
10196
10197 cds_ssr_protect(__func__);
10198 ret =
10199 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
10200 cds_ssr_unprotect(__func__);
10201
10202 return ret;
10203}
10204
10205#ifdef FEATURE_WLAN_TDLS
10206static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
10207 int index, uint8_t match)
10208{
10209 int i;
10210 for (i = 0; i < index; i++) {
10211 if (arr[i] == match)
10212 return true;
10213 }
10214 return false;
10215}
10216#endif
10217
10218/**
10219 * __wlan_hdd_change_station() - change station
10220 * @wiphy: Pointer to the wiphy structure
10221 * @dev: Pointer to the net device.
10222 * @mac: bssid
10223 * @params: Pointer to station parameters
10224 *
10225 * Return: 0 for success, error number on failure.
10226 */
10227#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10228static int __wlan_hdd_change_station(struct wiphy *wiphy,
10229 struct net_device *dev,
10230 const uint8_t *mac,
10231 struct station_parameters *params)
10232#else
10233static int __wlan_hdd_change_station(struct wiphy *wiphy,
10234 struct net_device *dev,
10235 uint8_t *mac,
10236 struct station_parameters *params)
10237#endif
10238{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010239 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010240 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10241 hdd_context_t *pHddCtx;
10242 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053010243 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010244#ifdef FEATURE_WLAN_TDLS
10245 tCsrStaParams StaParams = { 0 };
10246 uint8_t isBufSta = 0;
10247 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053010248 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010249#endif
10250 int ret;
10251
10252 ENTER();
10253
Anurag Chouhan6d760662016-02-20 16:05:43 +053010254 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010255 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010256 return -EINVAL;
10257 }
10258
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010259 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010260 TRACE_CODE_HDD_CHANGE_STATION,
10261 pAdapter->sessionId, params->listen_interval));
10262
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010263 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10264 hdd_err("invalid session id: %d", pAdapter->sessionId);
10265 return -EINVAL;
10266 }
10267
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010268 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10269 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010270 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010271 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010272
10273 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10274
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010275 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010276
Krunal Sonib4326f22016-03-10 13:05:51 -080010277 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10278 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010279 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
10280 status =
10281 hdd_softap_change_sta_state(pAdapter,
10282 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080010283 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010284
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010285 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010286 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010287 return -EINVAL;
10288 }
10289 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010290 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10291 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010292#ifdef FEATURE_WLAN_TDLS
10293 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070010294
10295 if (cds_is_sub_20_mhz_enabled()) {
10296 hdd_err("TDLS not allowed with sub 20 MHz");
10297 return -EINVAL;
10298 }
10299
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010300 StaParams.capability = params->capability;
10301 StaParams.uapsd_queues = params->uapsd_queues;
10302 StaParams.max_sp = params->max_sp;
10303
10304 /* Convert (first channel , number of channels) tuple to
10305 * the total list of channels. This goes with the assumption
10306 * that if the first channel is < 14, then the next channels
10307 * are an incremental of 1 else an incremental of 4 till the number
10308 * of channels.
10309 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010310 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010311 if (0 != params->supported_channels_len) {
10312 int i = 0, j = 0, k = 0, no_of_channels = 0;
10313 int num_unique_channels;
10314 int next;
10315 for (i = 0;
10316 i < params->supported_channels_len
10317 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
10318 int wifi_chan_index;
10319 if (!wlan_hdd_is_duplicate_channel
10320 (StaParams.supported_channels, j,
10321 params->supported_channels[i])) {
10322 StaParams.
10323 supported_channels[j] =
10324 params->
10325 supported_channels[i];
10326 } else {
10327 continue;
10328 }
10329 wifi_chan_index =
10330 ((StaParams.supported_channels[j] <=
10331 HDD_CHANNEL_14) ? 1 : 4);
10332 no_of_channels =
10333 params->supported_channels[i + 1];
10334
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010335 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 -080010336 StaParams.
10337 supported_channels[j],
10338 wifi_chan_index,
10339 no_of_channels);
10340 for (k = 1; k <= no_of_channels &&
10341 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
10342 k++) {
10343 next =
10344 StaParams.
10345 supported_channels[j] +
10346 wifi_chan_index;
10347 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
10348 StaParams.
10349 supported_channels[j
10350 +
10351 1]
10352 = next;
10353 } else {
10354 continue;
10355 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010356 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010357 j + 1,
10358 StaParams.
10359 supported_channels[j +
10360 1]);
10361 j += 1;
10362 }
10363 }
10364 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010365 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010366 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010367 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010368 StaParams.
10369 supported_channels[i]);
10370 }
10371 if (MAX_CHANNEL < num_unique_channels)
10372 num_unique_channels = MAX_CHANNEL;
10373 StaParams.supported_channels_len =
10374 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010375 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010376 StaParams.supported_channels_len);
10377 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010378 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010379 params->supported_oper_classes,
10380 params->supported_oper_classes_len);
10381 StaParams.supported_oper_classes_len =
10382 params->supported_oper_classes_len;
10383
10384 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010385 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010386 params->ext_capab,
10387 sizeof(StaParams.extn_capability));
10388
10389 if (NULL != params->ht_capa) {
10390 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010391 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010392 sizeof(tSirHTCap));
10393 }
10394
10395 StaParams.supported_rates_len =
10396 params->supported_rates_len;
10397
10398 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
10399 * The supported_rates array , for all the structures propogating till Add Sta
10400 * to the firmware has to be modified , if the supplicant (ieee80211) is
10401 * modified to send more rates.
10402 */
10403
10404 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
10405 */
10406 if (StaParams.supported_rates_len >
10407 SIR_MAC_MAX_SUPP_RATES)
10408 StaParams.supported_rates_len =
10409 SIR_MAC_MAX_SUPP_RATES;
10410
10411 if (0 != StaParams.supported_rates_len) {
10412 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010413 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010414 params->supported_rates,
10415 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010416 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010417 StaParams.supported_rates_len);
10418 for (i = 0; i < StaParams.supported_rates_len;
10419 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010420 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010421 StaParams.supported_rates[i]);
10422 }
10423
10424 if (NULL != params->vht_capa) {
10425 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010426 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010427 params->vht_capa,
10428 sizeof(tSirVHTCap));
10429 }
10430
10431 if (0 != params->ext_capab_len) {
10432 /*Define A Macro : TODO Sunil */
10433 if ((1 << 4) & StaParams.extn_capability[3]) {
10434 isBufSta = 1;
10435 }
10436 /* TDLS Channel Switching Support */
10437 if ((1 << 6) & StaParams.extn_capability[3]) {
10438 isOffChannelSupported = 1;
10439 }
10440 }
10441
Nitesh Shah99934ac2016-09-05 15:54:08 +053010442 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053010443 (params->ht_capa || params->vht_capa ||
10444 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053010445 is_qos_wmm_sta = true;
10446
10447 hdd_notice("%s: TDLS Peer is QOS capable"
10448 " is_qos_wmm_sta= %d HTcapPresent = %d",
10449 __func__, is_qos_wmm_sta,
10450 StaParams.htcap_present);
10451
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010452 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053010453 &StaParams,
10454 isBufSta,
10455 isOffChannelSupported,
10456 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010457 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010458 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010459 return -EINVAL;
10460 }
10461
10462 status =
10463 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
10464 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010465 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010466 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010467 return -EINVAL;
10468 }
10469 }
10470#endif
10471 }
10472 EXIT();
10473 return ret;
10474}
10475
10476/**
10477 * wlan_hdd_change_station() - cfg80211 change station handler function
10478 * @wiphy: Pointer to the wiphy structure
10479 * @dev: Pointer to the net device.
10480 * @mac: bssid
10481 * @params: Pointer to station parameters
10482 *
10483 * This is the cfg80211 change station handler function which invokes
10484 * the internal function @__wlan_hdd_change_station with
10485 * SSR protection.
10486 *
10487 * Return: 0 for success, error number on failure.
10488 */
10489#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
10490static int wlan_hdd_change_station(struct wiphy *wiphy,
10491 struct net_device *dev,
10492 const u8 *mac,
10493 struct station_parameters *params)
10494#else
10495static int wlan_hdd_change_station(struct wiphy *wiphy,
10496 struct net_device *dev,
10497 u8 *mac,
10498 struct station_parameters *params)
10499#endif
10500{
10501 int ret;
10502
10503 cds_ssr_protect(__func__);
10504 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
10505 cds_ssr_unprotect(__func__);
10506
10507 return ret;
10508}
10509
10510/*
10511 * FUNCTION: __wlan_hdd_cfg80211_add_key
10512 * This function is used to initialize the key information
10513 */
10514static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10515 struct net_device *ndev,
10516 u8 key_index, bool pairwise,
10517 const u8 *mac_addr,
10518 struct key_params *params)
10519{
10520 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10521 tCsrRoamSetKey setKey;
10522 int status;
10523 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010524 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010525 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010526 hdd_context_t *pHddCtx;
10527 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10528
10529 ENTER();
10530
Anurag Chouhan6d760662016-02-20 16:05:43 +053010531 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010532 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010533 return -EINVAL;
10534 }
10535
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010536 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10537 hdd_err("invalid session id: %d", pAdapter->sessionId);
10538 return -EINVAL;
10539 }
10540
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010541 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010542 TRACE_CODE_HDD_CFG80211_ADD_KEY,
10543 pAdapter->sessionId, params->key_len));
10544 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10545 status = wlan_hdd_validate_context(pHddCtx);
10546
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010547 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010548 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010549
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010550 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010551 hdd_device_mode_to_string(pAdapter->device_mode),
10552 pAdapter->device_mode);
10553
10554 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010555 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010556
10557 return -EINVAL;
10558 }
10559
10560 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010561 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010562
10563 return -EINVAL;
10564 }
10565
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010566 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010567
10568 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010569 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010570 setKey.keyId = key_index;
10571 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010572 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010573
10574 switch (params->cipher) {
10575 case WLAN_CIPHER_SUITE_WEP40:
10576 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10577 break;
10578
10579 case WLAN_CIPHER_SUITE_WEP104:
10580 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
10581 break;
10582
10583 case WLAN_CIPHER_SUITE_TKIP:
10584 {
10585 u8 *pKey = &setKey.Key[0];
10586 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
10587
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010588 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010589
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010590 /* Supplicant sends the 32bytes key in this order
10591 *
10592 * |--------------|----------|----------|
10593 * | Tk1 |TX-MIC | RX Mic |
10594 * |--------------|----------|----------|
10595 * <---16bytes---><--8bytes--><--8bytes-->
10596 *
10597 * Sme expects the 32 bytes key to be in the below order
10598 *
10599 * |--------------|----------|----------|
10600 * | Tk1 |RX-MIC | TX Mic |
10601 * |--------------|----------|----------|
10602 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010603 */
10604 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010605 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010606
10607 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010608 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010609
10610 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010611 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010612
10613 break;
10614 }
10615
10616 case WLAN_CIPHER_SUITE_CCMP:
10617 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10618 break;
10619
10620#ifdef FEATURE_WLAN_WAPI
10621 case WLAN_CIPHER_SUITE_SMS4:
10622 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010623 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010624 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10625 mac_addr, params->key,
10626 params->key_len);
10627 return 0;
10628 }
10629#endif
10630
10631#ifdef FEATURE_WLAN_ESE
10632 case WLAN_CIPHER_SUITE_KRK:
10633 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10634 break;
10635#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10636 case WLAN_CIPHER_SUITE_BTK:
10637 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10638 break;
10639#endif
10640#endif
10641
10642#ifdef WLAN_FEATURE_11W
10643 case WLAN_CIPHER_SUITE_AES_CMAC:
10644 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10645 break;
10646#endif
10647
10648 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010649 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010650 return -EOPNOTSUPP;
10651 }
10652
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010653 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010654
10655 if (!pairwise) {
10656 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010657 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010658 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010659 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010660 } else {
10661 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010662 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010663 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010664 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010665 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010666 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010667 /* if a key is already installed, block all subsequent ones */
10668 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010669 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010670 return 0;
10671 }
10672
10673 setKey.keyDirection = eSIR_TX_RX;
10674 /*Set the group key */
10675 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10676 pAdapter->sessionId, &setKey, &roamId);
10677
10678 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010679 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010680 return -EINVAL;
10681 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010682 /* Save the keys here and call sme_roam_set_key for setting
10683 * the PTK after peer joins the IBSS network
10684 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010685 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010686 &setKey, sizeof(tCsrRoamSetKey));
10687
10688 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10689 return status;
10690 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010691 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10692 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010693 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10694 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010695 status = wlansap_set_key_sta(
10696 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010697 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010698 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010699 __LINE__, status);
10700 }
10701 }
10702
10703 /* Save the key in ap ctx for use on START_BASS and restart */
10704 if (pairwise ||
10705 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10706 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010707 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010708 sizeof(tCsrRoamSetKey));
10709 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010710 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010711 sizeof(tCsrRoamSetKey));
10712
Krunal Sonib4326f22016-03-10 13:05:51 -080010713 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10714 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010715 hdd_wext_state_t *pWextState =
10716 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10717 hdd_station_ctx_t *pHddStaCtx =
10718 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10719
10720 if (!pairwise) {
10721 /* set group key */
10722 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010723 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010724 __func__, __LINE__);
10725 hdd_perform_roam_set_key_complete(pAdapter);
10726 }
10727 }
10728
10729 pWextState->roamProfile.Keys.KeyLength[key_index] =
10730 (u8) params->key_len;
10731
10732 pWextState->roamProfile.Keys.defaultIndex = key_index;
10733
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010734 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010735 KeyMaterial[key_index][0], params->key,
10736 params->key_len);
10737
10738 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10739
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010740 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010741 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10742 setKey.keyDirection);
10743
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010744 /* The supplicant may attempt to set the PTK once
10745 * pre-authentication is done. Save the key in the
10746 * UMAC and include it in the ADD BSS request
10747 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010748 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010749 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010750 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010751 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010752 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010753 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010754 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010755 return -EINVAL;
10756 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010757
10758 /* issue set key request to SME */
10759 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10760 pAdapter->sessionId, &setKey, &roamId);
10761
10762 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010763 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010764 pHddStaCtx->roam_info.roamingState =
10765 HDD_ROAM_STATE_NONE;
10766 return -EINVAL;
10767 }
10768
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010769 /* in case of IBSS as there was no information
10770 * available about WEP keys during IBSS join, group
10771 * key intialized with NULL key, so re-initialize
10772 * group key with correct value
10773 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010774 if ((eCSR_BSS_TYPE_START_IBSS ==
10775 pWextState->roamProfile.BSSType)
10776 &&
10777 !((IW_AUTH_KEY_MGMT_802_1X ==
10778 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10779 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10780 pHddStaCtx->conn_info.authType)
10781 )
10782 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10783 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10784 )
10785 ) {
10786 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010787 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010788
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010789 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010790 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10791 setKey.keyDirection);
10792
10793 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10794 pAdapter->sessionId, &setKey,
10795 &roamId);
10796
10797 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010798 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010799 pHddStaCtx->roam_info.roamingState =
10800 HDD_ROAM_STATE_NONE;
10801 return -EINVAL;
10802 }
10803 }
10804 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010805 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010806 return 0;
10807}
10808
10809static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10810 struct net_device *ndev,
10811 u8 key_index, bool pairwise,
10812 const u8 *mac_addr,
10813 struct key_params *params)
10814{
10815 int ret;
10816 cds_ssr_protect(__func__);
10817 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10818 mac_addr, params);
10819 cds_ssr_unprotect(__func__);
10820
10821 return ret;
10822}
10823
10824/*
10825 * FUNCTION: __wlan_hdd_cfg80211_get_key
10826 * This function is used to get the key information
10827 */
10828static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10829 struct net_device *ndev,
10830 u8 key_index, bool pairwise,
10831 const u8 *mac_addr, void *cookie,
10832 void (*callback)(void *cookie,
10833 struct key_params *)
10834 )
10835{
10836 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10837 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10838 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10839 struct key_params params;
10840
10841 ENTER();
10842
Anurag Chouhan6d760662016-02-20 16:05:43 +053010843 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010844 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010845 return -EINVAL;
10846 }
10847
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010848 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010849 hdd_device_mode_to_string(pAdapter->device_mode),
10850 pAdapter->device_mode);
10851
10852 memset(&params, 0, sizeof(params));
10853
10854 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010855 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856 key_index);
10857 return -EINVAL;
10858 }
10859
10860 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10861 case eCSR_ENCRYPT_TYPE_NONE:
10862 params.cipher = IW_AUTH_CIPHER_NONE;
10863 break;
10864
10865 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10866 case eCSR_ENCRYPT_TYPE_WEP40:
10867 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10868 break;
10869
10870 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10871 case eCSR_ENCRYPT_TYPE_WEP104:
10872 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10873 break;
10874
10875 case eCSR_ENCRYPT_TYPE_TKIP:
10876 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10877 break;
10878
10879 case eCSR_ENCRYPT_TYPE_AES:
10880 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10881 break;
10882
10883 default:
10884 params.cipher = IW_AUTH_CIPHER_NONE;
10885 break;
10886 }
10887
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010888 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010889 TRACE_CODE_HDD_CFG80211_GET_KEY,
10890 pAdapter->sessionId, params.cipher));
10891
10892 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10893 params.seq_len = 0;
10894 params.seq = NULL;
10895 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10896 callback(cookie, &params);
10897
10898 EXIT();
10899 return 0;
10900}
10901
10902static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10903 struct net_device *ndev,
10904 u8 key_index, bool pairwise,
10905 const u8 *mac_addr, void *cookie,
10906 void (*callback)(void *cookie,
10907 struct key_params *)
10908 )
10909{
10910 int ret;
10911
10912 cds_ssr_protect(__func__);
10913 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10914 mac_addr, cookie, callback);
10915 cds_ssr_unprotect(__func__);
10916
10917 return ret;
10918}
10919
10920/**
10921 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10922 * @wiphy: wiphy interface context
10923 * @ndev: pointer to net device
10924 * @key_index: Key index used in 802.11 frames
10925 * @unicast: true if it is unicast key
10926 * @multicast: true if it is multicast key
10927 *
10928 * This function is required for cfg80211_ops API.
10929 * It is used to delete the key information
10930 * Underlying hardware implementation does not have API to delete the
10931 * encryption key. It is automatically deleted when the peer is
10932 * removed. Hence this function currently does nothing.
10933 * Future implementation may interprete delete key operation to
10934 * replacing the key with a random junk value, effectively making it
10935 * useless.
10936 *
10937 * Return: status code, always 0.
10938 */
10939
10940static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10941 struct net_device *ndev,
10942 u8 key_index,
10943 bool pairwise, const u8 *mac_addr)
10944{
10945 EXIT();
10946 return 0;
10947}
10948
10949/**
10950 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10951 * @wiphy: Pointer to wiphy structure.
10952 * @dev: Pointer to net_device structure.
10953 * @key_index: key index
10954 * @pairwise: pairwise
10955 * @mac_addr: mac address
10956 *
10957 * This is the cfg80211 delete key handler function which invokes
10958 * the internal function @__wlan_hdd_cfg80211_del_key with
10959 * SSR protection.
10960 *
10961 * Return: 0 for success, error number on failure.
10962 */
10963static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10964 struct net_device *dev,
10965 u8 key_index,
10966 bool pairwise, const u8 *mac_addr)
10967{
10968 int ret;
10969
10970 cds_ssr_protect(__func__);
10971 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10972 pairwise, mac_addr);
10973 cds_ssr_unprotect(__func__);
10974
10975 return ret;
10976}
10977
10978/*
10979 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10980 * This function is used to set the default tx key index
10981 */
10982static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10983 struct net_device *ndev,
10984 u8 key_index,
10985 bool unicast, bool multicast)
10986{
10987 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10988 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10989 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10990 hdd_context_t *pHddCtx;
10991 int status;
10992
10993 ENTER();
10994
Anurag Chouhan6d760662016-02-20 16:05:43 +053010995 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010996 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010997 return -EINVAL;
10998 }
10999
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011000 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11001 hdd_err("invalid session id: %d", pAdapter->sessionId);
11002 return -EINVAL;
11003 }
11004
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011005 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011006 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
11007 pAdapter->sessionId, key_index));
11008
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011009 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011010 hdd_device_mode_to_string(pAdapter->device_mode),
11011 pAdapter->device_mode, key_index);
11012
11013 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011014 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011015 return -EINVAL;
11016 }
11017
11018 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11019 status = wlan_hdd_validate_context(pHddCtx);
11020
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011021 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011022 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011023
Krunal Sonib4326f22016-03-10 13:05:51 -080011024 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11025 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011026 if ((eCSR_ENCRYPT_TYPE_TKIP !=
11027 pHddStaCtx->conn_info.ucEncryptionType) &&
11028 (eCSR_ENCRYPT_TYPE_AES !=
11029 pHddStaCtx->conn_info.ucEncryptionType)) {
11030 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011031 * then update the default key index
11032 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011033
11034 tCsrRoamSetKey setKey;
11035 uint32_t roamId = 0xFF;
11036 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
11037
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011038 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011039
11040 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011041 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011042 setKey.keyId = key_index;
11043 setKey.keyLength = Keys->KeyLength[key_index];
11044
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011045 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011046 &Keys->KeyMaterial[key_index][0],
11047 Keys->KeyLength[key_index]);
11048
11049 setKey.keyDirection = eSIR_TX_RX;
11050
Anurag Chouhanc5548422016-02-24 18:33:27 +053011051 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011052 &pHddStaCtx->conn_info.bssId);
11053
11054 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
11055 pWextState->roamProfile.EncryptionType.
11056 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011057 /* In the case of dynamic wep
11058 * supplicant hardcodes DWEP type to
11059 * eCSR_ENCRYPT_TYPE_WEP104 even
11060 * though ap is configured for WEP-40
11061 * encryption. In this canse the key
11062 * length is 5 but the encryption type
11063 * is 104 hence checking the key
11064 * lenght(5) and encryption type(104)
11065 * and switching encryption type to 40
11066 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011067 pWextState->roamProfile.EncryptionType.
11068 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
11069 pWextState->roamProfile.mcEncryptionType.
11070 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
11071 }
11072
11073 setKey.encType =
11074 pWextState->roamProfile.EncryptionType.
11075 encryptionType[0];
11076
11077 /* Issue set key request */
11078 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11079 pAdapter->sessionId, &setKey,
11080 &roamId);
11081
11082 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011083 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011084 status);
11085 return -EINVAL;
11086 }
11087 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011088 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011089 /* In SoftAp mode setting key direction for default mode */
11090 if ((eCSR_ENCRYPT_TYPE_TKIP !=
11091 pWextState->roamProfile.EncryptionType.encryptionType[0])
11092 && (eCSR_ENCRYPT_TYPE_AES !=
11093 pWextState->roamProfile.EncryptionType.
11094 encryptionType[0])) {
11095 /* Saving key direction for default key index to TX default */
11096 hdd_ap_ctx_t *pAPCtx =
11097 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11098 pAPCtx->wepKey[key_index].keyDirection =
11099 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053011100 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053011101 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053011102 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011103 }
11104 }
11105
11106 EXIT();
11107 return status;
11108}
11109
11110static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
11111 struct net_device *ndev,
11112 u8 key_index,
11113 bool unicast, bool multicast)
11114{
11115 int ret;
11116 cds_ssr_protect(__func__);
11117 ret =
11118 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
11119 multicast);
11120 cds_ssr_unprotect(__func__);
11121
11122 return ret;
11123}
11124
Abhishek Singhc9941602016-08-09 16:06:22 +053011125/*
11126 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
11127 * @wiphy: wiphy pointer
11128 * @channel: channel of the BSS
11129 * @bssid: Bssid of BSS
11130 * @ssid: Ssid of the BSS
11131 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011132 *
Abhishek Singhc9941602016-08-09 16:06:22 +053011133 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011134 */
Abhishek Singhc9941602016-08-09 16:06:22 +053011135#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011136static
Abhishek Singhc9941602016-08-09 16:06:22 +053011137struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
11138 struct ieee80211_channel *channel, const u8 *bssid,
11139 const u8 *ssid, size_t ssid_len)
11140{
11141 return cfg80211_get_bss(wiphy, channel, bssid,
11142 ssid,
11143 ssid_len,
11144 WLAN_CAPABILITY_ESS,
11145 WLAN_CAPABILITY_ESS);
11146}
11147#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011148static
Abhishek Singhc9941602016-08-09 16:06:22 +053011149struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
11150 struct ieee80211_channel *channel, const u8 *bssid,
11151 const u8 *ssid, size_t ssid_len)
11152{
11153 return cfg80211_get_bss(wiphy, channel, bssid,
11154 ssid,
11155 ssid_len,
11156 IEEE80211_BSS_TYPE_ESS,
11157 IEEE80211_PRIVACY_ANY);
11158}
11159#endif
11160
11161
11162/*
11163 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
11164 * interface that BSS might have been lost.
11165 * @pAdapter: adaptor
11166 * @bssid: bssid which might have been lost
11167 *
11168 * Return: bss which is unlinked from kernel cache
11169 */
11170struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
11171 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011172{
11173 struct net_device *dev = pAdapter->dev;
11174 struct wireless_dev *wdev = dev->ieee80211_ptr;
11175 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011176 struct cfg80211_bss *bss = NULL;
11177
Abhishek Singhc9941602016-08-09 16:06:22 +053011178 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
11179 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011180 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011181 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011182 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053011183 hdd_info("cfg80211_unlink_bss called for BSSID "
11184 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011185 cfg80211_unlink_bss(wiphy, bss);
11186 }
11187 return bss;
11188}
11189
Abhishek Singhc9941602016-08-09 16:06:22 +053011190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011191/**
11192 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
11193 * @pAdapter: Pointer to adapter
11194 * @bss_desc: Pointer to bss descriptor
11195 *
11196 * This function is used to inform the BSS details to nl80211 interface.
11197 *
11198 * Return: struct cfg80211_bss pointer
11199 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053011200struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
11201 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011202{
11203 /*
11204 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
11205 * already exists in bss data base of cfg80211 for that particular BSS
11206 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
11207 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
11208 * As of now there is no possibility to get the mgmt(probe response)
11209 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
11210 * and passing to cfg80211_inform_bss_frame.
11211 */
11212 struct net_device *dev = pAdapter->dev;
11213 struct wireless_dev *wdev = dev->ieee80211_ptr;
11214 struct wiphy *wiphy = wdev->wiphy;
11215 int chan_no = bss_desc->channelId;
11216#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
11217 qcom_ie_age *qie_age = NULL;
11218 int ie_length =
11219 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
11220#else
11221 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
11222#endif
11223 const char *ie =
11224 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
11225 unsigned int freq;
11226 struct ieee80211_channel *chan;
11227 struct ieee80211_mgmt *mgmt = NULL;
11228 struct cfg80211_bss *bss_status = NULL;
11229 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
11230 int rssi = 0;
11231 hdd_context_t *pHddCtx;
11232 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011233 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011234 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011235
11236 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11237 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011238 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011239 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011240
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011241 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011242 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
11243 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011244 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011245 return NULL;
11246 }
11247
11248 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
11249
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011251 * Instead it wants a monotonic increasing value
11252 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070011253 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011254 mgmt->u.probe_resp.timestamp =
11255 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011256
11257 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
11258 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
11259
11260#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
11261 /* GPS Requirement: need age ie per entry. Using vendor specific. */
11262 /* Assuming this is the last IE, copy at the end */
11263 ie_length -= sizeof(qcom_ie_age);
11264 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
11265 qie_age->element_id = QCOM_VENDOR_IE_ID;
11266 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
11267 qie_age->oui_1 = QCOM_OUI1;
11268 qie_age->oui_2 = QCOM_OUI2;
11269 qie_age->oui_3 = QCOM_OUI3;
11270 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053011271 /*
11272 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
11273 * all bss related timestamp is in units of ms. Due to this when scan
11274 * results are sent to lowi the scan age is high.To address this,
11275 * send age in units of 1/10 ms.
11276 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011277 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053011278 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011279 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070011280 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
11281 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070011282 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
11283 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011284#endif
11285
11286 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
11287 if (bss_desc->fProbeRsp) {
11288 mgmt->frame_control |=
11289 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
11290 } else {
11291 mgmt->frame_control |=
11292 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
11293 }
11294
11295 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070011296 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011297 freq =
11298 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070011299 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011300 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070011301 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011302 freq =
11303 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070011304 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011305 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011306 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011307 kfree(mgmt);
11308 return NULL;
11309 }
11310
11311 chan = __ieee80211_get_channel(wiphy, freq);
11312 /* When the band is changed on the fly using the GUI, three things are done
11313 * 1. scan abort
11314 * 2. flush scan results from cache
11315 * 3. update the band with the new band user specified (refer to the
11316 * hdd_set_band_helper function) as part of the scan abort, message will be
11317 * queued to PE and we proceed with flushing and changinh the band.
11318 * PE will stop the scanning further and report back the results what ever
11319 * it had till now by calling the call back function.
11320 * if the time between update band and scandone call back is sufficient
11321 * enough the band change reflects in SME, SME validates the channels
11322 * and discards the channels correponding to previous band and calls back
11323 * with zero bss results. but if the time between band update and scan done
11324 * callback is very small then band change will not reflect in SME and SME
11325 * reports to HDD all the channels correponding to previous band.this is due
11326 * to race condition.but those channels are invalid to the new band and so
11327 * this function __ieee80211_get_channel will return NULL.Each time we
11328 * report scan result with this pointer null warning kernel trace is printed.
11329 * if the scan results contain large number of APs continuosly kernel
11330 * warning trace is printed and it will lead to apps watch dog bark.
11331 * So drop the bss and continue to next bss.
11332 */
11333 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053011334 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
11335 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011336 kfree(mgmt);
11337 return NULL;
11338 }
11339
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070011340 /* Based on .ini configuration, raw rssi can be reported for bss.
11341 * Raw rssi is typically used for estimating power.
11342 */
11343
11344 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
11345 bss_desc->rssi;
11346
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011347 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053011348 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011349
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053011350 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011351 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070011352 (int)(rssi / 100),
11353 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011354
11355 bss_status =
11356 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
11357 GFP_KERNEL);
11358 kfree(mgmt);
11359 return bss_status;
11360}
11361
11362/**
11363 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
11364 * @pAdapter: Pointer to adapter
11365 * @pRoamInfo: Pointer to roam info
11366 *
11367 * This function is used to update the BSS data base of CFG8011
11368 *
11369 * Return: struct cfg80211_bss pointer
11370 */
11371struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
11372 tCsrRoamInfo *pRoamInfo)
11373{
11374 tCsrRoamConnectedProfile roamProfile;
11375 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11376 struct cfg80211_bss *bss = NULL;
11377
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011378 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
11379 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
11380
11381 if (NULL != roamProfile.pBssDesc) {
11382 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11383 roamProfile.pBssDesc);
11384
11385 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011386 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011387
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080011388 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011389 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011390 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011391 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011392 return bss;
11393}
11394/**
11395 * wlan_hdd_cfg80211_update_bss() - update bss
11396 * @wiphy: Pointer to wiphy
11397 * @pAdapter: Pointer to adapter
11398 * @scan_time: scan request timestamp
11399 *
11400 * Return: zero if success, non-zero otherwise
11401 */
11402int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
11403 hdd_adapter_t *pAdapter,
11404 uint32_t scan_time)
11405{
11406 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11407 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011408 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011409 tScanResultHandle pResult;
11410 struct cfg80211_bss *bss_status = NULL;
11411 hdd_context_t *pHddCtx;
11412 int ret;
11413
11414 ENTER();
11415
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011416 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11417 hdd_err("invalid session id: %d", pAdapter->sessionId);
11418 return -EINVAL;
11419 }
11420
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011421 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011422 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
11423 NO_SESSION, pAdapter->sessionId));
11424
11425 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11426 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011427 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011428 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011429
11430 /* start getting scan results and populate cgf80211 BSS database */
11431 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
11432
11433 /* no scan results */
11434 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011435 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053011436 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011437 }
11438
11439 pScanResult = sme_scan_result_get_first(hHal, pResult);
11440
11441 while (pScanResult) {
11442 /*
11443 * - cfg80211_inform_bss() is not updating ie field of bss
11444 * entry if entry already exists in bss data base of cfg80211
11445 * for that particular BSS ID. Using cfg80211_inform_bss_frame
11446 * to update thebss entry instead of cfg80211_inform_bss,
11447 * But this call expects mgmt packet as input. As of now
11448 * there is no possibility to get the mgmt(probe response)
11449 * frame from PE, converting bss_desc to
11450 * ieee80211_mgmt(probe response) and passing to c
11451 * fg80211_inform_bss_frame.
11452 * - Update BSS only if beacon timestamp is later than
11453 * scan request timestamp.
11454 */
11455 if ((scan_time == 0) ||
11456 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053011457 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011458 bss_status =
11459 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11460 &pScanResult->BssDescriptor);
11461
11462 if (NULL == bss_status) {
11463 hdd_info("NULL returned by cfg80211_inform_bss_frame");
11464 } else {
11465 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011466 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011467 bss_status);
11468 }
11469 } else {
11470 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
11471 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
11472 }
11473 pScanResult = sme_scan_result_get_next(hHal, pResult);
11474 }
11475
11476 sme_scan_result_purge(hHal, pResult);
11477 /*
11478 * For SAP mode, scan is invoked by hostapd during SAP start
11479 * if hostapd is restarted, we need to flush previous scan
11480 * result so that it will reflect environment change
11481 */
Krunal Sonib4326f22016-03-10 13:05:51 -080011482 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011483#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
11484 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
11485#endif
11486 )
11487 sme_scan_flush_result(hHal);
11488
11489 EXIT();
11490 return 0;
11491}
11492
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011493/**
11494 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
11495 * @pAdapter: Pointer to adapter
11496 * @pRoamInfo: Pointer to roam info
11497 * @index: Index
11498 * @preauth: Preauth flag
11499 *
11500 * This function is used to notify the supplicant of a new PMKSA candidate.
11501 *
11502 * Return: 0 for success, non-zero for failure
11503 */
11504int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
11505 tCsrRoamInfo *pRoamInfo,
11506 int index, bool preauth)
11507{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011508 struct net_device *dev = pAdapter->dev;
11509 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
11510
11511 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011512 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011513
11514 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011515 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011516 return -EINVAL;
11517 }
11518
11519 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011520 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011521 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
11522 cfg80211_pmksa_candidate_notify(dev, index,
11523 pRoamInfo->bssid.bytes,
11524 preauth, GFP_KERNEL);
11525 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011526 return 0;
11527}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011528
11529#ifdef FEATURE_WLAN_LFR_METRICS
11530/**
11531 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
11532 * @pAdapter: Pointer to adapter
11533 * @pRoamInfo: Pointer to roam info
11534 *
11535 * 802.11r/LFR metrics reporting function to report preauth initiation
11536 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011537 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011538 */
11539#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011540QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011541 tCsrRoamInfo *pRoamInfo)
11542{
11543 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11544 union iwreq_data wrqu;
11545
11546 ENTER();
11547
11548 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011549 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011550 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011551 }
11552
11553 /* create the event */
11554 memset(&wrqu, 0, sizeof(wrqu));
11555 memset(metrics_notification, 0, sizeof(metrics_notification));
11556
11557 wrqu.data.pointer = metrics_notification;
11558 wrqu.data.length = scnprintf(metrics_notification,
11559 sizeof(metrics_notification),
11560 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
11561 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11562
11563 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11564 metrics_notification);
11565
11566 EXIT();
11567
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011568 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011569}
11570
11571/**
11572 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11573 * @pAdapter: Pointer to adapter
11574 * @pRoamInfo: Pointer to roam info
11575 * @preauth_status: Preauth status
11576 *
11577 * 802.11r/LFR metrics reporting function to report handover initiation
11578 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011579 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011580 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011581QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011582wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
11583 tCsrRoamInfo *pRoamInfo,
11584 bool preauth_status)
11585{
11586 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11587 union iwreq_data wrqu;
11588
11589 ENTER();
11590
11591 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011592 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011593 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011594 }
11595
11596 /* create the event */
11597 memset(&wrqu, 0, sizeof(wrqu));
11598 memset(metrics_notification, 0, sizeof(metrics_notification));
11599
11600 scnprintf(metrics_notification, sizeof(metrics_notification),
11601 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
11602 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11603
11604 if (1 == preauth_status)
11605 strlcat(metrics_notification, " true",
11606 sizeof(metrics_notification));
11607 else
11608 strlcat(metrics_notification, " false",
11609 sizeof(metrics_notification));
11610
11611 wrqu.data.pointer = metrics_notification;
11612 wrqu.data.length = strlen(metrics_notification);
11613
11614 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11615 metrics_notification);
11616
11617 EXIT();
11618
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011619 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011620}
11621
11622/**
11623 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11624 * @pAdapter: Pointer to adapter
11625 * @pRoamInfo: Pointer to roam info
11626 *
11627 * 802.11r/LFR metrics reporting function to report handover initiation
11628 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011629 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011630 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011631QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011632 tCsrRoamInfo *pRoamInfo)
11633{
11634 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11635 union iwreq_data wrqu;
11636
11637 ENTER();
11638
11639 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011640 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011641 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011642 }
11643
11644 /* create the event */
11645 memset(&wrqu, 0, sizeof(wrqu));
11646 memset(metrics_notification, 0, sizeof(metrics_notification));
11647
11648 wrqu.data.pointer = metrics_notification;
11649 wrqu.data.length = scnprintf(metrics_notification,
11650 sizeof(metrics_notification),
11651 "QCOM: LFR_PREAUTH_HANDOVER "
11652 MAC_ADDRESS_STR,
11653 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11654
11655 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11656 metrics_notification);
11657
11658 EXIT();
11659
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011660 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011661}
11662#endif
11663
11664/**
11665 * hdd_select_cbmode() - select channel bonding mode
11666 * @pAdapter: Pointer to adapter
11667 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011668 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011669 *
11670 * Return: none
11671 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011672void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11673 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011674{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011675 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011676 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011677 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011678
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011679 /*
11680 * CDS api expects secondary channel for calculating
11681 * the channel params
11682 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011683 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011684 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11685 if (operationChannel >= 1 && operationChannel <= 5)
11686 sec_ch = operationChannel + 4;
11687 else if (operationChannel >= 6 && operationChannel <= 13)
11688 sec_ch = operationChannel - 4;
11689 }
11690
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011691 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011692 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011693
11694 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011695 eHddDot11Mode hdd_dot11_mode;
11696 uint8_t iniDot11Mode =
11697 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11698
11699 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11700 switch (iniDot11Mode) {
11701 case eHDD_DOT11_MODE_AUTO:
11702 case eHDD_DOT11_MODE_11ac:
11703 case eHDD_DOT11_MODE_11ac_ONLY:
11704 if (sme_is_feature_supported_by_fw(DOT11AC))
11705 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11706 else
11707 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11708 break;
11709 case eHDD_DOT11_MODE_11n:
11710 case eHDD_DOT11_MODE_11n_ONLY:
11711 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11712 break;
11713 default:
11714 hdd_dot11_mode = iniDot11Mode;
11715 break;
11716 }
11717 ch_info->channel_width = ch_params->ch_width;
11718 ch_info->phy_mode =
11719 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011720 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011721 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011722 hdd_info("ch_info width %d, phymode %d channel %d",
11723 ch_info->channel_width, ch_info->phy_mode,
11724 ch_info->channel);
11725 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011726}
11727
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011728/**
11729 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11730 * @adapter: STA adapter
11731 * @roam_profile: STA roam profile
11732 *
11733 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11734 *
11735 * Return: false if sta-sap conc is not allowed, else return true
11736 */
11737static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11738 tCsrRoamProfile *roam_profile)
11739{
11740 hdd_context_t *hdd_ctx;
11741 hdd_adapter_t *ap_adapter;
11742 hdd_ap_ctx_t *hdd_ap_ctx;
11743 hdd_hostapd_state_t *hostapd_state;
11744 uint8_t channel = 0;
11745 QDF_STATUS status;
11746
11747 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11748 if (!hdd_ctx) {
11749 hdd_err("HDD context is NULL");
11750 return true;
11751 }
11752
11753 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11754 /* probably no sap running, no handling required */
11755 if (ap_adapter == NULL)
11756 return true;
11757
11758 /*
11759 * sap is not in started state, so it is fine to go ahead with sta.
11760 * if sap is currently doing CAC then don't allow sta to go further.
11761 */
11762 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11763 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11764 return true;
11765
11766 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11767 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11768 return false;
11769 }
11770
11771 /*
11772 * log and return error, if we allow STA to go through, we don't
11773 * know what is going to happen better stop sta connection
11774 */
11775 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11776 if (NULL == hdd_ap_ctx) {
11777 hdd_err("AP context not found");
11778 return false;
11779 }
11780
11781 /* sap is on non-dfs channel, nothing to handle */
11782 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11783 hdd_info("sap is on non-dfs channel, sta is allowed");
11784 return true;
11785 }
11786 /*
11787 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011788 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011789 */
11790 status = cds_get_channel_from_scan_result(adapter,
11791 roam_profile, &channel);
11792
Nitesh Shah59774522016-09-16 15:14:21 +053011793 /*
11794 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11795 * channels for roaming case.
11796 */
11797 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11798 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11799 return true;
11800 }
11801
11802 /*
11803 * If channel is 0 or DFS then better to call pcl and find out the
11804 * best channel. If channel is non-dfs 5 GHz then better move SAP
11805 * to STA's channel to make scc, so we have room for 3port MCC
11806 * scenario.
11807 */
11808 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011809 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11810 true);
11811
11812 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11813 qdf_event_reset(&hostapd_state->qdf_event);
11814 status = wlansap_set_channel_change_with_csa(
11815 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11816 hdd_ap_ctx->sapConfig.ch_width_orig);
11817
11818 if (QDF_STATUS_SUCCESS != status) {
11819 hdd_err("Set channel with CSA IE failed, can't allow STA");
11820 return false;
11821 }
11822
11823 /*
11824 * wait here for SAP to finish the channel switch. When channel
11825 * switch happens, SAP sends few beacons with CSA_IE. After
11826 * successfully Transmission of those beacons, it will move its
11827 * state from started to disconnected and move to new channel.
11828 * once it moves to new channel, sap again moves its state
11829 * machine from disconnected to started and set this event.
11830 * wait for 10 secs to finish this.
11831 */
11832 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11833 if (!QDF_IS_STATUS_SUCCESS(status)) {
11834 hdd_err("wait for qdf_event failed, STA not allowed!!");
11835 return false;
11836 }
11837
11838 return true;
11839}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011840
Krunal Soni31949422016-07-29 17:17:53 -070011841/**
11842 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011843 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011844 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011845 * @ssid_len: Length of ssid
11846 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011847 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011848 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011849 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011850 *
11851 * This function is used to start the association process
11852 *
11853 * Return: 0 for success, non-zero for failure
11854 */
Krunal Soni31949422016-07-29 17:17:53 -070011855static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011856 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011857 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011858 u8 operatingChannel,
11859 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011860{
11861 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080011862 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011863 hdd_wext_state_t *pWextState;
11864 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011865 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011866 uint32_t roamId;
11867 tCsrRoamProfile *pRoamProfile;
11868 eCsrAuthType RSNAuthType;
11869 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011870 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011871
11872 ENTER();
11873
11874 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11875 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011876 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011877
11878 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011879 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011880 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011881
11882 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011883 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011884 return -EINVAL;
11885 }
11886
11887 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011888 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11889 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011890
11891 if (pRoamProfile) {
11892 hdd_station_ctx_t *pHddStaCtx;
11893 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11894
11895 if (HDD_WMM_USER_MODE_NO_QOS ==
11896 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11897 /*QoS not enabled in cfg file */
11898 pRoamProfile->uapsd_mask = 0;
11899 } else {
11900 /*QoS enabled, update uapsd mask from cfg file */
11901 pRoamProfile->uapsd_mask =
11902 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11903 }
11904
11905 pRoamProfile->SSIDs.numOfSSIDs = 1;
11906 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011907 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011908 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011909 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011910 ssid, ssid_len);
11911
Deepak Dhamdherea2785822016-11-17 01:17:45 -080011912 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053011913 /* cleanup bssid hint */
11914 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
11915 QDF_MAC_ADDR_SIZE);
11916 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
11917 QDF_MAC_ADDR_SIZE);
11918
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011919 if (bssid) {
11920 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011921 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011922 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011923 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011924 /*
11925 * Save BSSID in seperate variable as
11926 * pRoamProfile's BSSID is getting zeroed out in the
11927 * association process. In case of join failure
11928 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011929 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011930 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011931 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011932 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011933 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053011934 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
11935 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011936 /*
11937 * Save BSSID in a separate variable as
11938 * pRoamProfile's BSSID is getting zeroed out in the
11939 * association process. In case of join failure
11940 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011941 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011942 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011943 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011944 hdd_info("bssid_hint is given by upper layer %pM",
11945 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011946 }
11947
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011948 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011949 pRoamProfile->SSIDs.SSIDList->SSID.length,
11950 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11951 operatingChannel);
11952
11953 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11954 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011955 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011956 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11957 }
11958#ifdef FEATURE_WLAN_WAPI
11959 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011960 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011961 switch (pAdapter->wapi_info.wapiAuthMode) {
11962 case WAPI_AUTH_MODE_PSK:
11963 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011964 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011965 pAdapter->wapi_info.wapiAuthMode);
11966 pRoamProfile->AuthType.authType[0] =
11967 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11968 break;
11969 }
11970 case WAPI_AUTH_MODE_CERT:
11971 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011972 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011973 pAdapter->wapi_info.wapiAuthMode);
11974 pRoamProfile->AuthType.authType[0] =
11975 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11976 break;
11977 }
11978 } /* End of switch */
11979 if (pAdapter->wapi_info.wapiAuthMode ==
11980 WAPI_AUTH_MODE_PSK
11981 || pAdapter->wapi_info.wapiAuthMode ==
11982 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011983 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011984 pRoamProfile->AuthType.numEntries = 1;
11985 pRoamProfile->EncryptionType.numEntries = 1;
11986 pRoamProfile->EncryptionType.encryptionType[0] =
11987 eCSR_ENCRYPT_TYPE_WPI;
11988 pRoamProfile->mcEncryptionType.numEntries = 1;
11989 pRoamProfile->mcEncryptionType.
11990 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11991 }
11992 }
Krunal Soni31949422016-07-29 17:17:53 -070011993#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011994#ifdef WLAN_FEATURE_GTK_OFFLOAD
11995 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011996 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11997 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011998 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11999 sizeof(tSirGtkOffloadParams));
12000 pHddStaCtx->gtkOffloadReqParams.ulFlags =
12001 GTK_OFFLOAD_DISABLE;
12002 }
12003#endif
12004 pRoamProfile->csrPersona = pAdapter->device_mode;
12005
12006 if (operatingChannel) {
12007 pRoamProfile->ChannelInfo.ChannelList =
12008 &operatingChannel;
12009 pRoamProfile->ChannelInfo.numOfChannels = 1;
12010 } else {
12011 pRoamProfile->ChannelInfo.ChannelList = NULL;
12012 pRoamProfile->ChannelInfo.numOfChannels = 0;
12013 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012014 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012015 && operatingChannel) {
12016 /*
12017 * Need to post the IBSS power save parameters
12018 * to WMA. WMA will configure this parameters
12019 * to firmware if power save is enabled by the
12020 * firmware.
12021 */
12022 status = hdd_set_ibss_power_save_params(pAdapter);
12023
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012024 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012025 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012026 return -EINVAL;
12027 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012028 pRoamProfile->ch_params.ch_width =
12029 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053012030 /*
12031 * In IBSS mode while operating in 2.4 GHz,
12032 * the device supports only 20 MHz.
12033 */
12034 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
12035 pRoamProfile->ch_params.ch_width =
12036 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012037 hdd_select_cbmode(pAdapter, operatingChannel,
12038 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012039 }
Abhishek Singh99bce862016-06-20 15:10:51 +053012040 /*
12041 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12042 * or pmf=2 is an explicit configuration in the supplicant
12043 * configuration, drop the connection request.
12044 */
12045 if (pWextState->roamProfile.MFPEnabled &&
12046 !(pWextState->roamProfile.MFPRequired ||
12047 pWextState->roamProfile.MFPCapable)) {
12048 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12049 pWextState->roamProfile.MFPEnabled,
12050 pWextState->roamProfile.MFPRequired,
12051 pWextState->roamProfile.MFPCapable);
12052 return -EINVAL;
12053 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012054
Krunal Soni3091bcc2016-06-23 12:28:21 -070012055 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012056 hdd_err("Connection refused: conn in progress");
12057 return -EINVAL;
12058 }
12059
Krunal Soni31949422016-07-29 17:17:53 -070012060 /*
12061 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012062 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070012063 * enhancements, the supplicant is not issuing the scan command
12064 * now. So the unicast frames which are sent from the host are
12065 * not having the additional IEs. If it is P2P CLIENT and there
12066 * is no additional IE present in roamProfile, then use the
12067 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012068 */
12069
Krunal Sonib4326f22016-03-10 13:05:51 -080012070 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012071 (!pRoamProfile->pAddIEScan)) {
12072 pRoamProfile->pAddIEScan =
12073 &pAdapter->scan_info.scanAddIE.addIEdata[0];
12074 pRoamProfile->nAddIEScanLength =
12075 pAdapter->scan_info.scanAddIE.length;
12076 }
12077 /*
12078 * When policy manager is enabled from ini file, we shouldn't
12079 * check for other concurrency rules.
12080 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070012081 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080012082 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012083 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012084 pAdapter, pRoamProfile, &roamId))
12085 return 0;
12086 }
12087
Krunal Soni3091bcc2016-06-23 12:28:21 -070012088 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012089 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
12090 pRoamProfile))) {
12091 hdd_err("sap-sta conc will fail, can't allow sta");
12092 hdd_conn_set_connection_state(pAdapter,
12093 eConnectionState_NotConnected);
12094 return -ENOMEM;
12095 }
12096
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012097 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012098 if (!sme_config) {
12099 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012100 hdd_conn_set_connection_state(pAdapter,
12101 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012102 return -ENOMEM;
12103 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012104 sme_get_config_param(pHddCtx->hHal, sme_config);
12105 /* These values are not sessionized. So, any change in these SME
12106 * configs on an older or parallel interface will affect the
12107 * cb mode. So, restoring the default INI params before starting
12108 * interfaces such as sta, cli etc.,
12109 */
12110 sme_config->csrConfig.channelBondingMode5GHz =
12111 pHddCtx->config->nChannelBondingMode5GHz;
12112 sme_config->csrConfig.channelBondingMode24GHz =
12113 pHddCtx->config->nChannelBondingMode24GHz;
12114 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012115 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053012116 /*
12117 * Change conn_state to connecting before sme_roam_connect(),
12118 * because sme_roam_connect() has a direct path to call
12119 * hdd_sme_roam_callback(), which will change the conn_state
12120 * If direct path, conn_state will be accordingly changed to
12121 * NotConnected or Associated by either
12122 * hdd_association_completion_handler() or
12123 * hdd_dis_connect_handler() in sme_RoamCallback()if
12124 * sme_RomConnect is to be queued,
12125 * Connecting state will remain until it is completed.
12126 *
12127 * If connection state is not changed, connection state will
12128 * remain in eConnectionState_NotConnected state.
12129 * In hdd_association_completion_handler, "hddDisconInProgress"
12130 * is set to true if conn state is
12131 * eConnectionState_NotConnected.
12132 * If "hddDisconInProgress" is set to true then cfg80211 layer
12133 * is not informed of connect result indication which
12134 * is an issue.
12135 */
12136 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053012137 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053012138 hdd_conn_set_connection_state(pAdapter,
12139 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012140
Komal Seelama89be8d2016-09-29 11:09:26 +053012141 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
12142 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080012143 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012144 pAdapter->sessionId, pRoamProfile,
12145 &roamId);
12146
Rajeev Kumard31e1542017-01-13 14:37:42 -080012147 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080012148 (QDF_STA_MODE == pAdapter->device_mode ||
12149 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012150 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080012151 "qdf_status %d. -> NotConnected",
12152 pAdapter->sessionId, qdf_status);
12153 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012154 /* change back to NotAssociated */
12155 hdd_conn_set_connection_state(pAdapter,
12156 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053012157 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
12158 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012159 }
12160
12161 pRoamProfile->ChannelInfo.ChannelList = NULL;
12162 pRoamProfile->ChannelInfo.numOfChannels = 0;
12163
Nitesh Shah044fd672016-10-13 18:53:25 +053012164 if ((QDF_STA_MODE == pAdapter->device_mode)
Krunal Soni4274f362016-12-14 19:55:25 -080012165 && wma_is_current_hwmode_dbs()) {
Nitesh Shah044fd672016-10-13 18:53:25 +053012166 cds_get_channel_from_scan_result(pAdapter,
12167 pRoamProfile, &channel);
12168 if (channel)
12169 cds_checkn_update_hw_mode_single_mac_mode
12170 (channel);
12171 }
12172
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012173 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012174 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012175 return -EINVAL;
12176 }
12177 EXIT();
12178 return status;
12179}
12180
12181/**
12182 * wlan_hdd_cfg80211_set_auth_type() - set auth type
12183 * @pAdapter: Pointer to adapter
12184 * @auth_type: Auth type
12185 *
12186 * This function is used to set the authentication type (OPEN/SHARED).
12187 *
12188 * Return: 0 for success, non-zero for failure
12189 */
12190static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
12191 enum nl80211_auth_type auth_type)
12192{
12193 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12194 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12195
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012196 /*set authentication type */
12197 switch (auth_type) {
12198 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012199 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012200 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
12201 break;
12202
12203 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012204 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012205 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012206 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12207 break;
12208
12209 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012210 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012211 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
12212 break;
12213#ifdef FEATURE_WLAN_ESE
12214 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012215 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012216 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
12217 break;
12218#endif
12219
12220 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012221 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012222 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
12223 return -EINVAL;
12224 }
12225
12226 pWextState->roamProfile.AuthType.authType[0] =
12227 pHddStaCtx->conn_info.authType;
12228 return 0;
12229}
12230
12231/**
12232 * wlan_hdd_set_akm_suite() - set key management type
12233 * @pAdapter: Pointer to adapter
12234 * @key_mgmt: Key management type
12235 *
12236 * This function is used to set the key mgmt type(PSK/8021x).
12237 *
12238 * Return: 0 for success, non-zero for failure
12239 */
12240static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
12241{
12242 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12243
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012244#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
12245#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
12246 /*set key mgmt type */
12247 switch (key_mgmt) {
12248 case WLAN_AKM_SUITE_PSK:
12249 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012250 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012251 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012252 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
12253 break;
12254
12255 case WLAN_AKM_SUITE_8021X_SHA256:
12256 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012257 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012258 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012259 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
12260 break;
12261#ifdef FEATURE_WLAN_ESE
12262#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
12263#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
12264 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012265 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012266 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
12267 break;
12268#endif
12269#ifndef WLAN_AKM_SUITE_OSEN
12270#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
12271#endif
12272 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012273 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012274 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
12275 break;
12276
12277 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012278 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012279 return -EINVAL;
12280
12281 }
12282 return 0;
12283}
12284
12285/**
12286 * wlan_hdd_cfg80211_set_cipher() - set encryption type
12287 * @pAdapter: Pointer to adapter
12288 * @cipher: Cipher type
12289 * @ucast: Unicast flag
12290 *
12291 * This function is used to set the encryption type
12292 * (NONE/WEP40/WEP104/TKIP/CCMP).
12293 *
12294 * Return: 0 for success, non-zero for failure
12295 */
12296static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
12297 u32 cipher, bool ucast)
12298{
12299 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12300 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12301 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12302
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012303 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012304 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012305 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12306 } else {
12307
12308 /*set encryption method */
12309 switch (cipher) {
12310 case IW_AUTH_CIPHER_NONE:
12311 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12312 break;
12313
12314 case WLAN_CIPHER_SUITE_WEP40:
12315 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
12316 break;
12317
12318 case WLAN_CIPHER_SUITE_WEP104:
12319 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
12320 break;
12321
12322 case WLAN_CIPHER_SUITE_TKIP:
12323 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
12324 break;
12325
12326 case WLAN_CIPHER_SUITE_CCMP:
12327 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12328 break;
12329#ifdef FEATURE_WLAN_WAPI
12330 case WLAN_CIPHER_SUITE_SMS4:
12331 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
12332 break;
12333#endif
12334
12335#ifdef FEATURE_WLAN_ESE
12336 case WLAN_CIPHER_SUITE_KRK:
12337 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
12338 break;
12339#ifdef WLAN_FEATURE_ROAM_OFFLOAD
12340 case WLAN_CIPHER_SUITE_BTK:
12341 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
12342 break;
12343#endif
12344#endif
12345 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012346 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012347 return -EOPNOTSUPP;
12348 }
12349 }
12350
12351 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012352 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012353 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12354 pWextState->roamProfile.EncryptionType.numEntries = 1;
12355 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12356 encryptionType;
12357 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012358 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012359 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
12360 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
12361 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
12362 encryptionType;
12363 }
12364
12365 return 0;
12366}
12367
12368/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012369 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
12370 * @wext_state: Pointer to wext state
12371 * @gen_ie: Pointer to IE data
12372 * @len: length of IE data
12373 *
12374 * Return: 0 for success, non-zero for failure
12375 */
12376static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
12377 const uint8_t *gen_ie, uint16_t len)
12378{
12379 uint16_t cur_add_ie_len =
12380 wext_state->assocAddIE.length;
12381
12382 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12383 (wext_state->assocAddIE.length + len)) {
12384 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
12385 QDF_ASSERT(0);
12386 return -ENOMEM;
12387 }
12388 memcpy(wext_state->assocAddIE.addIEdata +
12389 cur_add_ie_len, gen_ie, len);
12390 wext_state->assocAddIE.length += len;
12391
12392 wext_state->roamProfile.pAddIEAssoc =
12393 wext_state->assocAddIE.addIEdata;
12394 wext_state->roamProfile.nAddIEAssocLength =
12395 wext_state->assocAddIE.length;
12396 return 0;
12397}
12398
12399/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012400 * wlan_hdd_cfg80211_set_ie() - set IEs
12401 * @pAdapter: Pointer to adapter
12402 * @ie: Pointer ot ie
12403 * @ie: IE length
12404 *
12405 * Return: 0 for success, non-zero for failure
12406 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012407static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012408 size_t ie_len)
12409{
12410 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12411 const uint8_t *genie = ie;
12412 uint16_t remLen = ie_len;
12413#ifdef FEATURE_WLAN_WAPI
12414 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
12415 u16 *tmp;
12416 uint16_t akmsuiteCount;
12417 int *akmlist;
12418#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012419 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012420
12421 /* clear previous assocAddIE */
12422 pWextState->assocAddIE.length = 0;
12423 pWextState->roamProfile.bWPSAssociation = false;
12424 pWextState->roamProfile.bOSENAssociation = false;
12425
12426 while (remLen >= 2) {
12427 uint16_t eLen = 0;
12428 uint8_t elementId;
12429 elementId = *genie++;
12430 eLen = *genie++;
12431 remLen -= 2;
12432
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012433 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012434
12435 switch (elementId) {
12436 case DOT11F_EID_WPA:
12437 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 -070012438 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012439 return -EINVAL;
12440 } else if (0 ==
12441 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
12442 uint16_t curAddIELen =
12443 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012444 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012445
12446 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12447 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012448 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012449 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012450 return -ENOMEM;
12451 }
12452 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12453 memcpy(pWextState->assocAddIE.addIEdata +
12454 curAddIELen, genie - 2, eLen + 2);
12455 pWextState->assocAddIE.length += eLen + 2;
12456
12457 pWextState->roamProfile.bWPSAssociation = true;
12458 pWextState->roamProfile.pAddIEAssoc =
12459 pWextState->assocAddIE.addIEdata;
12460 pWextState->roamProfile.nAddIEAssocLength =
12461 pWextState->assocAddIE.length;
12462 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012463 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012464 memset(pWextState->WPARSNIE, 0,
12465 MAX_WPA_RSN_IE_LEN);
12466 memcpy(pWextState->WPARSNIE, genie - 2,
12467 (eLen + 2));
12468 pWextState->roamProfile.pWPAReqIE =
12469 pWextState->WPARSNIE;
12470 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
12471 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
12472 P2P_OUI_TYPE_SIZE))) {
12473 uint16_t curAddIELen =
12474 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012475 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012476
12477 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12478 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012479 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012480 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012481 return -ENOMEM;
12482 }
12483 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12484 memcpy(pWextState->assocAddIE.addIEdata +
12485 curAddIELen, genie - 2, eLen + 2);
12486 pWextState->assocAddIE.length += eLen + 2;
12487
12488 pWextState->roamProfile.pAddIEAssoc =
12489 pWextState->assocAddIE.addIEdata;
12490 pWextState->roamProfile.nAddIEAssocLength =
12491 pWextState->assocAddIE.length;
12492 }
12493#ifdef WLAN_FEATURE_WFD
12494 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
12495 WFD_OUI_TYPE_SIZE)) &&
12496 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080012497 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012498 pAdapter->device_mode)) {
12499 uint16_t curAddIELen =
12500 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012501 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012502
12503 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12504 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012505 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012506 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012507 return -ENOMEM;
12508 }
12509 /* WFD IE is saved to Additional IE ; it should
12510 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012511 * WFD IE
12512 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012513 memcpy(pWextState->assocAddIE.addIEdata +
12514 curAddIELen, genie - 2, eLen + 2);
12515 pWextState->assocAddIE.length += eLen + 2;
12516
12517 pWextState->roamProfile.pAddIEAssoc =
12518 pWextState->assocAddIE.addIEdata;
12519 pWextState->roamProfile.nAddIEAssocLength =
12520 pWextState->assocAddIE.length;
12521 }
12522#endif
12523 /* Appending HS 2.0 Indication Element in Assiciation Request */
12524 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
12525 HS20_OUI_TYPE_SIZE))) {
12526 uint16_t curAddIELen =
12527 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012528 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012529
12530 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12531 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012532 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012533 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012534 return -ENOMEM;
12535 }
12536 memcpy(pWextState->assocAddIE.addIEdata +
12537 curAddIELen, genie - 2, eLen + 2);
12538 pWextState->assocAddIE.length += eLen + 2;
12539
12540 pWextState->roamProfile.pAddIEAssoc =
12541 pWextState->assocAddIE.addIEdata;
12542 pWextState->roamProfile.nAddIEAssocLength =
12543 pWextState->assocAddIE.length;
12544 }
12545 /* Appending OSEN Information Element in Assiciation Request */
12546 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
12547 OSEN_OUI_TYPE_SIZE))) {
12548 uint16_t curAddIELen =
12549 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012550 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012551
12552 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12553 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012554 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012555 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012556 return -ENOMEM;
12557 }
12558 memcpy(pWextState->assocAddIE.addIEdata +
12559 curAddIELen, genie - 2, eLen + 2);
12560 pWextState->assocAddIE.length += eLen + 2;
12561
12562 pWextState->roamProfile.bOSENAssociation = true;
12563 pWextState->roamProfile.pAddIEAssoc =
12564 pWextState->assocAddIE.addIEdata;
12565 pWextState->roamProfile.nAddIEAssocLength =
12566 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012567 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
12568 MBO_OUI_TYPE_SIZE))){
12569 hdd_info("Set MBO IE(len %d)", eLen + 2);
12570 status = wlan_hdd_add_assoc_ie(pWextState,
12571 genie - 2, eLen + 2);
12572 if (status)
12573 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012574 } else {
12575 uint16_t add_ie_len =
12576 pWextState->assocAddIE.length;
12577
12578 hdd_info("Set OSEN IE(len %d)", eLen + 2);
12579
12580 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12581 (pWextState->assocAddIE.length + eLen)) {
12582 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012583 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012584 return -ENOMEM;
12585 }
12586
12587 memcpy(pWextState->assocAddIE.addIEdata +
12588 add_ie_len, genie - 2, eLen + 2);
12589 pWextState->assocAddIE.length += eLen + 2;
12590
12591 pWextState->roamProfile.pAddIEAssoc =
12592 pWextState->assocAddIE.addIEdata;
12593 pWextState->roamProfile.nAddIEAssocLength =
12594 pWextState->assocAddIE.length;
12595 }
12596 break;
12597 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012598 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012599 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
12600 memcpy(pWextState->WPARSNIE, genie - 2,
12601 (eLen + 2));
12602 pWextState->roamProfile.pRSNReqIE =
12603 pWextState->WPARSNIE;
12604 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12605 break;
12606 /*
12607 * Appending Extended Capabilities with Interworking bit set
12608 * in Assoc Req.
12609 *
12610 * In assoc req this EXT Cap will only be taken into account if
12611 * interworkingService bit is set to 1. Currently
12612 * driver is only interested in interworkingService capability
12613 * from supplicant. If in future any other EXT Cap info is
12614 * required from supplicat, it needs to be handled while
12615 * sending Assoc Req in LIM.
12616 */
12617 case DOT11F_EID_EXTCAP:
12618 {
12619 uint16_t curAddIELen =
12620 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012621 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012622
12623 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12624 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012625 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012626 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012627 return -ENOMEM;
12628 }
12629 memcpy(pWextState->assocAddIE.addIEdata +
12630 curAddIELen, genie - 2, eLen + 2);
12631 pWextState->assocAddIE.length += eLen + 2;
12632
12633 pWextState->roamProfile.pAddIEAssoc =
12634 pWextState->assocAddIE.addIEdata;
12635 pWextState->roamProfile.nAddIEAssocLength =
12636 pWextState->assocAddIE.length;
12637 break;
12638 }
12639#ifdef FEATURE_WLAN_WAPI
12640 case WLAN_EID_WAPI:
12641 /* Setting WAPI Mode to ON=1 */
12642 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012643 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012644 tmp = (u16 *) ie;
12645 tmp = tmp + 2; /* Skip element Id and Len, Version */
12646 akmsuiteCount = WPA_GET_LE16(tmp);
12647 tmp = tmp + 1;
12648 akmlist = (int *)(tmp);
12649 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12650 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12651 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012652 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012653 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012654 return -EINVAL;
12655 }
12656
12657 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012658 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012659 pAdapter->wapi_info.wapiAuthMode =
12660 WAPI_AUTH_MODE_PSK;
12661 }
12662 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012663 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012664 pAdapter->wapi_info.wapiAuthMode =
12665 WAPI_AUTH_MODE_CERT;
12666 }
12667 break;
12668#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012669 case DOT11F_EID_SUPPOPERATINGCLASSES:
12670 {
12671 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12672 status = wlan_hdd_add_assoc_ie(pWextState,
12673 genie - 2, eLen + 2);
12674 if (status)
12675 return status;
12676 break;
12677 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012678 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012679 hdd_err("Set UNKNOWN IE %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012680 /* when Unknown IE is received we break
12681 * and continue to the next IE in the buffer
12682 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012683 break;
12684 }
12685 genie += eLen;
12686 remLen -= eLen;
12687 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012688 return 0;
12689}
12690
12691/**
12692 * hdd_is_wpaie_present() - check for WPA ie
12693 * @ie: Pointer to ie
12694 * @ie_len: Ie length
12695 *
12696 * Parse the received IE to find the WPA IE
12697 *
12698 * Return: true if wpa ie is found else false
12699 */
12700static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12701{
12702 uint8_t eLen = 0;
12703 uint16_t remLen = ie_len;
12704 uint8_t elementId = 0;
12705
12706 while (remLen >= 2) {
12707 elementId = *ie++;
12708 eLen = *ie++;
12709 remLen -= 2;
12710 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012711 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012712 return false;
12713 }
12714 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12715 /* OUI - 0x00 0X50 0XF2
12716 * WPA Information Element - 0x01
12717 * WPA version - 0x01
12718 */
12719 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12720 return true;
12721 }
12722 ie += eLen;
12723 remLen -= eLen;
12724 }
12725 return false;
12726}
12727
12728/**
12729 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12730 * @pAdapter: Pointer to adapter
12731 * @req: Pointer to security parameters
12732 *
12733 * Return: 0 for success, non-zero for failure
12734 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012735static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12736 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012737{
12738 int status = 0;
12739 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12740 ENTER();
12741
12742 /*set wpa version */
12743 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12744
12745 if (req->crypto.wpa_versions) {
12746 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12747 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12748 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12749 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12750 }
12751 }
12752
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012753 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012754
12755 /*set authentication type */
12756 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12757
12758 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012759 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012760 return status;
12761 }
12762
12763 /*set key mgmt type */
12764 if (req->crypto.n_akm_suites) {
12765 status =
12766 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12767 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012768 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012769 return status;
12770 }
12771 }
12772
12773 /*set pairwise cipher type */
12774 if (req->crypto.n_ciphers_pairwise) {
12775 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12776 req->crypto.
12777 ciphers_pairwise[0],
12778 true);
12779 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012780 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012781 return status;
12782 }
12783 } else {
12784 /*Reset previous cipher suite to none */
12785 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12786 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012787 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012788 return status;
12789 }
12790 }
12791
12792 /*set group cipher type */
12793 status =
12794 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12795 false);
12796
12797 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012798 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012799 return status;
12800 }
12801#ifdef WLAN_FEATURE_11W
12802 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12803#endif
12804
12805 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12806 if (req->ie_len) {
12807 status =
12808 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12809 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012810 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012811 return status;
12812 }
12813 }
12814
12815 /*incase of WEP set default key information */
12816 if (req->key && req->key_len) {
12817 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12818 || (WLAN_CIPHER_SUITE_WEP104 ==
12819 req->crypto.ciphers_pairwise[0])
12820 ) {
12821 if (IW_AUTH_KEY_MGMT_802_1X
12822 ==
12823 (pWextState->
12824 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012825 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012826 return -EOPNOTSUPP;
12827 } else {
12828 u8 key_len = req->key_len;
12829 u8 key_idx = req->key_idx;
12830
12831 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12832 key_len)
12833 && (CSR_MAX_NUM_KEY > key_idx)
12834 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012835 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012836 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012837 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012838 Keys.
12839 KeyMaterial[key_idx][0],
12840 req->key, key_len);
12841 pWextState->roamProfile.Keys.
12842 KeyLength[key_idx] = (u8) key_len;
12843 pWextState->roamProfile.Keys.
12844 defaultIndex = (u8) key_idx;
12845 }
12846 }
12847 }
12848 }
12849
12850 return status;
12851}
12852
12853/**
12854 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12855 * @pAdapter: Pointer to adapter
12856 *
12857 * This function is used to disconnect from previous connection
12858 *
12859 * Return: 0 for success, non-zero for failure
12860 */
12861static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12862{
12863 unsigned long rc;
12864 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012865 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012866
12867 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12868
Jeff Johnson9edf9572016-10-03 15:24:49 -070012869 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012870 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12871 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12872 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012873 hdd_conn_set_connection_state(pAdapter,
12874 eConnectionState_Disconnecting);
12875 /* Issue disconnect to CSR */
12876 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012877
12878 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12879 pAdapter->sessionId,
12880 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12881 /*
12882 * Wait here instead of returning directly, this will block the
12883 * next connect command and allow processing of the scan for
12884 * ssid and the previous connect command in CSR. Else we might
12885 * hit some race conditions leading to SME and HDD out of sync.
12886 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012887 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012888 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12889 } else if (0 != status) {
12890 hdd_err("csrRoamDisconnect failure, returned %d",
12891 (int)status);
12892 pHddStaCtx->staDebugState = status;
12893 result = -EINVAL;
12894 goto disconnected;
12895 }
12896
12897 rc = wait_for_completion_timeout(
12898 &pAdapter->disconnect_comp_var,
12899 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012900 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012901 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12902 pAdapter->sessionId, pHddStaCtx->staDebugState);
12903 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012904 }
12905 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012906 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012907 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012908 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012909 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012910 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012911 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012912 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012913 }
12914 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012915disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012916 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12917 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012918}
12919
12920/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012921 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12922 * @adapter: Pointer to the HDD adapter
12923 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012924 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012925 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012926 * This function will start reassociation if prev_bssid is set and bssid/
12927 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012928 *
Naveen Rawat07332902016-07-27 09:13:17 -070012929 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012930 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012931#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12932 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012933static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12934 struct cfg80211_connect_params *req,
12935 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012936{
Naveen Rawat07332902016-07-27 09:13:17 -070012937 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012938 const uint8_t *bssid = NULL;
12939 uint16_t channel = 0;
12940
12941 if (req->bssid)
12942 bssid = req->bssid;
12943 else if (req->bssid_hint)
12944 bssid = req->bssid_hint;
12945
12946 if (req->channel)
12947 channel = req->channel->hw_value;
12948 else if (req->channel_hint)
12949 channel = req->channel_hint->hw_value;
12950
12951 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012952 reassoc = true;
12953 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012954 channel, MAC_ADDR_ARRAY(bssid));
12955 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012956 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012957 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012958 }
Naveen Rawat07332902016-07-27 09:13:17 -070012959 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012960}
12961#else
Naveen Rawat07332902016-07-27 09:13:17 -070012962static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12963 struct cfg80211_connect_params *req,
12964 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012965{
Naveen Rawat07332902016-07-27 09:13:17 -070012966 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012967}
12968#endif
12969
12970/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012971 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12972 * @wiphy: Pointer to wiphy
12973 * @dev: Pointer to network device
12974 * @req: Pointer to cfg80211 connect request
12975 *
12976 * This function is used to start the association process
12977 *
12978 * Return: 0 for success, non-zero for failure
12979 */
12980static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12981 struct net_device *ndev,
12982 struct cfg80211_connect_params *req)
12983{
12984 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012985 u16 channel;
12986#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12987 const u8 *bssid_hint = req->bssid_hint;
12988#else
12989 const u8 *bssid_hint = NULL;
12990#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012991 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12992 hdd_context_t *pHddCtx;
12993
12994 ENTER();
12995
Anurag Chouhan6d760662016-02-20 16:05:43 +053012996 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012997 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012998 return -EINVAL;
12999 }
13000
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013001 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13002 hdd_err("invalid session id: %d", pAdapter->sessionId);
13003 return -EINVAL;
13004 }
13005
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013006 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013007 TRACE_CODE_HDD_CFG80211_CONNECT,
13008 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013009 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013010 hdd_device_mode_to_string(pAdapter->device_mode),
13011 pAdapter->device_mode);
13012
Krunal Sonib4326f22016-03-10 13:05:51 -080013013 if (pAdapter->device_mode != QDF_STA_MODE &&
13014 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013015 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013016 hdd_device_mode_to_string(pAdapter->device_mode),
13017 pAdapter->device_mode);
13018 return -EINVAL;
13019 }
13020
13021 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13022 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013023 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013024 return -EINVAL;
13025 }
13026
13027 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013028 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013029 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013030
Naveen Rawat07332902016-07-27 09:13:17 -070013031 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013032 return status;
13033
Agrawal Ashishf156e942016-08-04 14:54:47 +053013034 /* Try disconnecting if already in connected state */
13035 status = wlan_hdd_try_disconnect(pAdapter);
13036 if (0 > status) {
13037 hdd_err("Failed to disconnect the existing connection");
13038 return -EALREADY;
13039 }
13040
13041 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013042 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013043 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080013044 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013045 pAdapter->device_mode),
13046 req->channel->hw_value, HW_MODE_20_MHZ)) {
13047 hdd_err("This concurrency combination is not allowed");
13048 return -ECONNREFUSED;
13049 }
13050 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013051 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080013052 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013053 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
13054 hdd_err("This concurrency combination is not allowed");
13055 return -ECONNREFUSED;
13056 }
13057 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070013058
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013059 /*initialise security parameters */
13060 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
13061
13062 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013063 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013064 return status;
13065 }
13066
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053013067 if (req->channel)
13068 channel = req->channel->hw_value;
13069 else
13070 channel = 0;
13071 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
13072 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013073 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013074 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013075 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013076 return status;
13077 }
13078 EXIT();
13079 return status;
13080}
13081
13082/**
13083 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
13084 * @wiphy: Pointer to wiphy
13085 * @dev: Pointer to network device
13086 * @req: Pointer to cfg80211 connect request
13087 *
13088 * Return: 0 for success, non-zero for failure
13089 */
13090static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
13091 struct net_device *ndev,
13092 struct cfg80211_connect_params *req)
13093{
13094 int ret;
13095 cds_ssr_protect(__func__);
13096 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
13097 cds_ssr_unprotect(__func__);
13098
13099 return ret;
13100}
13101
13102/**
13103 * wlan_hdd_disconnect() - hdd disconnect api
13104 * @pAdapter: Pointer to adapter
13105 * @reason: Disconnect reason code
13106 *
13107 * This function is used to issue a disconnect request to SME
13108 *
13109 * Return: 0 for success, non-zero for failure
13110 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013111static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013112{
13113 int status, result = 0;
13114 unsigned long rc;
13115 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13116 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13117
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013118 ENTER();
13119
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013120 status = wlan_hdd_validate_context(pHddCtx);
13121
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013122 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013123 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013124
13125 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013126 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013127 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
13128 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013129 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013130 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
13131 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13132
13133 /*issue disconnect */
13134
13135 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13136 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053013137 /*
13138 * Wait here instead of returning directly, this will block the next
13139 * connect command and allow processing of the scan for ssid and
13140 * the previous connect command in CSR. Else we might hit some
13141 * race conditions leading to SME and HDD out of sync.
13142 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013143 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013144 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013145 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013146 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013147 (int)status);
13148 pHddStaCtx->staDebugState = status;
13149 result = -EINVAL;
13150 goto disconnected;
13151 }
13152 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13153 msecs_to_jiffies
13154 (WLAN_WAIT_TIME_DISCONNECT));
13155
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013156 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013157 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013158 result = -ETIMEDOUT;
13159 }
13160disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013161 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
13162#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
13163 /* Sending disconnect event to userspace for kernel version < 3.11
13164 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
13165 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013166 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053013167 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
13168 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013169#endif
13170
13171 return result;
13172}
13173
13174/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013175 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
13176 * @reason: ieee80211 reason code.
13177 *
13178 * This utility function helps log string conversion of reason code.
13179 *
13180 * Return: string conversion of reason code, if match found;
13181 * "Unknown" otherwise.
13182 */
13183static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
13184{
13185 switch (reason) {
13186 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
13187 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
13188 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
13189 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
13190 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
13191 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
13192 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
13193 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
13194 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
13195 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
13196 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
13197 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
13198 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
13199 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
13200 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
13201 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
13202 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
13203 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
13204 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
13205 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
13206 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
13207 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
13208 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
13209 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
13210 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
13211 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
13212 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
13213 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
13214 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
13215 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
13216 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
13217 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
13218 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
13219 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
13220 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
13221 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
13222 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
13223 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
13224 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
13225 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
13226 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
13227 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
13228 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
13229 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
13230 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
13231 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
13232 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
13233 default:
13234 return "Unknown";
13235 }
13236}
13237
13238/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013239 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
13240 * @wiphy: Pointer to wiphy
13241 * @dev: Pointer to network device
13242 * @reason: Disconnect reason code
13243 *
13244 * This function is used to issue a disconnect request to SME
13245 *
13246 * Return: 0 for success, non-zero for failure
13247 */
13248static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
13249 struct net_device *dev, u16 reason)
13250{
13251 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13252 int status;
13253 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13254 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13255#ifdef FEATURE_WLAN_TDLS
13256 uint8_t staIdx;
13257#endif
13258
13259 ENTER();
13260
Anurag Chouhan6d760662016-02-20 16:05:43 +053013261 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013262 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013263 return -EINVAL;
13264 }
13265
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013266 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13267 hdd_err("invalid session id: %d", pAdapter->sessionId);
13268 return -EINVAL;
13269 }
13270
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013271 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013272 TRACE_CODE_HDD_CFG80211_DISCONNECT,
13273 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013274 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013275 hdd_device_mode_to_string(pAdapter->device_mode),
13276 pAdapter->device_mode, reason);
13277
13278 status = wlan_hdd_validate_context(pHddCtx);
13279
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080013280 if (hdd_is_roaming_in_progress()) {
13281 hdd_err("Roaming In Progress. Ignore!!!");
13282 return -EAGAIN;
13283 }
13284
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013285 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013286 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013287
13288 /* Issue disconnect request to SME, if station is in connected state */
13289 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
13290 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
13291 eCsrRoamDisconnectReason reasonCode =
13292 eCSR_DISCONNECT_REASON_UNSPECIFIED;
13293 hdd_scaninfo_t *pScanInfo;
13294
13295 switch (reason) {
13296 case WLAN_REASON_MIC_FAILURE:
13297 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
13298 break;
13299
13300 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
13301 case WLAN_REASON_DISASSOC_AP_BUSY:
13302 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
13303 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
13304 break;
13305
13306 case WLAN_REASON_PREV_AUTH_NOT_VALID:
13307 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
13308 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
13309 break;
13310
13311 case WLAN_REASON_DEAUTH_LEAVING:
13312 reasonCode =
13313 pHddCtx->config->
13314 gEnableDeauthToDisassocMap ?
13315 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
13316 eCSR_DISCONNECT_REASON_DEAUTH;
13317 break;
13318 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
13319 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
13320 break;
13321 default:
13322 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
13323 break;
13324 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013325 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013326 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013327 pScanInfo = &pAdapter->scan_info;
13328 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013329 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013330 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053013331 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013332 eCSR_SCAN_ABORT_DEFAULT);
13333 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053013334 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013335#ifdef FEATURE_WLAN_TDLS
13336 /* First clean up the tdls peers if any */
13337 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
13338 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
13339 pAdapter->sessionId)
13340 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
13341 uint8_t *mac;
13342 mac =
13343 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013344 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
13345 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013346 pHddCtx->tdlsConnInfo[staIdx].staId,
13347 pAdapter->sessionId,
13348 MAC_ADDR_ARRAY(mac));
13349 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
13350 (pAdapter),
13351 pAdapter->sessionId, mac);
13352 }
13353 }
13354#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013355 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013356 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080013357 hdd_info("Disconnect request from user space with reason: %s",
13358 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013359 status = wlan_hdd_disconnect(pAdapter, reasonCode);
13360 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013361 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013362 return -EINVAL;
13363 }
13364 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013365 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013366 pHddStaCtx->conn_info.connState);
13367 }
13368
13369 return status;
13370}
13371
13372/**
13373 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
13374 * @wiphy: Pointer to wiphy
13375 * @dev: Pointer to network device
13376 * @reason: Disconnect reason code
13377 *
13378 * Return: 0 for success, non-zero for failure
13379 */
13380static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
13381 struct net_device *dev, u16 reason)
13382{
13383 int ret;
13384 cds_ssr_protect(__func__);
13385 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
13386 cds_ssr_unprotect(__func__);
13387
13388 return ret;
13389}
13390
13391/**
13392 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
13393 * @pAdapter: Pointer to adapter
13394 * @param: Pointer to IBSS parameters
13395 *
13396 * This function is used to initialize the security settings in IBSS mode
13397 *
13398 * Return: 0 for success, non-zero for failure
13399 */
13400static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
13401 struct cfg80211_ibss_params
13402 *params)
13403{
13404 int status = 0;
13405 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13406 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13407 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13408
13409 ENTER();
13410
13411 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013412 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013413 pHddStaCtx->ibss_enc_key_installed = 0;
13414
13415 if (params->ie_len && (NULL != params->ie)) {
13416 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13417 params->ie_len, WLAN_EID_RSN)) {
13418 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13419 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13420 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
13421 tDot11fIEWPA dot11WPAIE;
13422 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13423 u8 *ie;
13424
13425 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
13426 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13427 params->ie_len,
13428 DOT11F_EID_WPA);
13429 if (NULL != ie) {
13430 pWextState->wpaVersion =
13431 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013432 /* Unpack the WPA IE
13433 * Skip past the EID byte and length byte
13434 * and four byte WiFi OUI
13435 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013436 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
13437 &ie[2 + 4],
13438 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013439 /* Extract the multicast cipher, the
13440 * encType for unicast cipher for
13441 * wpa-none is none
13442 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013443 encryptionType =
13444 hdd_translate_wpa_to_csr_encryption_type
13445 (dot11WPAIE.multicast_cipher);
13446 }
13447 }
13448
13449 status =
13450 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
13451 params->ie_len);
13452
13453 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013454 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013455 return status;
13456 }
13457 }
13458
13459 pWextState->roamProfile.AuthType.authType[0] =
13460 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13461
13462 if (params->privacy) {
13463 /* Security enabled IBSS, At this time there is no information
13464 * available about the security paramters, so initialise the
13465 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
13466 * The correct security parameters will be updated later in
13467 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
13468 * set inorder enable privacy bit in beacons
13469 */
13470
13471 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
13472 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013473 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013474 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13475 pWextState->roamProfile.EncryptionType.numEntries = 1;
13476 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13477 encryptionType;
13478 return status;
13479}
13480
13481/**
13482 * __wlan_hdd_cfg80211_join_ibss() - join ibss
13483 * @wiphy: Pointer to wiphy
13484 * @dev: Pointer to network device
13485 * @param: Pointer to IBSS join parameters
13486 *
13487 * This function is used to create/join an IBSS network
13488 *
13489 * Return: 0 for success, non-zero for failure
13490 */
13491static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13492 struct net_device *dev,
13493 struct cfg80211_ibss_params *params)
13494{
13495 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13496 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13497 tCsrRoamProfile *pRoamProfile;
13498 int status;
13499 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13500 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053013501 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013502 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013503
13504 ENTER();
13505
Anurag Chouhan6d760662016-02-20 16:05:43 +053013506 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013507 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013508 return -EINVAL;
13509 }
13510
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013511 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13512 hdd_err("invalid session id: %d", pAdapter->sessionId);
13513 return -EINVAL;
13514 }
13515
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013516 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013517 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
13518 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013519 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013520 hdd_device_mode_to_string(pAdapter->device_mode),
13521 pAdapter->device_mode);
13522
13523 status = wlan_hdd_validate_context(pHddCtx);
13524
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013525 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013526 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013527
13528 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053013529 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013530 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
13531 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
13532 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13533 int indx;
13534
13535 /* Get channel number */
13536 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013537 params->
13538 chandef.
13539 chan->
13540 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013541
13542 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
13543 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013544 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013545 return -EOPNOTSUPP;
13546 }
13547
13548 for (indx = 0; indx < numChans; indx++) {
13549 if (channelNum == validChan[indx]) {
13550 break;
13551 }
13552 }
13553 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013554 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013555 return -EINVAL;
13556 }
13557 }
13558
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013559 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013560 HW_MODE_20_MHZ)) {
13561 hdd_err("This concurrency combination is not allowed");
13562 return -ECONNREFUSED;
13563 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013564
Krunal Soni3091bcc2016-06-23 12:28:21 -070013565 status = qdf_reset_connection_update();
13566 if (!QDF_IS_STATUS_SUCCESS(status))
13567 hdd_err("ERR: clear event failed");
13568
13569 status = cds_current_connections_update(pAdapter->sessionId,
13570 channelNum,
13571 SIR_UPDATE_REASON_JOIN_IBSS);
13572 if (QDF_STATUS_E_FAILURE == status) {
13573 hdd_err("ERROR: connections update failed!!");
13574 return -EINVAL;
13575 }
13576
13577 if (QDF_STATUS_SUCCESS == status) {
13578 status = qdf_wait_for_connection_update();
13579 if (!QDF_IS_STATUS_SUCCESS(status)) {
13580 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013581 return -EINVAL;
13582 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013583 }
13584
13585 /*Try disconnecting if already in connected state */
13586 status = wlan_hdd_try_disconnect(pAdapter);
13587 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013588 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013589 return -EALREADY;
13590 }
13591
13592 pRoamProfile = &pWextState->roamProfile;
13593
13594 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013595 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013596 return -EINVAL;
13597 }
13598
13599 /* enable selected protection checks in IBSS mode */
13600 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
13601
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013602 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013603 WNI_CFG_IBSS_ATIM_WIN_SIZE,
13604 pHddCtx->config->
13605 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013606 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013607 }
13608
13609 /* BSSID is provided by upper layers hence no need to AUTO generate */
13610 if (NULL != params->bssid) {
13611 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013612 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013613 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013614 return -EIO;
13615 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013616 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013617 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
13618 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013619 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013620 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013621 return -EIO;
13622 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053013623 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013624 }
13625 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13626 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13627 pRoamProfile->beaconInterval = params->beacon_interval;
13628 else {
13629 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013630 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013631 params->beacon_interval, pRoamProfile->beaconInterval);
13632 }
13633
13634 /* Set Channel */
13635 if (channelNum) {
13636 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013637 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013638 pRoamProfile->ChannelInfo.numOfChannels = 1;
13639 pHddStaCtx->conn_info.operationChannel = channelNum;
13640 pRoamProfile->ChannelInfo.ChannelList =
13641 &pHddStaCtx->conn_info.operationChannel;
13642 }
13643
13644 /* Initialize security parameters */
13645 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13646 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013647 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013648 return status;
13649 }
13650
13651 /* Issue connect start */
13652 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13653 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013654 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013655 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013656 operationChannel,
13657 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013658
13659 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013660 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013661 return status;
13662 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013663 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013664 return 0;
13665}
13666
13667/**
13668 * wlan_hdd_cfg80211_join_ibss() - join ibss
13669 * @wiphy: Pointer to wiphy
13670 * @dev: Pointer to network device
13671 * @param: Pointer to IBSS join parameters
13672 *
13673 * This function is used to create/join an IBSS network
13674 *
13675 * Return: 0 for success, non-zero for failure
13676 */
13677static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13678 struct net_device *dev,
13679 struct cfg80211_ibss_params *params)
13680{
13681 int ret = 0;
13682
13683 cds_ssr_protect(__func__);
13684 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13685 cds_ssr_unprotect(__func__);
13686
13687 return ret;
13688}
13689
13690/**
13691 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13692 * @wiphy: Pointer to wiphy
13693 * @dev: Pointer to network device
13694 *
13695 * This function is used to leave an IBSS network
13696 *
13697 * Return: 0 for success, non-zero for failure
13698 */
13699static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13700 struct net_device *dev)
13701{
13702 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13703 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13704 tCsrRoamProfile *pRoamProfile;
13705 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13706 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013707 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013708 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013709 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013710
13711 ENTER();
13712
Anurag Chouhan6d760662016-02-20 16:05:43 +053013713 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013714 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013715 return -EINVAL;
13716 }
13717
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013718 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13719 hdd_err("invalid session id: %d", pAdapter->sessionId);
13720 return -EINVAL;
13721 }
13722
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013723 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013724 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13725 pAdapter->sessionId,
13726 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13727 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013728 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013729 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013730
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013731 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013732 hdd_device_mode_to_string(pAdapter->device_mode),
13733 pAdapter->device_mode);
13734 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013735 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013736 return -EIO;
13737 }
13738
13739 pRoamProfile = &pWextState->roamProfile;
13740
13741 /* Issue disconnect only if interface type is set to IBSS */
13742 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013743 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013744 return -EINVAL;
13745 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013746 /* Clearing add IE of beacon */
13747 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13748 sizeof(tSirMacAddr));
13749 updateIE.smeSessionId = pAdapter->sessionId;
13750 updateIE.ieBufferlength = 0;
13751 updateIE.pAdditionIEBuffer = NULL;
13752 updateIE.append = true;
13753 updateIE.notify = true;
13754 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13755 &updateIE,
13756 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013757 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013758 }
13759
13760 /* Reset WNI_CFG_PROBE_RSP Flags */
13761 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013762
13763 /* Issue Disconnect request */
13764 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13765 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13766 pAdapter->sessionId,
13767 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013768 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013769 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013770 hal_status);
13771 return -EAGAIN;
13772 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013773
13774 /* wait for mc thread to cleanup and then return to upper stack
13775 * so by the time upper layer calls the change interface, we are
13776 * all set to proceed further
13777 */
13778 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13779 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13780 if (!rc) {
13781 hdd_err("Failed to disconnect, timed out");
13782 return -ETIMEDOUT;
13783 }
13784
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013785 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013786 return 0;
13787}
13788
13789/**
13790 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13791 * @wiphy: Pointer to wiphy
13792 * @dev: Pointer to network device
13793 *
13794 * This function is used to leave an IBSS network
13795 *
13796 * Return: 0 for success, non-zero for failure
13797 */
13798static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13799 struct net_device *dev)
13800{
13801 int ret = 0;
13802
13803 cds_ssr_protect(__func__);
13804 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13805 cds_ssr_unprotect(__func__);
13806
13807 return ret;
13808}
13809
13810/**
13811 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13812 * @wiphy: Pointer to wiphy
13813 * @changed: Parameters changed
13814 *
13815 * This function is used to set the phy parameters. RTS Threshold/FRAG
13816 * Threshold/Retry Count etc.
13817 *
13818 * Return: 0 for success, non-zero for failure
13819 */
13820static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13821 u32 changed)
13822{
13823 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13824 tHalHandle hHal = pHddCtx->hHal;
13825 int status;
13826
13827 ENTER();
13828
Anurag Chouhan6d760662016-02-20 16:05:43 +053013829 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013830 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013831 return -EINVAL;
13832 }
13833
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013834 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013835 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13836 NO_SESSION, wiphy->rts_threshold));
13837 status = wlan_hdd_validate_context(pHddCtx);
13838
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013839 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013840 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013841
13842 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13843 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13844 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13845
13846 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13847 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013848 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013849 rts_threshold);
13850 return -EINVAL;
13851 }
13852
13853 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13854 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013855 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013856 rts_threshold);
13857 return -EIO;
13858 }
13859
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013860 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013861 }
13862
13863 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13864 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13865 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13866 wiphy->frag_threshold;
13867
13868 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13869 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013870 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013871 frag_threshold);
13872 return -EINVAL;
13873 }
13874
13875 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13876 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013877 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013878 frag_threshold);
13879 return -EIO;
13880 }
13881
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013882 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013883 }
13884
13885 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13886 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13887 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13888 wiphy->retry_short : wiphy->retry_long;
13889
13890 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13891 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013892 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013893 return -EINVAL;
13894 }
13895
13896 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13897 if (0 != sme_cfg_set_int(hHal,
13898 WNI_CFG_LONG_RETRY_LIMIT,
13899 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013900 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013901 retry_value);
13902 return -EIO;
13903 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013904 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013905 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13906 if (0 != sme_cfg_set_int(hHal,
13907 WNI_CFG_SHORT_RETRY_LIMIT,
13908 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013909 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013910 retry_value);
13911 return -EIO;
13912 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013913 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013914 }
13915 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013916 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013917 return 0;
13918}
13919
13920/**
13921 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13922 * @wiphy: Pointer to wiphy
13923 * @changed: Parameters changed
13924 *
13925 * Return: 0 for success, non-zero for failure
13926 */
13927static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13928{
13929 int ret;
13930
13931 cds_ssr_protect(__func__);
13932 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13933 cds_ssr_unprotect(__func__);
13934
13935 return ret;
13936}
13937
13938/**
13939 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13940 * key
13941 * @wiphy: Pointer to wiphy
13942 * @dev: Pointer to network device
13943 * @key_index: Key index
13944 *
13945 * Return: 0
13946 */
13947static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13948 struct net_device *netdev,
13949 u8 key_index)
13950{
13951 ENTER();
13952 return 0;
13953}
13954
13955/**
13956 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13957 * wlan_hdd_set_default_mgmt_key
13958 * @wiphy: pointer to wiphy
13959 * @netdev: pointer to net_device structure
13960 * @key_index: key index
13961 *
13962 * Return: 0 on success, error number on failure
13963 */
13964static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13965 struct net_device *netdev,
13966 u8 key_index)
13967{
13968 int ret;
13969
13970 cds_ssr_protect(__func__);
13971 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13972 cds_ssr_unprotect(__func__);
13973
13974 return ret;
13975}
13976
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013977/**
13978 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13979 * @wiphy: Pointer to wiphy
13980 * @dev: Pointer to network device
13981 * @params: Pointer to tx queue parameters
13982 *
13983 * Return: 0
13984 */
13985static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13986 struct net_device *dev,
13987 struct ieee80211_txq_params *params)
13988{
13989 ENTER();
13990 return 0;
13991}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013992
13993/**
13994 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13995 * @wiphy: pointer to wiphy
13996 * @netdev: pointer to net_device structure
13997 * @params: pointer to ieee80211_txq_params
13998 *
13999 * Return: 0 on success, error number on failure
14000 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014001static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
14002 struct net_device *dev,
14003 struct ieee80211_txq_params *params)
14004{
14005 int ret;
14006
14007 cds_ssr_protect(__func__);
14008 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
14009 cds_ssr_unprotect(__func__);
14010
14011 return ret;
14012}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014013
14014/**
14015 * __wlan_hdd_cfg80211_del_station() - delete station v2
14016 * @wiphy: Pointer to wiphy
14017 * @param: Pointer to delete station parameter
14018 *
14019 * Return: 0 for success, non-zero for failure
14020 */
14021static
14022int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14023 struct net_device *dev,
14024 struct tagCsrDelStaParams *pDelStaParams)
14025{
14026 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14027 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053014028 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014029 hdd_hostapd_state_t *hapd_state;
14030 int status;
14031 uint8_t staId;
14032 uint8_t *mac;
14033
14034 ENTER();
14035
Anurag Chouhan6d760662016-02-20 16:05:43 +053014036 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014037 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014038 return -EINVAL;
14039 }
14040
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014041 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14042 hdd_err("invalid session id: %d", pAdapter->sessionId);
14043 return -EINVAL;
14044 }
14045
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014046 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014047 TRACE_CODE_HDD_CFG80211_DEL_STA,
14048 pAdapter->sessionId, pAdapter->device_mode));
14049
14050 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14051 status = wlan_hdd_validate_context(pHddCtx);
14052
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014053 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014054 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014055
14056 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
14057
Krunal Sonib4326f22016-03-10 13:05:51 -080014058 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
14059 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014060
14061 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14062 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014063 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014064 return 0;
14065 }
14066
Anurag Chouhanc5548422016-02-24 18:33:27 +053014067 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014068 uint16_t i;
14069 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
14070 if ((pAdapter->aStaInfo[i].isUsed) &&
14071 (!pAdapter->aStaInfo[i].
14072 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014073 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014074 mac,
14075 pAdapter->aStaInfo[i].
14076 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053014077 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014078 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
14079 hdd_ipa_wlan_evt(pAdapter,
14080 pAdapter->
14081 aStaInfo[i].
14082 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070014083 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014084 mac);
14085 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014086 hdd_notice("Delete STA with MAC::"
14087 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014088 MAC_ADDR_ARRAY(mac));
14089
14090 if (pHddCtx->dev_dfs_cac_status ==
14091 DFS_CAC_IN_PROGRESS)
14092 goto fn_end;
14093
Wei Song2f76f642016-11-18 16:32:53 +080014094 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014095 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053014096 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014097 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014098 hdd_softap_sta_deauth(pAdapter,
14099 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014100 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014101 pAdapter->aStaInfo[i].
14102 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053014103 qdf_status =
14104 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080014105 &hapd_state->
14106 qdf_sta_disassoc_event,
14107 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053014108 if (!QDF_IS_STATUS_SUCCESS(
14109 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014110 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014111 }
14112 }
14113 }
14114 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014115 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014116 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053014117 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014118 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014119 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014120 hdd_notice("Skip DEL STA as this is not used::"
14121 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014122 MAC_ADDR_ARRAY(mac));
14123 return -ENOENT;
14124 }
14125
14126 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
14127 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070014128 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014129 }
14130
14131 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
14132 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014133 hdd_notice("Skip DEL STA as deauth is in progress::"
14134 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014135 MAC_ADDR_ARRAY(mac));
14136 return -ENOENT;
14137 }
14138
14139 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
14140
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014141 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014142 MAC_ADDR_ARRAY(mac));
14143
14144 /* Case: SAP in ACS selected DFS ch and client connected
14145 * Now Radar detected. Then if random channel is another
14146 * DFS ch then new CAC is initiated and no TX allowed.
14147 * So do not send any mgmt frames as it will timeout
14148 * during CAC.
14149 */
14150
14151 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
14152 goto fn_end;
14153
Wei Song2f76f642016-11-18 16:32:53 +080014154 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053014155 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
14156 (pAdapter), pAdapter->sessionId,
14157 (uint8_t *)&pDelStaParams->peerMacAddr,
14158 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014159 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014160 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014161 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014162 pAdapter->aStaInfo[staId].isDeauthInProgress =
14163 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014164 hdd_notice("STA removal failed for ::"
14165 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014166 MAC_ADDR_ARRAY(mac));
14167 return -ENOENT;
14168 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053014169 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080014170 &hapd_state->
14171 qdf_sta_disassoc_event,
14172 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053014173 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014174 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014175 }
14176 }
14177 }
14178
14179fn_end:
14180 EXIT();
14181 return 0;
14182}
14183
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014184#if defined(USE_CFG80211_DEL_STA_V2)
14185/**
14186 * wlan_hdd_del_station() - delete station wrapper
14187 * @adapter: pointer to the hdd adapter
14188 *
14189 * Return: None
14190 */
14191void wlan_hdd_del_station(hdd_adapter_t *adapter)
14192{
14193 struct station_del_parameters del_sta;
14194 del_sta.mac = NULL;
14195 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
14196 del_sta.reason_code = eCsrForcedDeauthSta;
14197
14198 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
14199 &del_sta);
14200}
14201#else
14202void wlan_hdd_del_station(hdd_adapter_t *adapter)
14203{
14204 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
14205}
14206#endif
14207
14208#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014209/**
14210 * wlan_hdd_cfg80211_del_station() - delete station v2
14211 * @wiphy: Pointer to wiphy
14212 * @param: Pointer to delete station parameter
14213 *
14214 * Return: 0 for success, non-zero for failure
14215 */
14216int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14217 struct net_device *dev,
14218 struct station_del_parameters *param)
14219#else
14220/**
14221 * wlan_hdd_cfg80211_del_station() - delete station
14222 * @wiphy: Pointer to wiphy
14223 * @mac: Pointer to station mac address
14224 *
14225 * Return: 0 for success, non-zero for failure
14226 */
14227#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14228int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14229 struct net_device *dev,
14230 const uint8_t *mac)
14231#else
14232int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
14233 struct net_device *dev,
14234 uint8_t *mac)
14235#endif
14236#endif
14237{
14238 int ret;
14239 struct tagCsrDelStaParams delStaParams;
14240
14241 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014242#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014243 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080014244 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014245 return -EINVAL;
14246 }
14247 wlansap_populate_del_sta_params(param->mac, param->reason_code,
14248 param->subtype, &delStaParams);
14249#else
14250 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
14251 (SIR_MAC_MGMT_DEAUTH >> 4),
14252 &delStaParams);
14253#endif
14254 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
14255 cds_ssr_unprotect(__func__);
14256
14257 return ret;
14258}
14259
14260/**
14261 * __wlan_hdd_cfg80211_add_station() - add station
14262 * @wiphy: Pointer to wiphy
14263 * @mac: Pointer to station mac address
14264 * @pmksa: Pointer to add station parameter
14265 *
14266 * Return: 0 for success, non-zero for failure
14267 */
14268static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14269 struct net_device *dev,
14270 const uint8_t *mac,
14271 struct station_parameters *params)
14272{
14273 int status = -EPERM;
14274#ifdef FEATURE_WLAN_TDLS
14275 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14276 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14277 u32 mask, set;
14278
14279 ENTER();
14280
Anurag Chouhan6d760662016-02-20 16:05:43 +053014281 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014282 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014283 return -EINVAL;
14284 }
14285
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014286 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14287 hdd_err("invalid session id: %d", pAdapter->sessionId);
14288 return -EINVAL;
14289 }
14290
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014291 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014292 TRACE_CODE_HDD_CFG80211_ADD_STA,
14293 pAdapter->sessionId, params->listen_interval));
14294
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014295 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014296 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014297
14298 mask = params->sta_flags_mask;
14299
14300 set = params->sta_flags_set;
14301
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014302 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014303 MAC_ADDR_ARRAY(mac));
14304
14305 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14306 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
14307 status =
14308 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
14309 }
14310 }
14311#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014312 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014313 return status;
14314}
14315
14316/**
14317 * wlan_hdd_cfg80211_add_station() - add station
14318 * @wiphy: Pointer to wiphy
14319 * @mac: Pointer to station mac address
14320 * @pmksa: Pointer to add station parameter
14321 *
14322 * Return: 0 for success, non-zero for failure
14323 */
14324#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14325static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14326 struct net_device *dev,
14327 const uint8_t *mac,
14328 struct station_parameters *params)
14329#else
14330static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
14331 struct net_device *dev, uint8_t *mac,
14332 struct station_parameters *params)
14333#endif
14334{
14335 int ret;
14336
14337 cds_ssr_protect(__func__);
14338 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
14339 cds_ssr_unprotect(__func__);
14340
14341 return ret;
14342}
14343
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014344/**
14345 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
14346 * @wiphy: Pointer to wiphy
14347 * @dev: Pointer to network device
14348 * @pmksa: Pointer to set pmksa parameter
14349 *
14350 * Return: 0 for success, non-zero for failure
14351 */
14352static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14353 struct net_device *dev,
14354 struct cfg80211_pmksa *pmksa)
14355{
14356 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14357 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14358 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014359 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014360 int status;
14361 tPmkidCacheInfo pmk_id;
14362
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014363 ENTER();
14364
Anurag Chouhan6d760662016-02-20 16:05:43 +053014365 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014366 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014367 return -EINVAL;
14368 }
14369
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014370 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14371 hdd_err("invalid session id: %d", pAdapter->sessionId);
14372 return -EINVAL;
14373 }
14374
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014375 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014376 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014377 return -EINVAL;
14378 }
14379
14380 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014381 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014382 pmksa->bssid, pmksa->pmkid);
14383 return -EINVAL;
14384 }
14385
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014386 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014387 MAC_ADDR_ARRAY(pmksa->bssid));
14388
14389 status = wlan_hdd_validate_context(pHddCtx);
14390
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014391 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014392 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014393
14394 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14395
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014396 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
14397 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014398
14399 /* Add to the PMKSA ID Cache in CSR */
14400 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
14401 &pmk_id, 1, false);
14402
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014403 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014404 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
14405 pAdapter->sessionId, result));
14406
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014407 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014408 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014409}
14410
14411/**
14412 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
14413 * @wiphy: Pointer to wiphy
14414 * @dev: Pointer to network device
14415 * @pmksa: Pointer to set pmksa parameter
14416 *
14417 * Return: 0 for success, non-zero for failure
14418 */
14419static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14420 struct net_device *dev,
14421 struct cfg80211_pmksa *pmksa)
14422{
14423 int ret;
14424
14425 cds_ssr_protect(__func__);
14426 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
14427 cds_ssr_unprotect(__func__);
14428
14429 return ret;
14430}
14431
14432/**
14433 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14434 * @wiphy: Pointer to wiphy
14435 * @dev: Pointer to network device
14436 * @pmksa: Pointer to pmksa parameter
14437 *
14438 * Return: 0 for success, non-zero for failure
14439 */
14440static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14441 struct net_device *dev,
14442 struct cfg80211_pmksa *pmksa)
14443{
14444 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14445 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14446 tHalHandle halHandle;
14447 int status = 0;
14448
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014449 ENTER();
14450
Anurag Chouhan6d760662016-02-20 16:05:43 +053014451 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014452 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014453 return -EINVAL;
14454 }
14455
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014456 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14457 hdd_err("invalid session id: %d", pAdapter->sessionId);
14458 return -EINVAL;
14459 }
14460
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014461 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014462 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014463 return -EINVAL;
14464 }
14465
14466 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014467 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014468 return -EINVAL;
14469 }
14470
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014471 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014472 MAC_ADDR_ARRAY(pmksa->bssid));
14473
14474 status = wlan_hdd_validate_context(pHddCtx);
14475
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014476 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014477 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014478
14479 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14480
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014481 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014482 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
14483 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014484 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014485 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014486 sme_roam_del_pmkid_from_cache(halHandle,
14487 pAdapter->sessionId, pmksa->bssid,
14488 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014489 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014490 MAC_ADDR_ARRAY(pmksa->bssid));
14491 status = -EINVAL;
14492 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014493 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014494 return status;
14495}
14496
14497/**
14498 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14499 * @wiphy: Pointer to wiphy
14500 * @dev: Pointer to network device
14501 * @pmksa: Pointer to pmksa parameter
14502 *
14503 * Return: 0 for success, non-zero for failure
14504 */
14505static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14506 struct net_device *dev,
14507 struct cfg80211_pmksa *pmksa)
14508{
14509 int ret;
14510
14511 cds_ssr_protect(__func__);
14512 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
14513 cds_ssr_unprotect(__func__);
14514
14515 return ret;
14516
14517}
14518
14519/**
14520 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14521 * @wiphy: Pointer to wiphy
14522 * @dev: Pointer to network device
14523 *
14524 * Return: 0 for success, non-zero for failure
14525 */
14526static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14527 struct net_device *dev)
14528{
14529 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14530 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14531 tHalHandle halHandle;
14532 int status = 0;
14533
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014534 ENTER();
14535
Anurag Chouhan6d760662016-02-20 16:05:43 +053014536 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014537 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014538 return -EINVAL;
14539 }
14540
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014541 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14542 hdd_err("invalid session id: %d", pAdapter->sessionId);
14543 return -EINVAL;
14544 }
14545
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014546 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014547
14548 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14549 status = wlan_hdd_validate_context(pHddCtx);
14550
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014551 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014552 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014553
14554 /* Retrieve halHandle */
14555 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14556
14557 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014558 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014559 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
14560 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014561 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014562 status = -EINVAL;
14563 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014564 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014565 return status;
14566}
14567
14568/**
14569 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14570 * @wiphy: Pointer to wiphy
14571 * @dev: Pointer to network device
14572 *
14573 * Return: 0 for success, non-zero for failure
14574 */
14575static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14576 struct net_device *dev)
14577{
14578 int ret;
14579
14580 cds_ssr_protect(__func__);
14581 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
14582 cds_ssr_unprotect(__func__);
14583
14584 return ret;
14585}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014586
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014587#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014588/**
14589 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14590 * @wiphy: Pointer to wiphy
14591 * @dev: Pointer to network device
14592 * @ftie: Pointer to fast transition ie parameter
14593 *
14594 * Return: 0 for success, non-zero for failure
14595 */
14596static int
14597__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14598 struct net_device *dev,
14599 struct cfg80211_update_ft_ies_params *ftie)
14600{
14601 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14602 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14603 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14604 int status;
14605
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014606 ENTER();
14607
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014608 status = wlan_hdd_validate_context(hdd_ctx);
14609 if (status)
14610 return status;
14611
Anurag Chouhan6d760662016-02-20 16:05:43 +053014612 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014613 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014614 return -EINVAL;
14615 }
14616
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014617 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14618 hdd_err("invalid session id: %d", pAdapter->sessionId);
14619 return -EINVAL;
14620 }
14621
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014622 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014623 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
14624 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
14625 /* Added for debug on reception of Re-assoc Req. */
14626 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014627 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014628 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014629 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014630 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014631 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014632 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014633
14634 /* Pass the received FT IEs to SME */
14635 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
14636 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014637 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014638 return 0;
14639}
14640
14641/**
14642 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14643 * @wiphy: Pointer to wiphy
14644 * @dev: Pointer to network device
14645 * @ftie: Pointer to fast transition ie parameter
14646 *
14647 * Return: 0 for success, non-zero for failure
14648 */
14649static int
14650wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14651 struct net_device *dev,
14652 struct cfg80211_update_ft_ies_params *ftie)
14653{
14654 int ret;
14655
14656 cds_ssr_protect(__func__);
14657 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14658 cds_ssr_unprotect(__func__);
14659
14660 return ret;
14661}
14662#endif
14663
14664#ifdef WLAN_FEATURE_GTK_OFFLOAD
14665/**
14666 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14667 * @callbackContext: Callback context
14668 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14669 *
14670 * Callback rountine called upon receiving response for get offload info
14671 *
14672 * Return: none
14673 */
14674void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14675 tpSirGtkOffloadGetInfoRspParams
14676 pGtkOffloadGetInfoRsp)
14677{
14678 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14679 uint8_t tempReplayCounter[8];
14680 hdd_station_ctx_t *pHddStaCtx;
14681
14682 ENTER();
14683
14684 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014685 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014686 return;
14687 }
14688
14689 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014690 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014691 return;
14692 }
14693
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014694 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014695 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014696 return;
14697 }
14698
14699 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14700 /* Update replay counter */
14701 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14702 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14703
14704 {
14705 /* changing from little to big endian since supplicant
14706 * works on big endian format
14707 */
14708 int i;
14709 uint8_t *p =
14710 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14711
14712 for (i = 0; i < 8; i++) {
14713 tempReplayCounter[7 - i] = (uint8_t) p[i];
14714 }
14715 }
14716
14717 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014718 cfg80211_gtk_rekey_notify(pAdapter->dev,
14719 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014720 tempReplayCounter, GFP_KERNEL);
14721}
14722
14723/**
14724 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14725 * @wiphy: Pointer to wiphy
14726 * @dev: Pointer to network device
14727 * @data: Pointer to rekey data
14728 *
14729 * This function is used to offload GTK rekeying job to the firmware.
14730 *
14731 * Return: 0 for success, non-zero for failure
14732 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014733static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014734int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14735 struct net_device *dev,
14736 struct cfg80211_gtk_rekey_data *data)
14737{
14738 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14739 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14740 hdd_station_ctx_t *pHddStaCtx;
14741 tHalHandle hHal;
14742 int result;
14743 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014744 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014745
14746 ENTER();
14747
Anurag Chouhan6d760662016-02-20 16:05:43 +053014748 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014749 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014750 return -EINVAL;
14751 }
14752
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014753 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14754 hdd_err("invalid session id: %d", pAdapter->sessionId);
14755 return -EINVAL;
14756 }
14757
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014758 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014759 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14760 pAdapter->sessionId, pAdapter->device_mode));
14761
14762 result = wlan_hdd_validate_context(pHddCtx);
14763
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014764 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014765 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014766
14767 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14768 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14769 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014770 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014771 return -EAGAIN;
14772 }
14773
14774 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14775 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14776 NL80211_KCK_LEN);
14777 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14778 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014779 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014780 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014781 {
14782 /* changing from big to little endian since driver
14783 * works on little endian format
14784 */
14785 uint8_t *p =
14786 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14787 ullKeyReplayCounter;
14788 int i;
14789
14790 for (i = 0; i < 8; i++) {
14791 p[7 - i] = data->replay_ctr[i];
14792 }
14793 }
14794
14795 if (true == pHddCtx->hdd_wlan_suspended) {
14796 /* if wlan is suspended, enable GTK offload directly from here */
14797 memcpy(&hddGtkOffloadReqParams,
14798 &pHddStaCtx->gtkOffloadReqParams,
14799 sizeof(tSirGtkOffloadParams));
14800 status =
14801 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14802 pAdapter->sessionId);
14803
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014804 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014805 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014806 status);
14807 return -EINVAL;
14808 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014809 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014810 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014811 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014812 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014813 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014814 return result;
14815}
14816
14817/**
14818 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14819 * @wiphy: Pointer to wiphy
14820 * @dev: Pointer to network device
14821 * @data: Pointer to rekey data
14822 *
14823 * This function is used to offload GTK rekeying job to the firmware.
14824 *
14825 * Return: 0 for success, non-zero for failure
14826 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014827static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014828int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14829 struct net_device *dev,
14830 struct cfg80211_gtk_rekey_data *data)
14831{
14832 int ret;
14833
14834 cds_ssr_protect(__func__);
14835 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14836 cds_ssr_unprotect(__func__);
14837
14838 return ret;
14839}
14840#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14841
14842/**
14843 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14844 * @wiphy: Pointer to wiphy
14845 * @dev: Pointer to network device
14846 * @param: Pointer to access control parameter
14847 *
14848 * Return: 0 for success, non-zero for failure
14849 */
14850static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14851 struct net_device *dev,
14852 const struct cfg80211_acl_data *params)
14853{
14854 int i;
14855 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14856 hdd_hostapd_state_t *pHostapdState;
14857 tsap_Config_t *pConfig;
14858 v_CONTEXT_t p_cds_context = NULL;
14859 hdd_context_t *pHddCtx;
14860 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014861 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014862
14863 ENTER();
14864
Anurag Chouhan6d760662016-02-20 16:05:43 +053014865 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014866 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014867 return -EINVAL;
14868 }
14869
14870 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014871 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014872 return -EINVAL;
14873 }
14874
14875 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14876 status = wlan_hdd_validate_context(pHddCtx);
14877
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014878 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014879 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014880
14881 p_cds_context = pHddCtx->pcds_context;
14882 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14883
14884 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014885 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014886 return -EINVAL;
14887 }
14888
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014889 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014890 params->n_acl_entries);
14891
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014892 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014893 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14894 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014895 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014896 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14897
14898 /* default value */
14899 pConfig->num_accept_mac = 0;
14900 pConfig->num_deny_mac = 0;
14901
14902 /**
14903 * access control policy
14904 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14905 * listed in hostapd.deny file.
14906 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14907 * listed in hostapd.accept file.
14908 */
14909 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14910 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14911 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14912 params->acl_policy) {
14913 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14914 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014915 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014916 params->acl_policy);
14917 return -ENOTSUPP;
14918 }
14919
14920 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14921 pConfig->num_accept_mac = params->n_acl_entries;
14922 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014923 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14924 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014925 MAC_ADDR_ARRAY(
14926 params->mac_addrs[i].addr));
14927
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014928 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014929 params->mac_addrs[i].addr,
14930 sizeof(qcmacaddr));
14931 }
14932 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14933 pConfig->num_deny_mac = params->n_acl_entries;
14934 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014935 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14936 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014937 MAC_ADDR_ARRAY(
14938 params->mac_addrs[i].addr));
14939
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014940 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014941 params->mac_addrs[i].addr,
14942 sizeof(qcmacaddr));
14943 }
14944 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014945 qdf_status = wlansap_set_mac_acl(
14946 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014947 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014948 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014949 return -EINVAL;
14950 }
14951 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014952 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014953 hdd_device_mode_to_string(pAdapter->device_mode),
14954 pAdapter->device_mode);
14955 return -EINVAL;
14956 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014957 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014958 return 0;
14959}
14960
14961/**
14962 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14963 * __wlan_hdd_cfg80211_set_mac_acl
14964 * @wiphy: pointer to wiphy structure
14965 * @dev: pointer to net_device
14966 * @params: pointer to cfg80211_acl_data
14967 *
14968 * Return; 0 on success, error number otherwise
14969 */
14970static int
14971wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14972 struct net_device *dev,
14973 const struct cfg80211_acl_data *params)
14974{
14975 int ret;
14976
14977 cds_ssr_protect(__func__);
14978 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14979 cds_ssr_unprotect(__func__);
14980
14981 return ret;
14982}
14983
14984#ifdef WLAN_NL80211_TESTMODE
14985#ifdef FEATURE_WLAN_LPHB
14986/**
14987 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14988 * @pHddCtx: Pointer to hdd context
14989 * @lphbInd: Pointer to low power heart beat indication parameter
14990 *
14991 * Return: none
14992 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014993static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14994 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014995{
14996 struct sk_buff *skb;
14997
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014998 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014999
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015000 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015001 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015002
15003 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015004 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015005 return;
15006 }
15007
15008 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
15009 wiphy, sizeof(tSirLPHBInd),
15010 GFP_ATOMIC);
15011 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015012 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015013 return;
15014 }
15015
15016 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015017 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015018 goto nla_put_failure;
15019 }
15020 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015021 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015022 goto nla_put_failure;
15023 }
15024 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015025 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015026 goto nla_put_failure;
15027 }
15028 cfg80211_testmode_event(skb, GFP_ATOMIC);
15029 return;
15030
15031nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015032 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015033 kfree_skb(skb);
15034
15035 return;
15036}
15037#endif /* FEATURE_WLAN_LPHB */
15038
15039/**
15040 * __wlan_hdd_cfg80211_testmode() - test mode
15041 * @wiphy: Pointer to wiphy
15042 * @data: Data pointer
15043 * @len: Data length
15044 *
15045 * Return: 0 for success, non-zero for failure
15046 */
15047static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
15048 void *data, int len)
15049{
15050 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
15051 int err;
15052 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15053
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015054 ENTER();
15055
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015056 err = wlan_hdd_validate_context(pHddCtx);
15057 if (err)
15058 return err;
15059
15060 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
15061 len, wlan_hdd_tm_policy);
15062 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015063 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015064 return err;
15065 }
15066
15067 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015068 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015069 return -EINVAL;
15070 }
15071
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015072 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015073 TRACE_CODE_HDD_CFG80211_TESTMODE,
15074 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015075 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
15076#ifdef FEATURE_WLAN_LPHB
15077 /* Low Power Heartbeat configuration request */
15078 case WLAN_HDD_TM_CMD_WLAN_HB:
15079 {
15080 int buf_len;
15081 void *buf;
15082 tSirLPHBReq *hb_params = NULL;
15083 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015084 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015085
15086 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015087 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015088 return -EINVAL;
15089 }
15090
15091 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
15092 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
15093
15094 hb_params_temp = (tSirLPHBReq *) buf;
15095 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
15096 && (hb_params_temp->params.lphbTcpParamReq.
15097 timePeriodSec == 0))
15098 return -EINVAL;
15099
15100 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015101 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015102 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015103 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015104 return -ENOMEM;
15105 }
15106
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015107 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015108 smeStatus =
15109 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
15110 hb_params,
15111 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015112 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015113 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015114 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015115 }
15116 return 0;
15117 }
15118#endif /* FEATURE_WLAN_LPHB */
15119
15120#if defined(QCA_WIFI_FTM)
15121 case WLAN_HDD_TM_CMD_WLAN_FTM:
15122 {
15123 int buf_len;
15124 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015125 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015126 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015127 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015128 return -EINVAL;
15129 }
15130
15131 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
15132 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
15133
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015134 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015135
15136 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
15137
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015138 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015139 err = -EBUSY;
15140 break;
15141 }
15142#endif
15143
15144 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015145 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015146 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
15147 return -EOPNOTSUPP;
15148 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015149 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015150 return err;
15151}
15152
15153/**
15154 * wlan_hdd_cfg80211_testmode() - test mode
15155 * @wiphy: Pointer to wiphy
15156 * @dev: Pointer to network device
15157 * @data: Data pointer
15158 * @len: Data length
15159 *
15160 * Return: 0 for success, non-zero for failure
15161 */
15162static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
15163#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
15164 struct wireless_dev *wdev,
15165#endif
15166 void *data, int len)
15167{
15168 int ret;
15169
15170 cds_ssr_protect(__func__);
15171 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
15172 cds_ssr_unprotect(__func__);
15173
15174 return ret;
15175}
15176
15177#if defined(QCA_WIFI_FTM)
15178/**
15179 * wlan_hdd_testmode_rx_event() - test mode rx event handler
15180 * @buf: Pointer to buffer
15181 * @buf_len: Buffer length
15182 *
15183 * Return: none
15184 */
15185void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
15186{
15187 struct sk_buff *skb;
15188 hdd_context_t *hdd_ctx;
15189
15190 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015191 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015192 return;
15193 }
15194
Anurag Chouhan6d760662016-02-20 16:05:43 +053015195 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015196 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015197 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015198 return;
15199 }
15200
15201 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
15202 buf_len, GFP_KERNEL);
15203 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015204 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015205 return;
15206 }
15207
15208 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
15209 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
15210 goto nla_put_failure;
15211
Ryan Hsucfef0ae2016-04-28 10:20:46 -070015212 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015213
15214 cfg80211_testmode_event(skb, GFP_KERNEL);
15215 return;
15216
15217nla_put_failure:
15218 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015219 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015220}
15221#endif
15222#endif /* CONFIG_NL80211_TESTMODE */
15223
15224#ifdef QCA_HT_2040_COEX
15225/**
15226 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
15227 * @wiphy: Pointer to wiphy
15228 * @dev: Pointer to network device
15229 * @chandef: Pointer to channel definition parameter
15230 *
15231 * Return: 0 for success, non-zero for failure
15232 */
15233static int
15234__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
15235 struct net_device *dev,
15236 struct cfg80211_chan_def *chandef)
15237{
15238 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15239 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015240 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015241 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053015242 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015243
Anurag Chouhan6d760662016-02-20 16:05:43 +053015244 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015245 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015246 return -EINVAL;
15247 }
15248
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015249 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15250 hdd_err("invalid session id: %d", pAdapter->sessionId);
15251 return -EINVAL;
15252 }
15253
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015254 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15255 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053015256 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015257 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015258
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015259 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015260 sme_get_config_param(pHddCtx->hHal, &sme_config);
15261 switch (chandef->width) {
15262 case NL80211_CHAN_WIDTH_20:
15263 if (sme_config.csrConfig.channelBondingMode24GHz !=
15264 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
15265 sme_config.csrConfig.channelBondingMode24GHz =
15266 eCSR_INI_SINGLE_CHANNEL_CENTERED;
15267 sme_update_config(pHddCtx->hHal, &sme_config);
15268 cbModeChange = true;
15269 }
15270 break;
15271
15272 case NL80211_CHAN_WIDTH_40:
15273 if (sme_config.csrConfig.channelBondingMode24GHz ==
15274 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
15275 if (NL80211_CHAN_HT40MINUS ==
15276 cfg80211_get_chandef_type(chandef))
15277 sme_config.csrConfig.channelBondingMode24GHz =
15278 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
15279 else
15280 sme_config.csrConfig.channelBondingMode24GHz =
15281 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
15282 sme_update_config(pHddCtx->hHal, &sme_config);
15283 cbModeChange = true;
15284 }
15285 break;
15286
15287 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015288 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015289 return -EINVAL;
15290 }
15291
15292 if (!cbModeChange)
15293 return 0;
15294
Krunal Sonib4326f22016-03-10 13:05:51 -080015295 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015296 return 0;
15297
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015298 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015299 sme_config.csrConfig.channelBondingMode24GHz);
15300
15301 /* Change SAP ht2040 mode */
15302 status = hdd_set_sap_ht2040_mode(pAdapter,
15303 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015304 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015305 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015306 return -EINVAL;
15307 }
15308
15309 return 0;
15310}
15311
15312/**
15313 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
15314 * @wiphy: Pointer to wiphy
15315 * @dev: Pointer to network device
15316 * @chandef: Pointer to channel definition parameter
15317 *
15318 * Return: 0 for success, non-zero for failure
15319 */
15320static int
15321wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
15322 struct net_device *dev,
15323 struct cfg80211_chan_def *chandef)
15324{
15325 int ret;
15326
15327 cds_ssr_protect(__func__);
15328 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
15329 cds_ssr_unprotect(__func__);
15330
15331 return ret;
15332}
15333#endif
15334
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015335#ifdef CHANNEL_SWITCH_SUPPORTED
15336/**
15337 * __wlan_hdd_cfg80211_channel_switch()- function to switch
15338 * channel in SAP/GO
15339 * @wiphy: wiphy pointer
15340 * @dev: dev pointer.
15341 * @csa_params: Change channel params
15342 *
15343 * This function is called to switch channel in SAP/GO
15344 *
15345 * Return: 0 if success else return non zero
15346 */
15347static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15348 struct net_device *dev,
15349 struct cfg80211_csa_settings *csa_params)
15350{
15351 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
15352 hdd_context_t *hdd_ctx;
15353 uint8_t channel;
15354 uint16_t freq;
15355 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080015356 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015357
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015358 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015359 csa_params->chandef.chan->center_freq);
15360
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015361 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
15362 hdd_err("invalid session id: %d", adapter->sessionId);
15363 return -EINVAL;
15364 }
15365
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015366 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
15367 ret = wlan_hdd_validate_context(hdd_ctx);
15368
15369 if (0 != ret)
15370 return ret;
15371
Krunal Sonib4326f22016-03-10 13:05:51 -080015372 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
15373 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015374 return -ENOTSUPP;
15375
15376 freq = csa_params->chandef.chan->center_freq;
15377 channel = cds_freq_to_chan(freq);
15378
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053015379 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
15380
15381 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015382 return ret;
15383}
15384
15385/**
15386 * wlan_hdd_cfg80211_channel_switch()- function to switch
15387 * channel in SAP/GO
15388 * @wiphy: wiphy pointer
15389 * @dev: dev pointer.
15390 * @csa_params: Change channel params
15391 *
15392 * This function is called to switch channel in SAP/GO
15393 *
15394 * Return: 0 if success else return non zero
15395 */
15396static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15397 struct net_device *dev,
15398 struct cfg80211_csa_settings *csa_params)
15399{
15400 int ret;
15401
15402 cds_ssr_protect(__func__);
15403 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
15404 cds_ssr_unprotect(__func__);
15405 return ret;
15406}
15407#endif
15408
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015409/**
15410 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
15411 * translation from NL to policy manager type
15412 * @type: Generic connection mode type defined in NL
15413 *
15414 *
15415 * This function provides the type translation
15416 *
15417 * Return: cds_con_mode enum
15418 */
15419enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
15420 enum nl80211_iftype type)
15421{
15422 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
15423 switch (type) {
15424 case NL80211_IFTYPE_STATION:
15425 mode = CDS_STA_MODE;
15426 break;
15427 case NL80211_IFTYPE_P2P_CLIENT:
15428 mode = CDS_P2P_CLIENT_MODE;
15429 break;
15430 case NL80211_IFTYPE_P2P_GO:
15431 mode = CDS_P2P_GO_MODE;
15432 break;
15433 case NL80211_IFTYPE_AP:
15434 mode = CDS_SAP_MODE;
15435 break;
15436 case NL80211_IFTYPE_ADHOC:
15437 mode = CDS_IBSS_MODE;
15438 break;
15439 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015440 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015441 type);
15442 }
15443 return mode;
15444}
15445
15446/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015447 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15448 * @wiphy: Handle to struct wiphy to get handle to module context.
15449 * @chandef: Contains information about the capture channel to be set.
15450 *
15451 * This interface is called if and only if monitor mode interface alone is
15452 * active.
15453 *
15454 * Return: 0 success or error code on failure.
15455 */
15456static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15457 struct cfg80211_chan_def *chandef)
15458{
15459 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15460 hdd_adapter_t *adapter;
15461 hdd_station_ctx_t *sta_ctx;
15462 struct hdd_mon_set_ch_info *ch_info;
15463 QDF_STATUS status;
15464 tHalHandle hal_hdl;
15465 struct qdf_mac_addr bssid;
15466 tCsrRoamProfile roam_profile;
15467 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015468 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015469 int ret;
15470 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
15471
15472 ENTER();
15473
15474 ret = wlan_hdd_validate_context(hdd_ctx);
15475 if (ret)
15476 return ret;
15477
15478 hal_hdl = hdd_ctx->hHal;
15479
15480 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
15481 if (!adapter)
15482 return -EIO;
15483
15484 hdd_info("%s: set monitor mode Channel %d and freq %d",
15485 adapter->dev->name, chan_num, chandef->chan->center_freq);
15486
15487 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15488 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015489 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
15490 roam_profile.ChannelInfo.numOfChannels = 1;
15491 roam_profile.phyMode = ch_info->phy_mode;
15492 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015493 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015494
15495 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
15496 QDF_MAC_ADDR_SIZE);
15497
15498 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015499 /*
15500 * CDS api expects secondary channel for calculating
15501 * the channel params
15502 */
15503 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
15504 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
15505 if (chan_num >= 1 && chan_num <= 5)
15506 sec_ch = chan_num + 4;
15507 else if (chan_num >= 6 && chan_num <= 13)
15508 sec_ch = chan_num - 4;
15509 }
15510 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015511 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
15512 &roam_profile);
15513 if (status) {
15514 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
15515 status);
15516 ret = qdf_status_to_os_return(status);
15517 return ret;
15518 }
15519 EXIT();
15520 return 0;
15521}
15522
15523/**
15524 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15525 * @wiphy: Handle to struct wiphy to get handle to module context.
15526 * @chandef: Contains information about the capture channel to be set.
15527 *
15528 * This interface is called if and only if monitor mode interface alone is
15529 * active.
15530 *
15531 * Return: 0 success or error code on failure.
15532 */
15533static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15534 struct cfg80211_chan_def *chandef)
15535{
15536 int ret;
15537
15538 cds_ssr_protect(__func__);
15539 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
15540 cds_ssr_unprotect(__func__);
15541 return ret;
15542}
15543
15544/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015545 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
15546 * @adapter: pointer to adapter
15547 *
15548 * Wrapper function to clear link layer stats.
15549 * return - void
15550 */
15551void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
15552{
15553 tSirLLStatsClearReq link_layer_stats_clear_req;
15554 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
15555
Mukul Sharma491021c2016-09-29 21:39:19 +053015556 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
15557 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015558 link_layer_stats_clear_req.stopReq = 0;
15559 link_layer_stats_clear_req.reqId = 1;
15560 link_layer_stats_clear_req.staId = adapter->sessionId;
15561 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
15562
15563 return;
15564}
15565
15566/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015567 * struct cfg80211_ops - cfg80211_ops
15568 *
15569 * @add_virtual_intf: Add virtual interface
15570 * @del_virtual_intf: Delete virtual interface
15571 * @change_virtual_intf: Change virtual interface
15572 * @change_station: Change station
15573 * @add_beacon: Add beacon in sap mode
15574 * @del_beacon: Delete beacon in sap mode
15575 * @set_beacon: Set beacon in sap mode
15576 * @start_ap: Start ap
15577 * @change_beacon: Change beacon
15578 * @stop_ap: Stop ap
15579 * @change_bss: Change bss
15580 * @add_key: Add key
15581 * @get_key: Get key
15582 * @del_key: Delete key
15583 * @set_default_key: Set default key
15584 * @set_channel: Set channel
15585 * @scan: Scan
15586 * @connect: Connect
15587 * @disconnect: Disconnect
15588 * @join_ibss = Join ibss
15589 * @leave_ibss = Leave ibss
15590 * @set_wiphy_params = Set wiphy params
15591 * @set_tx_power = Set tx power
15592 * @get_tx_power = get tx power
15593 * @remain_on_channel = Remain on channel
15594 * @cancel_remain_on_channel = Cancel remain on channel
15595 * @mgmt_tx = Tx management frame
15596 * @mgmt_tx_cancel_wait = Cancel management tx wait
15597 * @set_default_mgmt_key = Set default management key
15598 * @set_txq_params = Set tx queue parameters
15599 * @get_station = Get station
15600 * @set_power_mgmt = Set power management
15601 * @del_station = Delete station
15602 * @add_station = Add station
15603 * @set_pmksa = Set pmksa
15604 * @del_pmksa = Delete pmksa
15605 * @flush_pmksa = Flush pmksa
15606 * @update_ft_ies = Update FT IEs
15607 * @tdls_mgmt = Tdls management
15608 * @tdls_oper = Tdls operation
15609 * @set_rekey_data = Set rekey data
15610 * @sched_scan_start = Scheduled scan start
15611 * @sched_scan_stop = Scheduled scan stop
15612 * @resume = Resume wlan
15613 * @suspend = Suspend wlan
15614 * @set_mac_acl = Set mac acl
15615 * @testmode_cmd = Test mode command
15616 * @set_ap_chanwidth = Set AP channel bandwidth
15617 * @dump_survey = Dump survey
15618 * @key_mgmt_set_pmk = Set pmk key management
15619 */
15620static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
15621 .add_virtual_intf = wlan_hdd_add_virtual_intf,
15622 .del_virtual_intf = wlan_hdd_del_virtual_intf,
15623 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
15624 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015625 .start_ap = wlan_hdd_cfg80211_start_ap,
15626 .change_beacon = wlan_hdd_cfg80211_change_beacon,
15627 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015628 .change_bss = wlan_hdd_cfg80211_change_bss,
15629 .add_key = wlan_hdd_cfg80211_add_key,
15630 .get_key = wlan_hdd_cfg80211_get_key,
15631 .del_key = wlan_hdd_cfg80211_del_key,
15632 .set_default_key = wlan_hdd_cfg80211_set_default_key,
15633 .scan = wlan_hdd_cfg80211_scan,
15634 .connect = wlan_hdd_cfg80211_connect,
15635 .disconnect = wlan_hdd_cfg80211_disconnect,
15636 .join_ibss = wlan_hdd_cfg80211_join_ibss,
15637 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
15638 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
15639 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
15640 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
15641 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
15642 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
15643 .mgmt_tx = wlan_hdd_mgmt_tx,
15644 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
15645 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
15646 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053015647 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015648 .get_station = wlan_hdd_cfg80211_get_station,
15649 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
15650 .del_station = wlan_hdd_cfg80211_del_station,
15651 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015652 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
15653 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
15654 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015655#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015656 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
15657#endif
15658#ifdef FEATURE_WLAN_TDLS
15659 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
15660 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
15661#endif
15662#ifdef WLAN_FEATURE_GTK_OFFLOAD
15663 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
15664#endif /* WLAN_FEATURE_GTK_OFFLOAD */
15665#ifdef FEATURE_WLAN_SCAN_PNO
15666 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
15667 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
15668#endif /*FEATURE_WLAN_SCAN_PNO */
15669 .resume = wlan_hdd_cfg80211_resume_wlan,
15670 .suspend = wlan_hdd_cfg80211_suspend_wlan,
15671 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
15672#ifdef WLAN_NL80211_TESTMODE
15673 .testmode_cmd = wlan_hdd_cfg80211_testmode,
15674#endif
15675#ifdef QCA_HT_2040_COEX
15676 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
15677#endif
15678 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015679#ifdef CHANNEL_SWITCH_SUPPORTED
15680 .channel_switch = wlan_hdd_cfg80211_channel_switch,
15681#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015682 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053015683#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
15684 defined(CFG80211_ABORT_SCAN)
15685 .abort_scan = wlan_hdd_cfg80211_abort_scan,
15686#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015687};